-
Notifications
You must be signed in to change notification settings - Fork 0
/
hmk3_Grammar_Syntax.txt
259 lines (221 loc) · 7.84 KB
/
hmk3_Grammar_Syntax.txt
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
/*
Authors: HE YUJIE, 1809853J-I011-0065
CHEN YUXUAN, 1809853J-I011-0011
HE PEILIN, 1809853U-I011-0078
*/
/*
Starting rule of parsing a Pym program. Pym program consists of a sequence of statements. Declarations are also statements.
*/
program --> statement_list
/*
Parameters(below are the same):
- a pointer to a ParserInfo which contains current parser status
- status is responsible for returning result of current function (successful or unsuccessful) to its caller
Computations:
- directly call statement_list function and pass results
*/
TreeNode* program(ParserInfo*, Bool* status);
statement_list --> statement_list statement | empty
/*
Computations:
- if the remaining token list is empty, then return currently constructed tree;
- otherwise call statement and add its results to the left child of the tree
Example result:
()
/
/
() -- () -- () --()
*/
TreeNode* statement_list(ParserInfo*, Bool* status);
// different types of statement
statement --> compound_statement | expression_statement | if_statement | while_statement | def_statement | return_statement | declaration_statement
/*
Computations:
- prefetch the next token in the list:
- if it is INDENT, call compound_statement
- if it is IF, call if_statement
- if it is WHILE, call while_statement
- if it is DEF, call def_statement
- if it is RETURN, call return_statement
- if it is ID, call declaration_statement
- otherwise call expression_statement
- if the call succeeds, return the subtree generated by the call
*/
TreeNode* statement(ParserInfo*, Bool* status);
compound_statement --> INDENT statement_list DEDENT
/*
Computations:
- first, read a INDENT token
- then call statement_list
- finally read DEDENT
this function succeeds if and only if all the above operations succeed
when it succeeds, the left child is the subtree produced by statement_list
*/
TreeNode* compound_statement(ParserInfo*, Bool* status);
expression_statement --> expression simple_end
/*
Computations:
- call expression and then check whether there is a simple_end
- the left child is generated by expression, while the simple_end doesn't generate a subtree
*/
TreeNode* expression_statement(ParserInfo*, Bool* status);
//below are rules for parsing expressions
//Computation process is all similar to that of rel_expression
//assignment: RTL associativity
expression --> var = expression | or_expression
TreeNode* expression(ParserInfo*, Bool* status);
//or operation LTR associativity
or_expression --> or_expression OR and_expression | and_expression
TreeNode* or_expression(ParserInfo*, Bool* status);
//and operation LTR associativity
and_expression --> and_expression AND rel_expression | rel_expression
TreeNode* and_expression(ParserInfo*, Bool* status);
//relative operations LTR associativity
rel_expression --> rel_expression relop additive_expression | additive_expression
/*
Computations:
- call additive_expression
- if it succeeds return a tree with left child generated by additive_expression
- else call rel_expression, check for relop and call additive_expression
- if succeeds return a tree with left child generated by rel_expression and right child generated by additive_expression
()
/ \
() ()
*/
TreeNode* rel_expression(ParserInfo*, Bool* status);
//relative operators (no function generated)
relop --> == | != | > | >= | < | <=
//additive operations LTR associativity
additive_expression --> additive_expression addop mul_expression | mul_expression
TreeNode* additive_expression(ParserInfo*, Bool* status);
//additive operators (binary) (no function generated)
addop --> + | -
//multiplicative operations LTR associativity
mul_expression --> mul_expression mulop unary_expression | unary_expression
TreeNode* mul_expression(ParserInfo*, Bool* status);
//multiplicative operators (no function generated)
mulop --> * | / | %
//unary operations RTL associativity
unary_expression --> unaryop unary_expression | suffix_expression
TreeNode* unary_expression(ParserInfo*, Bool* status);
//unary operators (no function generated)
unaryop --> + | - | NOT
//function call or varible access or literals
suffix_expression --> ( expression ) | ID ( arg_list ) | var | NUMBER | CHARS | [ arg_list ]
/*
Computations:
- read the first available token
- if it is (, call expression and match a )
- if it is NUMBER or CHARS, end
- if it is [, call arg_list and match a ]
- if it is ID,
- if the further next token is (, call arg_list and match a )
- else call var
*/
TreeNode* suffix_expression(ParserInfo*, Bool* status);
var --> ID | ID [ expression ]
/*
Computations:
- left child is ID
- right child is the expression (optional)
*/
TreeNode* var(ParserInfo*, Bool* status);
arg_list --> empty | arg_list , expression | expression
/*
Computations:
- if the remaining token list is empty, then return currently constructed tree;
- otherwise
- call expression, if it succeeds, return it as a child
- otherwise call arg_list, match a comma and call expression
Example result:
()
/
() - () - () -()
*/
TreeNode* arg_list(ParserInfo*, Bool* status);
if_statement --> if_clause elif_clause_list else_clause
/*
Computations:
- call if_clause , elif_clause_list and else_clause
Example result:
()
/ | \
() () ()
*/
TreeNode* if_statement(ParserInfo*, Bool* status);
if_clause --> IF expression COLON NEWLINE compound_statement
/*
Example result:
()
/ \
() ()
*/
TreeNode* if_clause(ParserInfo*, Bool* status);
elif_clause_list --> empty | ELIF expression COLON NEWLINE compound_statement elif_clause_list
/*
Computations:
- generate linked list of elif clauses, each of which has two children (expression and compound_statement)
Example result:
()
/
()- () - () - ()
/ \ / \ / \ / \
() () () () () () () ()
*/
TreeNode* elif_clause_list(ParserInfo*, Bool* status);
else_clause --> ELSE COLON NEWLINE compound_statement | empty
/*
Computations:
- left child is compound_statement
*/
TreeNode* else_clause(ParserInfo*, Bool* status);
while_statement --> WHILE expression COLON NEWLINE compound_statement
/*
Computations:
- binary tree of expression and compound_statement
*/
TreeNode* while_statement(ParserInfo*, Bool* status);
return_statement --> RETURN expression simple_end | RETURN simple_end
/*
Computations:
- left child is expression
*/
TreeNode* return_statement(ParserInfo*, Bool* status);
def_statement --> DEF ID ( param_list ) func_type_specifier COLON NEWLINE compound_statement
/*
Computations:
- three children are param_list, func_type_specifier and compound_statement
*/
TreeNode* def_statement(ParserInfo*, Bool* status);
//For function return types
func_type_specifier --> empty | ARROW type_specifier | ARROW type_specifier [ array_extent ]
/*
Computations:
- left child is type_specifier and right child is array_extent
*/
TreeNode* func_type_specifier(ParserInfo*, Bool* status);
//paramters list
param_list --> empty | param_list , param | param_list
/*
Computations:
- similar to arg_list
*/
TreeNode* param_list(ParserInfo*, Bool* status);
param --> ID | ID COLON type_specifier | ID COLON type_specifier [ array_extent ]
/*
Computations:
- similar to func_type_specifier except that ID should be stored
*/
TreeNode* param(ParserInfo*, Bool* status);
//type names (no function generated)
type_specifier --> INT | NUM | STR
//size of array (no function generated)
array_extent --> empty | NUMBER
declaration_statement --> ID COLON type_specifier simple_end
/*
Computations:
- left child is type_specifier and ID should be stored
*/
TreeNode* declaration_statement(ParserInfo*, Bool* status);
//end of simple statement (no function generated)
simple_end --> NEWLINE | FEOF