simple poc
This commit is contained in:
parent
309366ab72
commit
dccb717812
15
Makefile
Normal file
15
Makefile
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
CXX := g++
|
||||||
|
CXXFLAGS := -std=c++17 -Wall -Wextra -O2
|
||||||
|
|
||||||
|
SRCS := $(wildcard src/*.cpp)
|
||||||
|
BIN := minilua
|
||||||
|
|
||||||
|
all: $(BIN)
|
||||||
|
|
||||||
|
$(BIN): $(SRCS)
|
||||||
|
$(CXX) $(CXXFLAGS) $^ -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(BIN)
|
||||||
|
|
||||||
|
.PHONY: all clean
|
7
main.lua
Normal file
7
main.lua
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
local x = 10
|
||||||
|
|
||||||
|
function main()
|
||||||
|
print("Hello: " .. x + 12)
|
||||||
|
end
|
||||||
|
|
||||||
|
main()
|
221
src/main.cpp
Normal file
221
src/main.cpp
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#define MAX_TOKENS 1024
|
||||||
|
#define MAX_SOURCE 65536
|
||||||
|
#define MAX_STACK 256
|
||||||
|
#define MAX_VARS 256
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
T_EOF, T_NUMBER, T_STRING, T_IDENT,
|
||||||
|
T_PLUS, T_MINUS, T_MUL, T_DIV, T_EQ,
|
||||||
|
T_LPAREN, T_RPAREN, T_LBRACE, T_RBRACE,
|
||||||
|
T_IF, T_WHILE, T_FUNCTION, T_RETURN,
|
||||||
|
T_SEMI, T_COMMA, T_ASSIGN, T_PRINT
|
||||||
|
} TokenType;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
TokenType type;
|
||||||
|
char text[64];
|
||||||
|
} Token;
|
||||||
|
|
||||||
|
char* source;
|
||||||
|
Token tokens[MAX_TOKENS];
|
||||||
|
int tok_index = 0, tok_count = 0;
|
||||||
|
|
||||||
|
void error(const char* msg) {
|
||||||
|
fprintf(stderr, "Error: %s\n", msg);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void next_token() { if (tok_index < tok_count) tok_index++; }
|
||||||
|
Token* current_token() { return &tokens[tok_index]; }
|
||||||
|
|
||||||
|
void tokenize() {
|
||||||
|
char* s = source;
|
||||||
|
while (*s) {
|
||||||
|
while (isspace(*s)) s++;
|
||||||
|
if (!*s) break;
|
||||||
|
|
||||||
|
if (isdigit(*s)) {
|
||||||
|
Token t = {};
|
||||||
|
t.type = T_NUMBER;
|
||||||
|
int len = 0;
|
||||||
|
while (isdigit(*s)) t.text[len++] = *s++;
|
||||||
|
t.text[len] = '\0';
|
||||||
|
tokens[tok_count++] = t;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isalpha(*s) || *s == '_') {
|
||||||
|
Token t = {};
|
||||||
|
t.type = T_IDENT;
|
||||||
|
int len = 0;
|
||||||
|
while (isalnum(*s) || *s == '_') t.text[len++] = *s++;
|
||||||
|
t.text[len] = '\0';
|
||||||
|
|
||||||
|
if (strcmp(t.text, "if") == 0) t.type = T_IF;
|
||||||
|
else if (strcmp(t.text, "while") == 0) t.type = T_WHILE;
|
||||||
|
else if (strcmp(t.text, "function") == 0) t.type = T_FUNCTION;
|
||||||
|
else if (strcmp(t.text, "return") == 0) t.type = T_RETURN;
|
||||||
|
else if (strcmp(t.text, "print") == 0) t.type = T_PRINT;
|
||||||
|
|
||||||
|
tokens[tok_count++] = t;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*s == '"') {
|
||||||
|
Token t = {};
|
||||||
|
t.type = T_STRING;
|
||||||
|
s++;
|
||||||
|
int len = 0;
|
||||||
|
while (*s && *s != '"') t.text[len++] = *s++;
|
||||||
|
if (*s == '"') s++;
|
||||||
|
t.text[len] = '\0';
|
||||||
|
tokens[tok_count++] = t;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (*s) {
|
||||||
|
case '+': tokens[tok_count++] = Token{ T_PLUS, "+" }; s++; break;
|
||||||
|
case '-': tokens[tok_count++] = Token{ T_MINUS, "-" }; s++; break;
|
||||||
|
case '*': tokens[tok_count++] = Token{ T_MUL, "*" }; s++; break;
|
||||||
|
case '/': tokens[tok_count++] = Token{ T_DIV, "/" }; s++; break;
|
||||||
|
case '=': tokens[tok_count++] = Token{ T_ASSIGN, "=" }; s++; break;
|
||||||
|
case ';': tokens[tok_count++] = Token{ T_SEMI, ";" }; s++; break;
|
||||||
|
case ',': tokens[tok_count++] = Token{ T_COMMA, "," }; s++; break;
|
||||||
|
case '(': tokens[tok_count++] = Token{ T_LPAREN, "(" }; s++; break;
|
||||||
|
case ')': tokens[tok_count++] = Token{ T_RPAREN, ")" }; s++; break;
|
||||||
|
case '{': tokens[tok_count++] = Token{ T_LBRACE, "{" }; s++; break;
|
||||||
|
case '}': tokens[tok_count++] = Token{ T_RBRACE, "}" }; s++; break;
|
||||||
|
default: error("Unknown character");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Token eof = {};
|
||||||
|
eof.type = T_EOF;
|
||||||
|
tokens[tok_count++] = eof;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char name[32];
|
||||||
|
int value;
|
||||||
|
} Variable;
|
||||||
|
|
||||||
|
Variable vars[MAX_VARS];
|
||||||
|
int var_count = 0;
|
||||||
|
|
||||||
|
int get_var(const char* name) {
|
||||||
|
for (int i = 0; i < var_count; i++) {
|
||||||
|
if (strcmp(vars[i].name, name) == 0)
|
||||||
|
return vars[i].value;
|
||||||
|
}
|
||||||
|
error("Undefined variable");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_var(const char* name, int value) {
|
||||||
|
for (int i = 0; i < var_count; i++) {
|
||||||
|
if (strcmp(vars[i].name, name) == 0) {
|
||||||
|
vars[i].value = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
strcpy(vars[var_count].name, name);
|
||||||
|
vars[var_count++].value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int eval_expr();
|
||||||
|
|
||||||
|
int eval_factor() {
|
||||||
|
Token* t = current_token();
|
||||||
|
if (t->type == T_NUMBER) {
|
||||||
|
int val = atoi(t->text);
|
||||||
|
next_token();
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
if (t->type == T_IDENT) {
|
||||||
|
int val = get_var(t->text);
|
||||||
|
next_token();
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
error("Invalid factor");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int eval_term() {
|
||||||
|
int val = eval_factor();
|
||||||
|
Token* t = current_token();
|
||||||
|
while (t->type == T_MUL || t->type == T_DIV) {
|
||||||
|
TokenType op = t->type;
|
||||||
|
next_token();
|
||||||
|
int rhs = eval_factor();
|
||||||
|
if (op == T_MUL) val *= rhs;
|
||||||
|
else val /= rhs;
|
||||||
|
t = current_token();
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
int eval_expr() {
|
||||||
|
int val = eval_term();
|
||||||
|
Token* t = current_token();
|
||||||
|
while (t->type == T_PLUS || t->type == T_MINUS) {
|
||||||
|
TokenType op = t->type;
|
||||||
|
next_token();
|
||||||
|
int rhs = eval_term();
|
||||||
|
if (op == T_PLUS) val += rhs;
|
||||||
|
else val -= rhs;
|
||||||
|
t = current_token();
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute() {
|
||||||
|
while (current_token()->type != T_EOF) {
|
||||||
|
Token* t = current_token();
|
||||||
|
if (t->type == T_IDENT) {
|
||||||
|
char varname[32];
|
||||||
|
strcpy(varname, t->text);
|
||||||
|
next_token();
|
||||||
|
if (current_token()->type == T_ASSIGN) {
|
||||||
|
next_token();
|
||||||
|
int val = eval_expr();
|
||||||
|
set_var(varname, val);
|
||||||
|
}
|
||||||
|
} else if (t->type == T_PRINT) {
|
||||||
|
next_token();
|
||||||
|
int val = eval_expr();
|
||||||
|
printf("%d\n", val);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_token()->type == T_SEMI)
|
||||||
|
next_token();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_file(const char* filename) {
|
||||||
|
FILE* f = fopen(filename, "rb");
|
||||||
|
if (!f) {
|
||||||
|
perror("fopen");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
source = (char*)malloc(MAX_SOURCE);
|
||||||
|
fread(source, 1, MAX_SOURCE, f);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
if (argc < 2) {
|
||||||
|
printf("Usage: minilua <file.lua>\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
load_file(argv[1]);
|
||||||
|
tokenize();
|
||||||
|
execute();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user