fela

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 90adebdb52dd7d28cfee75fed2be824504deeda7
Author: thing1 <thing1@seacrossedlovers.xyz>
Date:   Tue, 21 Oct 2025 21:03:14 +0100

init commit

Diffstat:
A.gitignore | 5+++++
AMakefile | 19+++++++++++++++++++
Aast.h | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Afela | 0
Afela.l | 11+++++++++++
Afela.y | 165+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest.fe | 4++++
Autil.h | 15+++++++++++++++
8 files changed, 271 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,5 @@ +lex.yy.c +y.gv +*.pdf +y.tab.c +y.tab.h diff --git a/Makefile b/Makefile @@ -0,0 +1,19 @@ +YFLAGS=-g +CFLAGS=-ggdb +LIBS=-lfl + +all: fela + +lexer: fela.l + lex fela.l + +parser: fela.y + yacc -d ${YFLAGS} fela.y + dot y.gv -Tpdf > g.pdf + +fela: lexer parser + cc lex.yy.c y.tab.c -o fela ${LIBS} ${CFLAGS} + +clean: + rm -rf lex.yy.* y.* fela *.html *.pdf + diff --git a/ast.h b/ast.h @@ -0,0 +1,52 @@ +enum ast_type { + DEC, + EXPR, +}; + +enum expr_ops { + VALUE, + VAR, + ADD, + SUB, + DIV, + MUL, + NESTED, + FUNCTION, +}; + +struct ast_expr { + enum expr_ops op; + char *fn; + union { + struct { + int child_count; + struct ast_expr *children; + }; + struct { + struct ast_exprs *exprs; + struct ast_decs *decs; + }; + long value; + }; +}; + +struct ast_exprs { + struct ast_exprs *exprs; + struct ast_expr *expr; +}; + + +struct ast_dec { + char *name; + struct ast_expr *value; +}; + +struct ast_decs { + struct ast_decs *decs; + struct ast_dec *dec; +}; + +typedef struct ast { + struct ast_decs *decs; + struct ast_exprs *exprs; +} ast; diff --git a/fela b/fela Binary files differ. diff --git a/fela.l b/fela.l @@ -0,0 +1,11 @@ +%{ +#include "y.tab.h" +%} + +%% +"func" { return FUNC; } +[0-9]+ { yylval.l = atol(yytext); return NUMBER; } +[A-z][A-z0-9]* { yylval.s = yytext; return NAME; } +[;=+\-*/\{\}\(\)\[\]] { return yytext[0]; } +[ \t\n] {;} +%% diff --git a/fela.y b/fela.y @@ -0,0 +1,165 @@ +%{ +#include <stdio.h> +#include <stdlib.h> + +#include "ast.h" +#include "util.h" + +#define YYDEBUG 1 + +extern char *yytext; +extern int yylex(); +int yyerror(const char *); +%} + +%union { + struct ast *tree; + struct ast_dec *dec; + struct ast_expr *expr; + struct ast_decs *decs; + struct ast_exprs *exprs; + struct func *func; + + char *s; + long l; +} + +%token <s> NAME +%token <l> NUMBER +%token FUNC + +%type <tree> body +%type <expr> expr +%type <expr> func +%type <exprs> exprs +%type <dec> dec +%type <decs> decs + + +%left '+' '-' +%left '*' '/' +%left '(' ')' + +%% + +body : decs { + $$ = alloczt(struct ast); + $$->decs = $1; + } + ; + +decs : decs dec ';' { + $$ = alloczt(struct ast_decs); + $$->decs = $1; + $$->dec = $2; + } + | dec ';' { + $$ = alloczt(struct ast_decs); + $$->dec = $1; + } + ; + + +dec : NAME NAME { + $$ = alloczt(struct ast_dec); + $$->name = strdup($2); + } + | NAME NAME '=' expr { + $$ = alloczt(struct ast_dec); + $$->name = strdup($2); + $$->value = $4; + } + | NAME NAME '=' func { + $$ = alloczt(struct ast_dec); + $$->value = $4; + } + + ; + +exprs : exprs expr ';' { + $$ = alloczt(struct ast_exprs); + $$->exprs = $1; + $$->expr = $2; + } + | expr ';' { + $$ = alloczt(struct ast_exprs); + $$->expr = $1; + } + ; + +func : FUNC '(' ')' '{' decs exprs '}' { + $$ = alloczt(struct ast_expr); + $$->op = FUNCTION; + $$->decs = $5; + $$->exprs = $6; + } +func : FUNC '(' ')' '{' exprs '}' { + $$ = alloczt(struct ast_expr); + $$->op = FUNCTION; + $$->exprs = $5; + } + ; + +expr : expr '+' expr { + $$ = alloczt(struct ast_expr); + $$->op = ADD; + $$->children = allocztn(struct ast_expr, 2); + $$->children[0] = *$1; + $$->children[1] = *$3; + } + | expr '-' expr { + $$ = alloczt(struct ast_expr); + $$->op = SUB; + $$->children = allocztn(struct ast_expr, 2); + $$->children[0] = *$1; + $$->children[1] = *$3; + } + | expr '/' expr { + $$ = alloczt(struct ast_expr); + $$->op = DIV; + $$->children = allocztn(struct ast_expr, 2); + $$->children[0] = *$1; + $$->children[1] = *$3; + } + | expr '*' expr { + $$ = alloczt(struct ast_expr); + $$->op = MUL; + $$->children = allocztn(struct ast_expr, 2); + $$->children[0] = *$1; + $$->children[1] = *$3; + } + | '(' expr ')' { + $$ = alloczt(struct ast_expr); + $$->op = NESTED; + $$->children = alloczt(struct ast_expr); + $$->children[0] = *$2; + $$->child_count++; + } + | NUMBER { + $$ = alloczt(struct ast_expr); + $$->op = VALUE; + $$->value = $1; + } + | NAME { + $$ = alloczt(struct ast_expr); + $$->op = VAR; + $$->fn = $1; + } + | NAME '(' ')' { + $$ = alloczt(struct ast_expr); + $$->op = FUNC; + $$->fn = $1; + } + ; +%% + +int +yyerror(const char *msg) { + fprintf(stderr, "err: \'%s\', %s\n", yytext, msg); + return 1; +} + +int +main() { + yyparse(); +} diff --git a/test.fe b/test.fe @@ -0,0 +1,4 @@ +byte num = func() { + int a = 0; + rand(); +}; diff --git a/util.h b/util.h @@ -0,0 +1,15 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#define allocztn(type, n) allocz(sizeof(type) * n) +#define alloczt(type) allocz(sizeof(type)) + +void * +allocz(const size_t size) { + void *p = malloc(size); + memset(p, 0, size); + return p; +} + +/* TODO make this allocate to an arena that can be freed */