simple poc

This commit is contained in:
OusmBlueNinja 2025-04-11 11:46:02 -05:00
parent 309366ab72
commit dccb717812
3 changed files with 243 additions and 0 deletions

15
Makefile Normal file
View 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
View File

@ -0,0 +1,7 @@
local x = 10
function main()
print("Hello: " .. x + 12)
end
main()

221
src/main.cpp Normal file
View 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;
}