-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparser.y
102 lines (82 loc) · 1.98 KB
/
parser.y
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
%define parse.error verbose
%{
#include <stdio.h>
#include <string.h>
#include "lambda.h"
/* Lexer would provide */
extern int yylex(void);
extern int yylineno;
/* Parser should provide */
void yyerror(const char* err_msg)
{
printf("error(parse): %s\n", err_msg);
}
%}
/* typedef of YYSTYPE i.e. type of yylval */
%union {
unsigned int n;
unsigned int bif;
unsigned int op;
unsigned int e;
unsigned int* a;
char c;
struct node* nd;
}
/* Return value by lexer's rule, which is part of yylex() */
/* Coded as C enum in parser header */
%token UNKNOWN_TOKEN
%token EOE EOL L_BRACKET R_BRACKET LAMBDA DOT
%token <c> VAR
%token <n> NUMBER
/* Associativity and precedence, not applicable here */
/* This is a deep topic, definitely deserve investigation */
/* %nonassoc <fn> CMP */
/* %left TIMES DIV */
/* Map data type of each grammatical construct */
%type <nd> exp
%type <nd> app
%type <nd> lambda
/* Top level production rule */
%start calclist
%%
exp:
app
|
lambda
|
VAR { $$ = new_var_node($1); }
|
NUMBER { $$ = new_num_node($1); }
|
L_BRACKET exp R_BRACKET { $$ = $2; }
;
lambda:
LAMBDA VAR DOT exp { $$ = new_lambda_node(new_var_node($2), $4); }
;
app:
exp exp { $$ = new_app_node($1, $2); }
;
/**************** Parser main loop ***************/
calclist:
/* Skip empty rule would fail bison */
/* Why? Without empty rule, there is no terminal production
* rule. And since calclist is recursively defined,
* production would not terminate
*/
%empty
|
calclist exp EOE {
handle_syntax_tree($2);
lambda_prompt();
}
|
calclist error EOE {
/* Using yyerrok allows recovery from syntax error and thus
* checking on later lines is possible */
yyerrok;
lambda_prompt();
/* Using YYABORT halts compiling upon first faulty line */
//YYABORT;
}
;
%%