diff options
author | Flavian Kaufmann <flavian@flaviankaufmann.ch> | 2025-05-21 09:31:49 +0200 |
---|---|---|
committer | Flavian Kaufmann <flavian@flaviankaufmann.ch> | 2025-05-21 09:31:49 +0200 |
commit | 442eba08dba74c3254a8d089ca1961147e59972b (patch) | |
tree | 9723190187eac5d541bf01a357950d73e31d54c1 | |
parent | db4ae8a3540b8307b695e6626ec95d91cad0582a (diff) | |
download | imp-442eba08dba74c3254a8d089ca1961147e59972b.tar.gz imp-442eba08dba74c3254a8d089ca1961147e59972b.zip |
syntactic sugar
-rw-r--r-- | example/example.imp | 16 | ||||
-rw-r--r-- | example/example2.imp | 7 | ||||
-rw-r--r-- | src/lexer.l | 67 | ||||
-rw-r--r-- | src/parser.y | 170 |
4 files changed, 141 insertions, 119 deletions
diff --git a/example/example.imp b/example/example.imp index 9db6655..b52d2da 100644 --- a/example/example.imp +++ b/example/example.imp @@ -1,7 +1,13 @@ -(y := 0; +y := 0; + var x := 5 in - (while x < 10 do - x := (x + 1) + + while x < 10 and true do + x := (x + 1); end; - y := x) -end)
\ No newline at end of file + + y := x; + +end; + +z := 5;
\ No newline at end of file diff --git a/example/example2.imp b/example/example2.imp new file mode 100644 index 0000000..9db6655 --- /dev/null +++ b/example/example2.imp @@ -0,0 +1,7 @@ +(y := 0; +var x := 5 in + (while x < 10 do + x := (x + 1) + end; + y := x) +end)
\ No newline at end of file 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)); } + ; %% |