aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFlavian Kaufmann <flavian@flaviankaufmann.ch>2025-05-21 09:31:49 +0200
committerFlavian Kaufmann <flavian@flaviankaufmann.ch>2025-05-21 09:31:49 +0200
commit442eba08dba74c3254a8d089ca1961147e59972b (patch)
tree9723190187eac5d541bf01a357950d73e31d54c1 /src
parentdb4ae8a3540b8307b695e6626ec95d91cad0582a (diff)
downloadimp-442eba08dba74c3254a8d089ca1961147e59972b.tar.gz
imp-442eba08dba74c3254a8d089ca1961147e59972b.zip
syntactic sugar
Diffstat (limited to 'src')
-rw-r--r--src/lexer.l67
-rw-r--r--src/parser.y170
2 files changed, 123 insertions, 114 deletions
diff --git a/src/lexer.l b/src/lexer.l
index 26ac229..b2cbaab 100644
--- a/src/lexer.l
+++ b/src/lexer.l
@@ -10,38 +10,41 @@ WHITESPACE [ \t\r\n]+
%%
-"skip" { return TOKEN_SKIP; }
-"if" { return TOKEN_IF; }
-"then" { return TOKEN_THEN; }
-"else" { return TOKEN_ELSE; }
-"end" { return TOKEN_END; }
-"while" { return TOKEN_WHILE; }
-"do" { return TOKEN_DO; }
-"var" { return TOKEN_VAR; }
-"in" { return TOKEN_IN; }
-
-"(" { return TOKEN_LEFT_PARENTHESIS; }
-")" { return TOKEN_RIGHT_PARENTHESIS; }
-";" { return TOKEN_SEMICOLON; }
-":=" { return TOKEN_ASSIGN; }
-
-"+" { return TOKEN_PLUS; }
-"-" { return TOKEN_MINUS; }
-"*" { return TOKEN_MULTIPLY; }
-
-"or" { return TOKEN_OR; }
-"and" { return TOKEN_AND; }
-"not" { return TOKEN_NOT; }
-
-"=" { return TOKEN_EQUALS; }
-"#" { return TOKEN_NOT_EQUALS; }
-"<=" { return TOKEN_LESS_EQUAL; }
-"<" { return TOKEN_LESS_THAN; }
-">=" { return TOKEN_GREATER_EQUAL; }
-">" { return TOKEN_GREATER_THAN; }
-
-{DIGIT}+ { yylval.num = atoi(yytext); return TOKEN_NUMERAL; }
-{IDENT} { yylval.id = strdup(yytext); return TOKEN_IDENTIFIER; }
+"skip" { return T_SKIP; }
+"if" { return T_IF; }
+"then" { return T_THEN; }
+"else" { return T_ELSE; }
+"end" { return T_END; }
+"while" { return T_WHILE; }
+"do" { return T_DO; }
+"var" { return T_VAR; }
+"in" { return T_IN; }
+
+"(" { return T_LPAREN; }
+")" { return T_RPAREN; }
+";" { return T_SEM; }
+":=" { return T_ASSIGN; }
+
+"+" { return T_PLUS; }
+"-" { return T_MINUS; }
+"*" { return T_STAR; }
+
+"or" { return T_OR; }
+"and" { return T_AND; }
+"not" { return T_NOT; }
+
+"=" { return T_EQ; }
+"#" { return T_NE; }
+"<=" { return T_LE; }
+"<" { return T_LT; }
+">=" { return T_GE; }
+">" { return T_GT; }
+
+"true" { return T_TRUE; }
+"false" { return T_FALSE; }
+
+{DIGIT}+ { yylval.num = atoi(yytext); return T_NUM; }
+{IDENT} { yylval.id = strdup(yytext); return T_ID; }
{WHITESPACE} { }
. { fprintf(stderr, "Unknown char: %s\n", yytext); }
diff --git a/src/parser.y b/src/parser.y
index cb3544e..f03e54f 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -17,93 +17,99 @@ void yyerror(const char *s) {
%union {
int num;
char *id;
- int op;
struct ASTNode *node;
}
-%start program
-
-%token <id> TOKEN_IDENTIFIER
-%token <num> TOKEN_NUMERAL
-%token TOKEN_ASSIGN
-%token TOKEN_LEFT_PARENTHESIS TOKEN_RIGHT_PARENTHESIS
-%token TOKEN_SEMICOLON
-%token TOKEN_SKIP
-%token TOKEN_IF TOKEN_THEN TOKEN_ELSE TOKEN_END TOKEN_WHILE TOKEN_DO TOKEN_VAR TOKEN_IN
-%token TOKEN_PLUS TOKEN_MINUS TOKEN_MULTIPLY
-%token TOKEN_NOT TOKEN_OR TOKEN_AND
-%token TOKEN_EQUALS TOKEN_NOT_EQUALS TOKEN_LESS_THAN TOKEN_LESS_EQUAL TOKEN_GREATER_THAN TOKEN_GREATER_EQUAL
-
-%type <node> program statement variable arithmetic_expression boolean_expression
-%type <op> arithmetic_operation boolean_operation relational_operation
-
+%start prog
+
+%token <num> T_NUM
+%token <id> T_ID
+%token T_EQ T_NE T_LT T_LE T_GT T_GE
+%token T_TRUE T_FALSE
+%left T_OR
+%left T_AND
+%token T_NOT
+%left T_PLUS T_MINUS
+%left T_STAR
+%right T_UMINUS
+%token T_END T_IF T_THEN T_ELSE T_WHILE T_DO T_VAR T_IN
+%token T_SKIP
+%token T_ASSIGN
+%token T_LPAREN T_RPAREN
+%token T_SEM
+
+%type <node> prog stm var aexp bexp
%%
-
-program : statement
- { ast_root = $1; }
- ;
-
-statement : TOKEN_SKIP
- { $$ = ast_skip(); }
- | variable TOKEN_ASSIGN arithmetic_expression
- { $$ = ast_assign($1, $3); }
- | TOKEN_LEFT_PARENTHESIS statement TOKEN_SEMICOLON statement TOKEN_RIGHT_PARENTHESIS
- { $$ = ast_seq($2, $4); }
- | TOKEN_IF boolean_expression TOKEN_THEN statement TOKEN_ELSE statement TOKEN_END
- { $$ = ast_if($2, $4, $6); }
- | TOKEN_WHILE boolean_expression TOKEN_DO statement TOKEN_END
- { $$ = ast_while($2, $4); }
- | TOKEN_VAR variable TOKEN_ASSIGN arithmetic_expression TOKEN_IN statement TOKEN_END
- { $$ = ast_let($2, $4, $6); }
- ;
-
-variable : TOKEN_IDENTIFIER
- { $$ = ast_var($1); }
- ;
-
-arithmetic_expression : TOKEN_LEFT_PARENTHESIS arithmetic_expression arithmetic_operation arithmetic_expression TOKEN_RIGHT_PARENTHESIS
- { $$ = ast_aop($3, $2, $4); }
- | variable
- { $$ = $1; }
- | TOKEN_NUMERAL
- { $$ = ast_int($1); }
- ;
-
-arithmetic_operation : TOKEN_PLUS
- { $$ = AOP_ADD; }
- | TOKEN_MINUS
- { $$ = AOP_SUB; }
- | TOKEN_MULTIPLY
- { $$ = AOP_MUL; }
- ;
-
-boolean_expression : TOKEN_LEFT_PARENTHESIS boolean_expression boolean_operation boolean_expression TOKEN_RIGHT_PARENTHESIS
- { $$ = ast_bop($3, $2, $4); }
- | TOKEN_NOT boolean_expression
- { $$ = ast_not($2); }
- | arithmetic_expression relational_operation arithmetic_expression
- { $$ = ast_rop($2, $1, $3); }
- ;
-
-boolean_operation : TOKEN_OR
- { $$ = BOP_OR; }
- | TOKEN_AND
- { $$ = BOP_AND; }
- ;
-relational_operation : TOKEN_EQUALS
- { $$ = ROP_EQ; }
- | TOKEN_NOT_EQUALS
- { $$ = ROP_NE; }
- | TOKEN_LESS_THAN
- { $$ = ROP_LT; }
- | TOKEN_LESS_EQUAL
- { $$ = ROP_LE; }
- | TOKEN_GREATER_THAN
- { $$ = ROP_GT; }
- | TOKEN_GREATER_EQUAL
- { $$ = ROP_GE; }
- ;
+prog : stm
+ { ast_root = $1; }
+ ;
+
+stm : T_SKIP
+ { $$ = ast_skip(); }
+ | var T_ASSIGN aexp
+ { $$ = ast_assign($1, $3); }
+ | T_LPAREN stm T_SEM stm T_RPAREN
+ { $$ = ast_seq($2, $4); }
+ | stm T_SEM stm
+ { $$ = ast_seq($1, $3); }
+ | stm T_SEM
+ { $$ = $1; }
+ | T_IF bexp T_THEN stm T_ELSE stm T_END
+ { $$ = ast_if($2, $4, $6); }
+ | T_IF bexp T_THEN stm T_END
+ { $$ = ast_if($2, $4, ast_skip()); }
+ | T_WHILE bexp T_DO stm T_END
+ { $$ = ast_while($2, $4); }
+ | T_VAR var T_ASSIGN aexp T_IN stm T_END
+ { $$ = ast_let($2, $4, $6); }
+ ;
+
+var : T_ID
+ { $$ = ast_var($1); }
+ ;
+
+aexp : aexp T_PLUS aexp
+ { $$ = ast_aop(AOP_ADD, $1, $3); }
+ | aexp T_MINUS aexp
+ { $$ = ast_aop(AOP_SUB, $1, $3); }
+ | aexp T_STAR aexp
+ { $$ = ast_aop(AOP_MUL, $1, $3); }
+ | T_MINUS aexp %prec T_UMINUS
+ { $$ = ast_aop(AOP_SUB, ast_int(0), $2); }
+ | T_LPAREN aexp T_RPAREN
+ { $$ = $2; }
+ | var
+ { $$ = $1; }
+ | T_NUM
+ { $$ = ast_int($1); }
+ ;
+
+bexp : bexp T_OR bexp
+ { $$ = ast_bop(BOP_OR, $1, $3); }
+ | bexp T_AND bexp
+ { $$ = ast_bop(BOP_AND, $1, $3); }
+ | T_NOT bexp
+ { $$ = ast_not($2); }
+ | aexp T_EQ aexp
+ { $$ = ast_rop(ROP_EQ, $1, $3); }
+ | aexp T_NE aexp
+ { $$ = ast_rop(ROP_NE, $1, $3); }
+ | aexp T_LE aexp
+ { $$ = ast_rop(ROP_LE, $1, $3); }
+ | aexp T_LT aexp
+ { $$ = ast_rop(ROP_LT, $1, $3); }
+ | aexp T_GE aexp
+ { $$ = ast_rop(ROP_GE, $1, $3); }
+ | aexp T_GT aexp
+ { $$ = ast_rop(ROP_GT, $1, $3); }
+ | T_LPAREN bexp T_RPAREN
+ { $$ = $2; }
+ | T_TRUE
+ { $$ = ast_rop(ROP_EQ, ast_int(1), ast_int(1)); }
+ | T_FALSE
+ { $$ = ast_rop(ROP_EQ, ast_int(0), ast_int(1)); }
+ ;
%%