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