commit 699d5e217911710d2a6f9989c62bc0115e535790
parent 119b3d86b933c4ad97d529501e089eab788b1c13
Author: thing1 <thing1@seacrossedlovers.xyz>
Date: Sun, 22 Mar 2026 19:37:25 +0000
started constructing the tree
Diffstat:
| M | Makefile | | | 2 | +- |
| M | comp.h | | | 26 | ++++++++++++++++---------- |
| M | comp.y | | | 103 | +++++++++++++++++++++++++++++++++++++------------------------------------------ |
| M | lex.c | | | 46 | +++++++++++++++++++++++++++++++++++----------- |
4 files changed, 100 insertions(+), 77 deletions(-)
diff --git a/Makefile b/Makefile
@@ -3,7 +3,7 @@ CFLAGS=-ggdb
all: lex
y.tab.c: comp.y
- yacc -ytd comp.y
+ yacc -td comp.y
comp.o: y.tab.c
cc -DYYDEBUG y.tab.c -c -o comp.o ${CFLAGS}
diff --git a/comp.h b/comp.h
@@ -15,18 +15,20 @@ typedef struct Func {
} Func;
enum Types {
- I8,
- I16,
- I32,
- I64,
+ I8 = 1,
+ I16 = 2,
+ I32 = 4,
+ I64 = 8,
- U8,
- U16,
- U32,
- U64,
+ U8 = I8 | 16,
+ U16 = I16 | 16,
+ U32 = I32 | 16,
+ U64 = I64 | 16,
- F32,
- F64,
+ F32 = I32 | 32,
+ F64 = I64 | 32,
+
+ VOID = 64,
COMPLEX,
};
@@ -92,3 +94,7 @@ typedef struct Value {
long long int lval;
double dval;
} Value;
+
+typedef struct Name {
+ char *name;
+} Name;
diff --git a/comp.y b/comp.y
@@ -8,6 +8,8 @@ extern int yylex();
void yyerror(const char *msg);
+#define NEW(x, v) x = malloc(sizeof(*x)); memcpy(x, &v, sizeof(v))
+
%}
%union {
@@ -16,19 +18,26 @@ void yyerror(const char *msg);
Rhs *rhs;
Expr *expr;
Value *value;
+ Name *name;
+
+ struct Token *tok;
}
%token FUNC
+%token VAR
%token NAME
%token INT
%token FLOAT
%type <func> func
%type <type> type
-%type <rhs> name
%type <rhs> rhs
%type <expr> expr
%type <value> value
+%type <name> name
+%type <tok> INT
+%type <tok> FLOAT
+%type <tok> NAME
%left '(' ')'
%left '*' '/'
@@ -39,81 +48,65 @@ prog : func
| prog func
;
-func : FUNC name '(' args ')' type '{' exprs '}'
- | FUNC name '(' ')' type '{' exprs '}'
+func : FUNC name '(' args ')' type
+ '{' exprs '}'
+ | FUNC name '(' ')' type
+ '{' exprs '}'
;
-name : NAME
+name : NAME { NEW($$, ((Name){.name = $1->data})); }
;
args : name
| args ',' name
;
-type : NAME
+type : NAME {
+ enum Types ty = 0;
+ switch (((char *)$1->data)[0]) {
+ case 'i': break;
+ case 'u': ty |= 16; break;
+ case 'f': ty |= 32; break;
+ case 'v': ty = 64; goto void_type;
+ default: yyerror("Invalid type");
+ }
+
+ switch (((char *)$1->data)[1]) {
+ case '8': ty = 1; break;
+ case '1': ty = 2; break;
+ case '3': ty = 4; break;
+ case '6': ty = 8; break;
+ default: yyerror("Invalid type size");
+ }
+
+ void_type:
+ NEW($$, ((Type){.type = ty}));
+ }
;
exprs : expr ';'
| exprs expr ';'
;
-expr : name '(' params ')'
- | type name '=' rhs
+expr : name '(' params ')' { NEW($$, ((Expr){.expr = FCALL_EXPR, .fcall.name = $1->name})); }
+ | VAR name type '=' rhs { NEW($$, ((Expr){.expr = ASSIGN, .assign.type = $3, .assign.name = $2->name, .assign.rhs = $5})); }
;
params : rhs
- | params ',' rhs
+ | params ',' rhs
;
-rhs : value
- | name '(' params ')' {
- $$ = malloc(sizeof(Rhs));
- $$->rhs = FCALL_RHS;
- $$->fcall.name = $1;
- }
- | rhs '+' rhs {
- $$ = malloc(sizeof(Rhs));
- $$->rhs = MATH;
- $$->math.op = ADD;
- $$->math.lhs = $1
- $$->math.rhs = $3;
- }
- | rhs '-' rhs {
- $$ = malloc(sizeof(Rhs));
- $$->rhs = MATH;
- $$->math.op = SUB;
- $$->math.lhs = $1
- $$->math.rhs = $3;
- }
- | rhs '*' rhs {
- $$ = malloc(sizeof(Rhs));
- $$->rhs = MATH;
- $$->math.op = MUL;
- $$->math.lhs = $1
- $$->math.rhs = $3;
- }
- | rhs '/' rhs {
- $$ = malloc(sizeof(Rhs));
- $$->rhs = MATH;
- $$->math.op = DIV;
- $$->math.lhs = $1
- $$->math.rhs = $3;
- }
- | '(' rhs ')' {
- $$ = malloc(sizeof(Rhs));
- $$->rhs = BRACE;
- $$->brace = $2;
- }
+rhs : value { NEW($$, ((Rhs){.rhs = VALUE, .value = $1})); }
+ | name '(' params ')' { NEW($$, ((Rhs){.rhs = FCALL_RHS, .fcall.name = $1->name})); }
+ | rhs '+' rhs { NEW($$, ((Rhs){.rhs = MATH, .math.op = ADD, .math.lhs = $1, .math.rhs = $3}));}
+ | rhs '-' rhs { NEW($$, ((Rhs){.rhs = MATH, .math.op = SUB, .math.lhs = $1, .math.rhs = $3}));}
+ | rhs '*' rhs { NEW($$, ((Rhs){.rhs = MATH, .math.op = MUL, .math.lhs = $1, .math.rhs = $3}));}
+ | rhs '/' rhs { NEW($$, ((Rhs){.rhs = MATH, .math.op = DIV, .math.lhs = $1, .math.rhs = $3}));}
+ | '(' rhs ')' { NEW($$, ((Rhs){.rhs = BRACE, .brace = $2})); }
;
-value : INT {
- $$ = malloc(sizeof(Value));
- memcpy($$, &(Value){atoll(lasttok.data), 0}, sizeof(Value));
- }
- | FLOAT {
- $$ = malloc(sizeof(Value));
- memcpy($$, &(Value){0, atof(lasttok.data)}, sizeof(Value));
- }
+value : INT { NEW($$, ((Value){.lval = atoll($1->data)})); }
+ | FLOAT { NEW($$, ((Value){.dval = atof($1->data)})); }
;
%%
diff --git a/lex.c b/lex.c
@@ -5,7 +5,7 @@
#include "comp.h"
#include "y.tab.h"
-#define LEXRET(t) lasttok = (t); return (t);
+#define LEXRET(t) memcpy(&Gtoken, &(t), sizeof((t))); yylval.tok = &Gtoken; lasttok = (t); return (t);
extern void yyerror(const char *msg);
@@ -26,6 +26,8 @@ struct Lexer {
struct Token (*f)();
};
+struct Token Gtoken;
+
struct Token lex_func();
struct Token lex_name();
struct Token lex_obrace();
@@ -44,6 +46,28 @@ struct Lexer lex = {0};
struct Token lasttok = {0};
+void llerror(const char *msg) {
+ char *terms = ",{};";
+ char *first = NULL, *new;
+ do {
+ new = strchr(lex.input, *terms);
+ if (!first) first = new;
+ if (new && new < first)
+ first = new;
+ } while (*(terms++) && new);
+
+ yyerror(msg);
+ if (!first) exit(1);
+ lex.input = first;
+
+ switch (lex.input[0]) {
+ case '{': lex.f = lex_ocbrace; break;
+ case '}': lex.f = lex_ccbrace; break;
+ case ',': lex.f = lex_comma; break;
+ case ';': lex.f = lex_semi; break;
+ }
+}
+
void move(int off) {
lex.input += off;
lex.pos.col += off;
@@ -69,7 +93,7 @@ struct Token lex_char(char c) {
struct Pos start = lex.pos;
if (lex.input[0] != c)
- yyerror("Expected different char");
+ llerror("Expected different char");
move(1);
skip();
@@ -80,7 +104,7 @@ struct Token lex_func() {
struct Pos start = lex.pos;
if (memcmp(lex.input, "func", 4) != 0)
- yyerror("Expected func!");
+ llerror("Expected func!");
move(4);
lex.f = &lex_name;
@@ -91,7 +115,7 @@ struct Token lex_name() {
struct Pos start = lex.pos;
if (!isalpha(lex.input[0]))
- yyerror("Expected name!");
+ llerror("Expected name!");
struct Token t = {start, NAME, lex.input, lex.input + 1};
move(1);
@@ -104,7 +128,7 @@ struct Token lex_name() {
case '*': lex.f = &lex_mul; break;
case '/': lex.f = &lex_div; break;
case ',': lex.f = &lex_comma; break;
- default: yyerror("Unexpected token!");
+ default: llerror("Unexpected token!");
}
LEXRET(t);
@@ -118,7 +142,7 @@ struct Token lex_obrace() {
case '(': lex.f = &lex_obrace; break;
default:
if (isdigit(peek())) lex.f = &lex_int;
- else yyerror("Unexpected token!");
+ else llerror("Unexpected token!");
}
LEXRET(t);
@@ -128,7 +152,7 @@ struct Token lex_int() {
struct Pos start = lex.pos;
if (!isdigit(lex.input[0]))
- yyerror("Expected number!");
+ llerror("Expected number!");
struct Token t = {start, INT, lex.input, lex.input + 1};
move(1);
@@ -140,7 +164,7 @@ struct Token lex_int() {
case '*': lex.f = &lex_mul; break;
case '/': lex.f = &lex_div; break;
case ',': lex.f = &lex_comma; break;
- default: yyerror("Unexpected token!");
+ default: llerror("Unexpected token!");
}
LEXRET(t);
@@ -198,7 +222,7 @@ struct Token lex_comma() {
lex.f = &lex_name;
else switch (peek()) {
case '(': lex.f = &lex_obrace; break;
- default: yyerror("Unexpeced token!");
+ default: llerror("Unexpeced token!");
}
LEXRET(t);
@@ -212,7 +236,7 @@ struct Token lex_comma() {
lex.f = &lex_int; \
else if (isalpha(peek())) \
lex.f = &lex_name; \
- else yyerror("Unexpeced token!"); \
+ else llerror("Unexpeced token!"); \
LEXRET(t); \
}
@@ -228,6 +252,6 @@ int yylex() {
}
int main() {
- lex = (struct Lexer){(struct Pos){0, 0}, "func f() v {\n\tg((1 + 5) * 2);\nh(3, 5);\n}", &lex_func};
+ lex = (struct Lexer){(struct Pos){0, 0}, "func f() i32 {\n\tg((1 + 5) * 2);\nh(3, 5);\n}", &lex_func};
yyparse();
}