1
2
3
4
5
6 using Cm.Ast;
7 using LexerFileTokens;
8
9 parser StatementParser
10 {
11 uselexer LexerFileLexer;
12
13 using ExpressionParser.Expression;
14 using ExpressionParser.ArgumentList;
15 using TypeExprParser.TypeExpr;
16 using IdentifierParser.Identifier;
17
18 Statement(ParsingContext* ctx) : StatementNode*
19 ::= LabeledStatement(ctx):labeledStatement{ return labeledStatement; }
20 | ControlStatement(ctx):controlStatement{ return controlStatement; }
21 | ExpressionStatement(ctx):expressionStatement{ return expressionStatement; }
22 | AssignmentStatement(ctx):assignmentStatement{ return assignmentStatement; }
23 | ConstructionStatement(ctx):constructionStatement{ return constructionStatement; }
24 | DeleteStatement(ctx):deleteStatement{ return deleteStatement; }
25 | DestroyStatement(ctx):destroyStatement{ return destroyStatement; }
26 | EmptyStatement(ctx):emptyStatement{ return emptyStatement; }
27 | ThrowStatement(ctx):throwStatement{ return throwStatement; }
28 | TryStatement(ctx):tryStatement{ return tryStatement; }
29 | AssertStatement(ctx):assertStatement{ return assertStatement; }
30 | ConditionalCompilationStatement(ctx):condCompStatement{ return condCompStatement; }
31 ;
32
33 Label(ParsingContext* ctx, var Span s, var ustring label) : LabelNode*
34 ::= (ID{ s = span; label = lexer.GetMatch(span); } COLON{ s.end = span.end; }){ return new LabelNode(s, ctx->ModuleId(), label); }
35 ;
36
37 LabeledStatement(ParsingContext* ctx, var UniquePtr<LabeledStatementNode> stmt) : StatementNode*
38 ::= Label(ctx):lbl Statement(ctx):s{ stmt.Reset(new LabeledStatementNode(span, ctx->ModuleId(), s)); stmt->SetLabelNode(lbl); return stmt.Release(); }
39 ;
40
41 ControlStatement(ParsingContext* ctx) : StatementNode*
42 ::= CompoundStatement(ctx):compoundStatement{ return compoundStatement; }
43 | ReturnStatement(ctx):returnStatement{ return returnStatement; }
44 | IfStatement(ctx):ifStatement{ return ifStatement; }
45 | WhileStatement(ctx):whileStatement{ return whileStatement; }
46 | DoStatement(ctx):doStatement{ return doStatement; }
47 | RangeForStatement(ctx):rangeForStatement{ return rangeForStatement; }
48 | ForStatement(ctx):forStatement{ return forStatement; }
49 | BreakStatement(ctx):breakStatement{ return breakStatement; }
50 | ContinueStatement(ctx):continueStatement{ return continueStatement; }
51 | GotoStatement(ctx):gotoStatement{ return gotoStatement; }
52 | SwitchStatement(ctx):switchStatement{ return switchStatement; }
53 | GotoCaseStatement(ctx):gotoCaseStatement{ return gotoCaseStatement; }
54 | GotoDefaultStatement(ctx):gotoDefaultStatement{ return gotoDefaultStatement; }
55 ;
56
57 CompoundStatement(ParsingContext* ctx, var UniquePtr<CompoundStatementNode> compoundStatement) : CompoundStatementNode*
58 ::= LBRACE{ compoundStatement.Reset(new CompoundStatementNode(span, ctx->ModuleId())); } (Statement(ctx):stmt{ compoundStatement->AddStatement(stmt); })* RBRACE!
59 {
60 compoundStatement->SetSpanEnd(span.end);
61 return compoundStatement.Release();
62 }
63 ;
64
65 ReturnStatement(ParsingContext* ctx, var Span s) : StatementNode*
66 ::= RETURN{ s = span; } Expression(ctx):expr? SEMICOLON!{ s.end = span.end; return new ReturnStatementNode(s, ctx->ModuleId(), expr); }
67 ;
68
69 IfStatement(ParsingContext* ctx, var Span s, var Span leftParenSpan, var Span rightParenSpan, var Span elseSpan) : IfStatementNode*
70 ::=
71 ( IF{ s = span; } LPAREN{ leftParenSpan = span; } Expression(ctx):cond RPAREN{ rightParenSpan = span; } Statement(ctx):thenS{ s.end = span.end; }
72 (ELSE{ elseSpan = span; } Statement(ctx):elseS{ s.end = span.end; })?
73 )
74 {
75 IfStatementNode* value = new IfStatementNode(s, ctx->ModuleId(), cond, thenS, elseS);
76 value->SetLeftParenSpan(leftParenSpan);
77 value->SetRightParenSpan(rightParenSpan);
78 value->SetElseSpan(elseSpan);
79 return value;
80 }
81 ;
82
83 WhileStatement(ParsingContext* ctx, var Span s, var Span leftParenSpan, var Span rightParenSpan) : WhileStatementNode*
84 ::= (WHILE{ s = span; } LPAREN!{ leftParenSpan = span; } Expression(ctx):cond! RPAREN!{ rightParenSpan = span; } Statement(ctx):stmt!{ s.end = span.end; })
85 {
86 WhileStatementNode* value = new WhileStatementNode(s, ctx->ModuleId(), cond, stmt);
87 value->SetLeftParenSpan(leftParenSpan);
88 value->SetRightParenSpan(rightParenSpan);
89 return value;
90 }
91 ;
92
93 DoStatement(ParsingContext* ctx, var Span s, var Span whileSpan, var Span leftParenSpan, var Span rightParenSpan) : DoStatementNode*
94 ::= (DO{ s = span; } Statement(ctx):stmt! WHILE!{ whileSpan = span; } LPAREN!{ leftParenSpan = span; } Expression(ctx):cond! RPAREN!{ rightParenSpan = span; } SEMICOLON!{ s.end = span.end; })
95 {
96 DoStatementNode* value = new DoStatementNode(s, ctx->ModuleId(), stmt, cond);
97 value->SetWhileSpan(whileSpan);
98 value->SetLeftParenSpan(leftParenSpan);
99 value->SetRightParenSpan(rightParenSpan);
100 return value;
101 }
102 ;
103
104 ForStatement(ParsingContext* ctx, var Span s, var Span leftParenSpan, var Span rightParenSpan) : ForStatementNode*
105 ::=
106 (
107 FOR{ s = span; } LPAREN{ leftParenSpan = span; } ForInitStatement(ctx):init! Expression(ctx):cond? SEMICOLON! ForLoopStatementExpr(ctx):loop! RPAREN!{ rightParenSpan = span; }
108 Statement(ctx):stmt!{ s.end = span.end; }
109 )
110 {
111 ForStatementNode* value = new ForStatementNode(s, ctx->ModuleId(), init, cond, loop, stmt);
112 value->SetLeftParenSpan(leftParenSpan);
113 value->SetRightParenSpan(rightParenSpan);
114 return value;
115 }
116 ;
117
118 ForInitStatement(ParsingContext* ctx) : StatementNode*
119 ::= AssignmentStatement(ctx):assignmentStatement{ return assignmentStatement; }
120 | ConstructionStatement(ctx):constructionStatement{ return constructionStatement; }
121 | EmptyStatement(ctx):emptyStatement{ return emptyStatement; }
122 ;
123
124 ForLoopStatementExpr(ParsingContext* ctx) : StatementNode*
125 ::= AssignmentStatementExpr(ctx):assignmentStatementExpr{ return assignmentStatementExpr; }
126 | Expression(ctx):expr{ return new ExpressionStatementNode(span, ctx->ModuleId(), expr); }
127 | empty{ return new EmptyStatementNode(span, ctx->ModuleId()); }
128 ;
129
130 RangeForStatement(ParsingContext* ctx, var Span s, var Span leftParenSpan, var Span rightParenSpan, var Span colonSpan) : RangeForStatementNode*
131 ::=
132 (
133 FOR{ s = span; } LPAREN{ leftParenSpan = span; } TypeExpr(ctx):type Identifier(ctx):id COLON{ colonSpan = span; } Expression(ctx):container! RPAREN!{ rightParenSpan = span; }
134 Statement(ctx):action{ s.end = span.end; }
135 )
136 {
137 RangeForStatementNode* value = new RangeForStatementNode(s, ctx->ModuleId(), type, id, container, action);
138 value->SetLeftParenSpan(leftParenSpan);
139 value->SetRightParenSpan(rightParenSpan);
140 value->SetColonSpan(colonSpan);
141 return value;
142 }
143 ;
144
145 BreakStatement(ParsingContext* ctx, var Span s) : StatementNode*
146 ::= BREAK{ s = span; } SEMICOLON!{ s.end = span.end; return new BreakStatementNode(s, ctx->ModuleId()); }
147 ;
148
149 ContinueStatement(ParsingContext* ctx, var Span s) : StatementNode*
150 ::= CONTINUE{ s = span; } SEMICOLON!{ s.end = span.end; return new ContinueStatementNode(s, ctx->ModuleId()); }
151 ;
152
153 GotoStatement(ParsingContext* ctx, var ustring label, var Span s) : StatementNode*
154 ::= GOTO{ s = span; } ID{ label = lexer.GetMatch(span); } SEMICOLON!{ s.end = span.end; return new GotoStatementNode(s, ctx->ModuleId(), label); }
155 ;
156
157 SwitchStatement(ParsingContext* ctx, var UniquePtr<SwitchStatementNode> switchStatement,
158 var Span leftParenSpan, var Span rightParenSpan, var Span beginBraceSpan, var Span endBraceSpan) : SwitchStatementNode*
159 ::= (SWITCH LPAREN!{ leftParenSpan = span; } Expression(ctx):cond! RPAREN!)
160 {
161 rightParenSpan = span;
162 switchStatement.Reset(new SwitchStatementNode(span, ctx->ModuleId(), cond));
163 switchStatement->SetLeftParenSpan(leftParenSpan);
164 switchStatement->SetRightParenSpan(rightParenSpan);
165 }
166 LBRACE!{ beginBraceSpan = span; }
167 ( CaseStatement(ctx):caseStatement{ switchStatement->AddCase(caseStatement); }
168 | DefaultStatement(ctx):defaultStatement{ switchStatement->SetDefault(defaultStatement); }
169 )*
170 RBRACE!{ endBraceSpan = span; switchStatement->SetBeginBraceSpan(beginBraceSpan); switchStatement->SetEndBraceSpan(endBraceSpan); return switchStatement.Release(); }
171 ;
172
173 CaseStatement(ParsingContext* ctx, var UniquePtr<CaseStatementNode> caseS, var Span s, var Span caseSpan) : CaseStatementNode*
174 ::= empty{ caseS.Reset(new CaseStatementNode(span, ctx->ModuleId())); s = span; }
175 (((CASE{ caseSpan = span; } Expression(ctx):caseExpr{ caseS->AddCaseSpan(caseSpan); caseS->AddCaseExpr(caseExpr); } COLON!)+){ s.end = span.end; caseS->SetSpan(s); }
176 (Statement(ctx):stmt{ caseS->AddStatement(stmt); })*
177 )
178 {
179 return caseS.Release();
180 }
181 ;
182
183 DefaultStatement(ParsingContext* ctx, var UniquePtr<DefaultStatementNode> defaultS, var Span s) : DefaultStatementNode*
184 ::= (DEFAULT{ s = span; } COLON!{ s.end = span.end; defaultS.Reset(new DefaultStatementNode(s, ctx->ModuleId())); }
185 (Statement(ctx):stmt{ defaultS->AddStatement(stmt); })*
186 )
187 {
188 return defaultS.Release();
189 }
190 ;
191
192 GotoCaseStatement(ParsingContext* ctx, var Span s) : StatementNode*
193 ::= GOTO{ s = span; } CASE Expression(ctx):caseExpr SEMICOLON!{ s.end = span.end; return new GotoCaseStatementNode(s, ctx->ModuleId(), caseExpr); }
194 ;
195
196 GotoDefaultStatement(ParsingContext* ctx, var Span s) : StatementNode*
197 ::= GOTO{ s = span; } DEFAULT SEMICOLON!{ s.end = span.end; return new GotoDefaultStatementNode(s, ctx->ModuleId()); }
198 ;
199
200 AssignmentStatementExpr(ParsingContext* ctx, var Span s) : StatementNode*
201 ::= empty{ ctx->PushParsingLvalue(true); s = span; } Expression(ctx):target{ ctx->PopParsingLvalue(); } / { ctx->PopParsingLvalue(); } ASSIGN Expression(ctx):source
202 {
203 s.end = span.end; return new AssignmentStatementNode(s, ctx->ModuleId(), target, source);
204 }
205 ;
206
207 AssignmentStatement(ParsingContext* ctx, var UniquePtr<StatementNode> statement) : StatementNode*
208 ::= AssignmentStatementExpr(ctx):stmt SEMICOLON{ statement.Reset(stmt); statement->SetSpanEnd(span.end); return statement.Release(); }
209 ;
210
211 ConstructionStatement(ParsingContext* ctx, var UniquePtr<ConstructionStatementNode> constructionStatement) : ConstructionStatementNode*
212 ::= (TypeExpr(ctx):type Identifier(ctx):id!){ constructionStatement.Reset(new ConstructionStatementNode(span, ctx->ModuleId(), type, id)); }
213 ( ASSIGN Expression(ctx):value!{ constructionStatement->AddArgument(value); constructionStatement->SetAssignment(); }
214 | LPAREN ArgumentList(ctx, constructionStatement.Get()):argumentList RPAREN!
215 | empty{ constructionStatement->SetEmpty(); }
216 )
217 SEMICOLON!{ constructionStatement->SetSpanEnd(span.end); return constructionStatement.Release(); }
218 ;
219
220 DeleteStatement(ParsingContext* ctx, var Span s) : StatementNode*
221 ::= DELETE{ s = span; } Expression(ctx):ptr! SEMICOLON!{ s.end = span.end; return new DeleteStatementNode(s, ctx->ModuleId(), ptr); }
222 ;
223
224 DestroyStatement(ParsingContext* ctx, var Span s) : StatementNode*
225 ::= DESTROY{ s = span; } Expression(ctx):ptr! SEMICOLON!{ s.end = span.end; return new DestroyStatementNode(s, ctx->ModuleId(), ptr); }
226 ;
227
228 ExpressionStatement(ParsingContext* ctx, var Span s) : StatementNode*
229 ::= empty{ ctx->PushParsingExpressionStatement(true); }
230 (Expression(ctx):expr{ s = span; } SEMICOLON{ s.end = span.end; }){ ctx->PopParsingExpressionStatement(); return new ExpressionStatementNode(s, ctx->ModuleId(), expr); } / { ctx->PopParsingExpressionStatement(); }
231 ;
232
233 EmptyStatement(ParsingContext* ctx) : StatementNode*
234 ::= SEMICOLON{ return new EmptyStatementNode(span, ctx->ModuleId()); }
235 ;
236
237 ThrowStatement(ParsingContext* ctx, var Span s) : StatementNode*
238 ::= THROW{ s = span; } Expression(ctx):exception? SEMICOLON!{ s.end = span.end; return new ThrowStatementNode(s, ctx->ModuleId(), exception); }
239 ;
240
241 TryStatement(ParsingContext* ctx, var UniquePtr<TryStatementNode> tryStatement) : TryStatementNode*
242 ::=
243 ( (TRY CompoundStatement(ctx):tryBlock){ tryStatement.Reset(new TryStatementNode(span, ctx->ModuleId(), tryBlock)); }
244 (Catch(ctx):ctch{ tryStatement->AddCatch(ctch); })+
245 )
246 {
247 return tryStatement.Release();
248 }
249 ;
250
251 Catch(ParsingContext* ctx, var Span s, var Span leftParenSpan, var Span rightParenSpan) : CatchNode*
252 ::= CATCH{ s = span; } LPAREN!{ leftParenSpan = span; } TypeExpr(ctx):catchType! Identifier(ctx):catchId? RPAREN!{ rightParenSpan = span; }
253 CompoundStatement(ctx):catchBlock
254 {
255 s.end = span.end;
256 CatchNode* value = new CatchNode(s, ctx->ModuleId(), catchType, catchId, catchBlock);
257 value->SetLeftParenSpan(leftParenSpan);
258 value->SetRightParenSpan(rightParenSpan);
259 return value;
260 }
261 ;
262
263 AssertStatement(ParsingContext* ctx, var Span s) : StatementNode*
264 ::= HASH{ s = span; } ASSERT Expression(ctx):expr! SEMICOLON!{ s.end = span.end; return new AssertStatementNode(s, ctx->ModuleId(), expr); }
265 ;
266
267 ConditionalCompilationStatement(ParsingContext* ctx, var UniquePtr<ConditionalCompilationStatementNode> condCompStmt,
268 var Span s, var Span keywordSpan, var Span leftParenSpan, var Span rightParenSpan) : ConditionalCompilationStatementNode*
269 ::= HASH{ s = span; keywordSpan = span; }
270 IF{ keywordSpan.end = span.end; } LPAREN!{ leftParenSpan = span; }
271 ConditionalCompilationExpression(ctx):ifExpr{ s.end = span.end; condCompStmt.Reset(new ConditionalCompilationStatementNode(s, ctx->ModuleId(), ifExpr)); condCompStmt->IfPart()->SetKeywordSpan(keywordSpan); }
272 RPAREN!{ rightParenSpan = span; condCompStmt->IfPart()->SetLeftParenSpan(leftParenSpan); condCompStmt->IfPart()->SetRightParenSpan(rightParenSpan); }
273 (Statement(ctx):ifS{ condCompStmt->AddIfStatement(ifS); })*
274 (
275 HASH{ keywordSpan = span; } ELIF{ keywordSpan.end = span.end; }
276 LPAREN!{ leftParenSpan = span; } ConditionalCompilationExpression(ctx):elifExpr{ condCompStmt->AddElifExpr(span, ctx->ModuleId(), elifExpr); } RPAREN!
277 {
278 rightParenSpan = span;
279 condCompStmt->SetElifLeftParenSpan(leftParenSpan);
280 condCompStmt->SetElifRightParenSpan(rightParenSpan);
281 condCompStmt->SetElifKeywordSpan(keywordSpan);
282 }
283 (Statement(ctx):elifS{ condCompStmt->AddElifStatement(elifS); })*
284 )*
285 (
286 HASH{ keywordSpan = span; } ELSE (Statement(ctx):elseS{ condCompStmt->AddElseStatement(span, ctx->ModuleId(), elseS); })* empty{ condCompStmt->ElsePart()->SetKeywordSpan(keywordSpan); }
287 )?
288 HASH{ keywordSpan = span; } ENDIF!{ keywordSpan.end = span.end; condCompStmt->SetEndIfSpan(keywordSpan); return condCompStmt.Release(); }
289 ;
290
291 ConditionalCompilationExpression(ParsingContext* ctx) : ConditionalCompilationExpressionNode*
292 ::= ConditionalCompilationDisjunction(ctx):disjunction{ return disjunction; }
293 ;
294
295 ConditionalCompilationDisjunction(ParsingContext* ctx, var Span s, var UniquePtr<ConditionalCompilationExpressionNode> condCompExpr) : ConditionalCompilationExpressionNode*
296 ::=
297 (
298 ConditionalCompilationConjunction(ctx):left{ s = span; condCompExpr.Reset(left); }
299 (DISJUNCTION ConditionalCompilationConjunction(ctx):right{ s.end = span.end; condCompExpr.Reset(new ConditionalCompilationDisjunctionNode(s, ctx->ModuleId(), condCompExpr.Release(), right)); })*
300 )
301 {
302 return condCompExpr.Release();
303 }
304 ;
305
306 ConditionalCompilationConjunction(ParsingContext* ctx, var Span s, var UniquePtr<ConditionalCompilationExpressionNode> condCompExpr) : ConditionalCompilationExpressionNode*
307 ::=
308 (
309 ConditionalCompilationPrefix(ctx):left{ s = span; condCompExpr.Reset(left); }
310 (AMPAMP ConditionalCompilationPrefix(ctx):right{ s.end = span.end; condCompExpr.Reset(new ConditionalCompilationConjunctionNode(s, ctx->ModuleId(), condCompExpr.Release(), right)); })*
311 )
312 {
313 return condCompExpr.Release();
314 }
315 ;
316
317 ConditionalCompilationPrefix(ParsingContext* ctx, var Span s, var UniquePtr<ConditionalCompilationExpressionNode> condCompExpr) : ConditionalCompilationExpressionNode*
318 ::=
319 ( EXCLAMATION{ s = span; } ConditionalCompilationPrefix(ctx):prefix{ s.end = span.end; condCompExpr.Reset(new ConditionalCompilationNotNode(s, ctx->ModuleId(), prefix)); }
320 | ConditionalCompilationPrimary(ctx):primary!{ condCompExpr.Reset(primary); }
321 )
322 {
323 return condCompExpr.Release();
324 }
325 ;
326
327 ConditionalCompilationPrimary(ParsingContext* ctx, var ustring symbol) : ConditionalCompilationExpressionNode*
328 ::= ID{ symbol = lexer.GetMatch(span); return new ConditionalCompilationPrimaryNode(span, ctx->ModuleId(), symbol); }
329 | LPAREN ConditionalCompilationExpression(ctx):expr RPAREN!{ return new ParenthesizedConditionalCompilationExpressionNode(span, ctx->ModuleId(), expr); }
330 ;
331
332 ruleinfo
333 {
334 (Statement, "statement"), (Label, "label"), (LabeledStatement, "labeled statement"), (ControlStatement, "control statement"), (CompoundStatement, "compound statement"),
335 (ReturnStatement, "return statement"), (IfStatement, "if statement"), (WhileStatement, "while statement"), (DoStatement, "do statement"),
336 (ForStatement, "for statement"), (ForInitStatement, "for initialization statement"), (ForLoopStatementExpr, "for loop expression"),
337 (RangeForStatement, "range for statement"), (BreakStatement, "break statement"), (ContinueStatement, "continue statement"), (GotoStatement, "goto statement"),
338 (SwitchStatement, "switch statement"), (CaseStatement, "case statement"), (DefaultStatement, "default statement"), (GotoCaseStatement, "goto case statement"),
339 (GotoDefaultStatement, "goto default statement"), (AssignmentStatementExpr, "assignment expression"), (AssignmentStatement, "assignment statement"),
340 (ConstructionStatement, "construction statement"), (DeleteStatement, "delete statement"), (DestroyStatement, "destroy statement"), (ExpressionStatement, "expression statement"),
341 (EmptyStatement, "empty statement"), (ThrowStatement, "throw statement"), (TryStatement, "try statement"), (Catch, "catch statement"), (AssertStatement, "assert statement"),
342 (ConditionalCompilationStatement, "conditional compilation statement"), (ConditionalCompilationExpression, "conditional compilation expression"),
343 (ConditionalCompilationDisjunction, "conditional compilation disjunction"), (ConditionalCompilationConjunction, "conditional compilation conjunction"),
344 (ConditionalCompilationPrefix, "conditional compilation prefix expression"), (ConditionalCompilationPrimary, "conditional compilation primary expression")
345 }
346 }