summaryrefslogtreecommitdiff
path: root/lisp.y
diff options
context:
space:
mode:
authorFelix Perktold <Felix.Perktold@student.uibk.ac.at>2025-12-20 21:59:28 +0100
committerFelix Perktold <Felix.Perktold@student.uibk.ac.at>2025-12-20 21:59:28 +0100
commit5eeb355805e0d5d91981dbe7eacb078f41da0437 (patch)
treed4d2a76e7988cf63aa9438d2b42d0a4a4656ee42 /lisp.y
init commit
Diffstat (limited to 'lisp.y')
-rw-r--r--lisp.y59
1 files changed, 59 insertions, 0 deletions
diff --git a/lisp.y b/lisp.y
new file mode 100644
index 0000000..29031a4
--- /dev/null
+++ b/lisp.y
@@ -0,0 +1,59 @@
+%{
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include "lisp.h"
+
+int yylex(void);
+int yyerror(const char *s);
+
+static int is_integer(double x) {
+ return floor(x) == x && isfinite(x);
+}
+%}
+
+%union {
+ int ival;
+ double dval;
+ const char *strval;
+ value *val;
+}
+%token <dval> NUMBER
+%token <strval> STRING
+%token <ival> LPAREN RPAREN DOT WHITESPACE
+%token <ival> PLUS MINUS MULT DIV
+
+%type <val> sexpr atom sexprs
+
+%start sexprs
+
+%%
+opt_ws: /* matches no whitespace */
+ | WHITESPACE;
+
+sexprs: sexpr
+ | sexprs opt_ws sexpr;
+
+sexpr: atom
+ | LPAREN opt_ws sexpr opt_ws DOT opt_ws sexpr opt_ws RPAREN
+ {
+ $$ = cons($3, $7);
+ print_val($$);
+ printf("\n");
+ };
+
+atom: NUMBER
+ {
+ if(is_integer($1)) {
+ $$ = make_int($1);
+ } else {
+ $$ = make_double($1);
+ }
+ }
+ | LPAREN opt_ws RPAREN { $$ = make_nil(); }
+ | STRING { $$ = make_string($1); };
+%%
+
+int yyerror(const char *s) {
+ printf("%s\n",s);
+}