commit 3e00dac04bacb2dabe36a9e6b7aa7bba493c8c3d
parent 699d5e217911710d2a6f9989c62bc0115e535790
Author: thing1 <thing1@seacrossedlovers.xyz>
Date: Mon, 23 Mar 2026 15:12:12 +0000
got basic language down
next step is to do var checking
Diffstat:
| M | Makefile | | | 5 | ++++- |
| M | comp.h | | | 21 | +++++++++++++++++---- |
| M | comp.y | | | 52 | +++++++++++++++++++++++++++++++++++++++++----------- |
| M | lex.c | | | 59 | +++++++++++++++++++++++++++++++++++++++++++++++++++++------ |
4 files changed, 115 insertions(+), 22 deletions(-)
diff --git a/Makefile b/Makefile
@@ -6,7 +6,10 @@ y.tab.c: comp.y
yacc -td comp.y
comp.o: y.tab.c
- cc -DYYDEBUG y.tab.c -c -o comp.o ${CFLAGS}
+ cc -DYYALLOC -DYYDEBUG y.tab.c -c -o comp.o ${CFLAGS}
lex: lex.c comp.o
cc lex.c comp.o -o lex ${CFLAGS}
+
+clean:
+ rm -rf ./lex y.tab.h y.tab.c *.o
diff --git a/comp.h b/comp.h
@@ -1,16 +1,19 @@
+#include <stdio.h>
+#include <stdlib.h>
+
typedef struct Type Type;
typedef struct Func Func;
typedef struct Rhs Rhs;
typedef struct Expr Expr;
typedef struct Value Value;
+typedef struct Arg Arg;
typedef struct Func {
Type *type;
char *name;
- Type **argtypes;
- char **argnames;
+ Arg *args;
int argc;
- Expr **body;
+ Expr *body;
int exprc;
} Func;
@@ -52,7 +55,7 @@ typedef struct Expr {
} assign;
struct {
char *name;
- Rhs **args;
+ Rhs *args;
int argc;
} fcall;
};
@@ -98,3 +101,13 @@ typedef struct Value {
typedef struct Name {
char *name;
} Name;
+
+typedef struct List {
+ int count, size;
+ void *data;
+} List;
+
+typedef struct Arg {
+ char *name;
+ Type *type;
+} Arg;
diff --git a/comp.y b/comp.y
@@ -1,5 +1,6 @@
%{
#include <stdio.h>
+#include <stdlib.h>
#include "lex.h"
#include "comp.h"
@@ -8,8 +9,13 @@ extern int yylex();
void yyerror(const char *msg);
-#define NEW(x, v) x = malloc(sizeof(*x)); memcpy(x, &v, sizeof(v))
+Func magic = {0};
+
+#define NEW(x, v) x = malloc(sizeof(*x)); memcpy(x, &v, sizeof(v))
+#define APPEND(l, v) l->count++; \
+ l->data = (l->data) ? realloc(l->data, l->size * l->count) : malloc(l->size); \
+ memcpy(l->data + l->size * (l->count - 1), v, l->size);
%}
%union {
@@ -19,8 +25,11 @@ void yyerror(const char *msg);
Expr *expr;
Value *value;
Name *name;
+ Arg *arg;
struct Token *tok;
+
+ struct List *list;
}
%token FUNC
@@ -33,6 +42,10 @@ void yyerror(const char *msg);
%type <type> type
%type <rhs> rhs
%type <expr> expr
+%type <list> exprs
+%type <list> params
+%type <list> args
+%type <arg> arg
%type <value> value
%type <name> name
%type <tok> INT
@@ -49,18 +62,26 @@ prog : func
;
func : FUNC name '(' args ')' type
- '{' exprs '}'
- | FUNC name '(' ')' type
- '{' exprs '}'
+ '{' exprs '}' { NEW($$, ((Func){.type = $6, .args = (Arg *)$4->data, .argc = $4->count, .name = $2->name, .body = (Expr *)$8->data, .exprc = $8->count})); }
+ | FUNC name '(' ')' type
+ '{' exprs '}' { NEW($$, ((Func){.type = $5, .name = $2->name, .body = (Expr *)$7->data, .exprc = $7->count})); magic = *$$;}
;
name : NAME { NEW($$, ((Name){.name = $1->data})); }
;
-args : name
- | args ',' name
+args : arg {
+ NEW($$, ((List){.size = sizeof(Arg), .count = 0, .data = NULL}));
+ APPEND($$, $1);
+ }
+ | args ',' arg {
+ APPEND($1, $3);
+ $$ = $1;
+ }
;
+arg : name type { NEW($$, ((Arg){.name = $1->name, .type = $2})); }
+
type : NAME {
enum Types ty = 0;
switch (((char *)$1->data)[0]) {
@@ -84,16 +105,25 @@ type : NAME {
}
;
-exprs : expr ';'
- | exprs expr ';'
+exprs : expr ';' {
+ NEW($$, ((List){.size = sizeof(Expr), .count = 0, .data = NULL}));
+ APPEND($$, $1);
+ }
+ | exprs expr ';' { APPEND($1, $2); }
;
-expr : name '(' params ')' { NEW($$, ((Expr){.expr = FCALL_EXPR, .fcall.name = $1->name})); }
+expr : name '(' params ')' { NEW($$, ((Expr){.expr = FCALL_EXPR, .fcall.name = $1->name, .fcall.args = (Rhs *)$3->data, .fcall.argc = $3->count})); }
| VAR name type '=' rhs { NEW($$, ((Expr){.expr = ASSIGN, .assign.type = $3, .assign.name = $2->name, .assign.rhs = $5})); }
;
-params : rhs
- | params ',' rhs
+params : rhs {
+ NEW($$, ((List){.size = sizeof(Rhs), .count = 0, .data = NULL}));
+ APPEND($$, $1);
+ }
+ | params ',' rhs {
+ APPEND($1, $3);
+ $$ = $1;
+ }
;
rhs : value { NEW($$, ((Rhs){.rhs = VALUE, .value = $1})); }
diff --git a/lex.c b/lex.c
@@ -29,12 +29,14 @@ struct Lexer {
struct Token Gtoken;
struct Token lex_func();
+struct Token lex_var();
struct Token lex_name();
struct Token lex_obrace();
struct Token lex_cbrace();
struct Token lex_ocbrace();
struct Token lex_ccbrace();
struct Token lex_semi();
+struct Token lex_assign();
struct Token lex_int();
struct Token lex_add();
struct Token lex_sub();
@@ -103,14 +105,25 @@ struct Token lex_char(char c) {
struct Token lex_func() {
struct Pos start = lex.pos;
- if (memcmp(lex.input, "func", 4) != 0)
- llerror("Expected func!");
- move(4);
+ if (memcmp(lex.input, "func ", 5) != 0)
+ llerror("Expected 'func'!");
+ move(5);
lex.f = &lex_name;
LEXRET(((struct Token){start, FUNC, NULL, NULL}));
}
+struct Token lex_var() {
+ struct Pos start = lex.pos;
+
+ if (memcmp(lex.input, "var ", 4) != 0)
+ llerror("Expected 'var'!");
+ move(4);
+
+ lex.f = &lex_name;
+ LEXRET(((struct Token){start, VAR, NULL, NULL}));
+}
+
struct Token lex_name() {
struct Pos start = lex.pos;
@@ -128,7 +141,12 @@ struct Token lex_name() {
case '*': lex.f = &lex_mul; break;
case '/': lex.f = &lex_div; break;
case ',': lex.f = &lex_comma; break;
- default: llerror("Unexpected token!");
+ case '=': lex.f = &lex_assign; break;
+ default:
+ if (lasttok.type == VAR)
+ lex.f = &lex_name;
+ else
+ llerror("Unexpected token!");
}
LEXRET(t);
@@ -164,6 +182,7 @@ struct Token lex_int() {
case '*': lex.f = &lex_mul; break;
case '/': lex.f = &lex_div; break;
case ',': lex.f = &lex_comma; break;
+ case ';': lex.f = &lex_semi; break;
default: llerror("Unexpected token!");
}
@@ -173,7 +192,12 @@ struct Token lex_int() {
struct Token lex_ocbrace() {
struct Token t = lex_char('{');
switch (peek()) {
- default: lex.f = &lex_name; break;
+ default:
+ if (memcmp(lex.input, "var ", 4) == 0)
+ lex.f = &lex_var;
+ else
+ lex.f = &lex_name;
+ break;
}
LEXRET(t);
}
@@ -213,6 +237,21 @@ struct Token lex_semi() {
LEXRET(t);
}
+struct Token lex_assign() {
+ struct Token t = lex_char('=');
+
+ switch (peek()) {
+ case '(': lex.f = &lex_obrace; break;
+ default:
+ lex.f = (isdigit(peek())) ? &lex_int : &lex_name;
+ break;
+ }
+
+ LEXRET(t);
+}
+
+
+
struct Token lex_comma() {
struct Token t = lex_char(',');
@@ -251,7 +290,15 @@ int yylex() {
return lex.f().type;
}
+extern Func magic;
+
int main() {
- lex = (struct Lexer){(struct Pos){0, 0}, "func f() i32 {\n\tg((1 + 5) * 2);\nh(3, 5);\n}", &lex_func};
+ lex = (struct Lexer){(struct Pos){0, 0},
+ "func f() v { \n\
+ var a v = 4; \n\
+ g((1 + 5) * 2); \n\
+ h(3, 5); \n\
+ }",
+ &lex_func};
yyparse();
}