aboutsummaryrefslogtreecommitdiff
path: root/src/parser.y
blob: f03e54f4dcb0a0be162b38c26ef81ef237a1e086 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
%{
#include <stdio.h>
#include "ast.h"

extern char *yytext;
extern int yylineno;
extern int yylex();

ASTNode *ast_root;

void yyerror(const char *s) { 
  fprintf(stderr, "Parse error at token \"%s\", line %d: %s\n", yytext, yylineno, s); 
}
%}


%union {
  int            num;
  char           *id;
  struct ASTNode *node;
}

%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

%%

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)); }
      ;

%%