commit 90adebdb52dd7d28cfee75fed2be824504deeda7
Author: thing1 <thing1@seacrossedlovers.xyz>
Date: Tue, 21 Oct 2025 21:03:14 +0100
init commit
Diffstat:
| A | .gitignore | | | 5 | +++++ |
| A | Makefile | | | 19 | +++++++++++++++++++ |
| A | ast.h | | | 52 | ++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | fela | | | 0 | |
| A | fela.l | | | 11 | +++++++++++ |
| A | fela.y | | | 165 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | test.fe | | | 4 | ++++ |
| A | util.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 */