• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

rieske / trans / 29902648358

22 Jul 2026 08:04AM UTC coverage: 91.671% (+0.5%) from 91.142%
29902648358

Pull #53

github

rieske
Fuzz-test and fix the backend
Pull Request #53: Fuzz-test and fix the backend

128 of 134 new or added lines in 10 files covered. (95.52%)

5514 of 6015 relevant lines covered (91.67%)

379841.41 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.0
/src/ast/ContextualSyntaxNodeBuilder.cpp
1
#include "ContextualSyntaxNodeBuilder.h"
2

3
#include <algorithm>
4
#include <functional>
5
#include <sstream>
6
#include <stdexcept>
7
#include <string>
8

9
#include "ArithmeticExpression.h"
10
#include "ArrayAccess.h"
11
#include "ArrayDeclarator.h"
12
#include "AssignmentExpression.h"
13
#include "BitwiseExpression.h"
14
#include "Block.h"
15
#include "ComparisonExpression.h"
16
#include "ConstantExpression.h"
17
#include "ExpressionList.h"
18
#include "ForLoopHeader.h"
19
#include "FunctionCall.h"
20
#include "FunctionDefinition.h"
21
#include "Identifier.h"
22
#include "IdentifierExpression.h"
23
#include "IfElseStatement.h"
24
#include "IfStatement.h"
25
#include "JumpStatement.h"
26
#include "LogicalAndExpression.h"
27
#include "LogicalOrExpression.h"
28
#include "LoopStatement.h"
29
#include "Operator.h"
30
#include "ParenthesizedDeclarator.h"
31
#include "PostfixExpression.h"
32
#include "PrefixExpression.h"
33
#include "ReturnStatement.h"
34
#include "VoidReturnStatement.h"
35
#include "ShiftExpression.h"
36
#include "TypeCast.h"
37
#include "UnaryExpression.h"
38
#include "WhileLoopHeader.h"
39

40
#include "ast/StringLiteralExpression.h"
41
#include "types/Type.h"
42

43
namespace ast {
44

45
void doNothing(AbstractSyntaxTreeBuilderContext&) {
78,186✔
46
}
78,186✔
47

48
// Grammar covers more of C than the AST builder implements. Register explicit stubs so
49
// unsupported constructs fail with a clear message instead of "no AST creator defined".
50
std::function<void(AbstractSyntaxTreeBuilderContext&)> notImplementedYet(const char* feature) {
5,016✔
51
    return [feature](AbstractSyntaxTreeBuilderContext&) {
5,016✔
52
        throw std::runtime_error { std::string(feature) + " is not implemented yet" };
18✔
53
    };
5,016✔
54
}
55

56
void shortType(AbstractSyntaxTreeBuilderContext& context) {
×
57
    throw std::runtime_error { "short type is not implemented yet" };
×
58
}
59

60
void integerType(AbstractSyntaxTreeBuilderContext& context) {
1,266✔
61
    context.pushTypeSpecifier( { type::signedInteger(), context.popTerminal().value });
1,266✔
62
}
1,266✔
63

64
void longType(AbstractSyntaxTreeBuilderContext& context) {
×
65
    throw std::runtime_error { "long type is not implemented yet" };
×
66
}
67

68
void characterType(AbstractSyntaxTreeBuilderContext& context) {
6✔
69
    context.pushTypeSpecifier( { type::signedCharacter(), context.popTerminal().value });
6✔
70
}
6✔
71

72
void voidType(AbstractSyntaxTreeBuilderContext& context) {
38✔
73
    context.pushTypeSpecifier( { type::voidType(), context.popTerminal().value });
38✔
74
}
38✔
75

76
void floatType(AbstractSyntaxTreeBuilderContext& context) {
×
77
    context.pushTypeSpecifier( { type::floating(), context.popTerminal().value });
×
78
}
×
79

80
void doubleType(AbstractSyntaxTreeBuilderContext& context) {
×
81
    throw std::runtime_error { "double type is not implemented yet" };
×
82
}
83

84
void signedType(AbstractSyntaxTreeBuilderContext& context) {
×
85
    throw std::runtime_error { "signed type is not implemented yet" };
×
86
}
87

88
void unsignedType(AbstractSyntaxTreeBuilderContext& context) {
×
89
    throw std::runtime_error { "unsigned type is not implemented yet" };
×
90
}
91

92
void typedefName(AbstractSyntaxTreeBuilderContext& context) {
×
93
    throw std::runtime_error { "typedefName type is not implemented yet" };
×
94
}
95

96
void structOrUnionType(AbstractSyntaxTreeBuilderContext& context) {
×
97
    throw std::runtime_error { "structOrUnionType type is not implemented yet" };
×
98
}
99

100
void enumType(AbstractSyntaxTreeBuilderContext& context) {
×
101
    throw std::runtime_error { "enumType type is not implemented yet" };
×
102
}
103

104
void constQualifier(AbstractSyntaxTreeBuilderContext& context) {
×
105
    context.pushTypeQualifier(type::Qualifier::CONST);
×
106
}
×
107

108
void volatileQualifier(AbstractSyntaxTreeBuilderContext& context) {
×
109
    context.pushTypeQualifier(type::Qualifier::VOLATILE);
×
110
}
×
111

112
void typeQualifierList(AbstractSyntaxTreeBuilderContext& context) {
×
113
    context.newTypeQualifierList(context.popTypeQualifier());
×
114
}
×
115

116
void addTypeQualifierToList(AbstractSyntaxTreeBuilderContext& context) {
×
117
    context.addToTypeQualifierList(context.popTypeQualifier());
×
118
}
×
119

120
void parenthesizedExpression(AbstractSyntaxTreeBuilderContext& context) {
62✔
121
    context.popTerminal();
62✔
122
    context.popTerminal();
62✔
123
}
62✔
124

125
void parenthesizedDeclarator(AbstractSyntaxTreeBuilderContext& context) {
10✔
126
    context.popTerminal();
10✔
127
    context.popTerminal();
10✔
128
    context.pushDirectDeclarator(std::make_unique<ParenthesizedDeclarator>(context.popDeclarator()));
10✔
129
}
10✔
130

131
void declarationTypeSpecifier(AbstractSyntaxTreeBuilderContext& context) {
1,308✔
132
    context.pushDeclarationSpecifiers( { context.popTypeSpecifier() });
1,308✔
133
}
1,308✔
134

135
void addDeclarationTypeSpecifier(AbstractSyntaxTreeBuilderContext& context) {
×
136
    auto declarationSpecifiers = context.popDeclarationSpecifiers();
×
137
    auto typeSpecifier = context.popTypeSpecifier();
×
138
    context.pushDeclarationSpecifiers( { typeSpecifier, declarationSpecifiers });
×
139
}
×
140

141
void declarationStorageClassSpecifier(AbstractSyntaxTreeBuilderContext& context) {
×
142
    context.pushDeclarationSpecifiers( { context.popStorageSpecifier() });
×
143
}
×
144

145
void addDeclarationStorageClassSpecifier(AbstractSyntaxTreeBuilderContext& context) {
×
146
    auto declarationSpecifiers = context.popDeclarationSpecifiers();
×
147
    auto storageSpecifier = context.popStorageSpecifier();
×
148
    context.pushDeclarationSpecifiers( { storageSpecifier, declarationSpecifiers });
×
149
}
×
150

151
void declarationTypeQualifier(AbstractSyntaxTreeBuilderContext& context) {
×
152
    context.pushDeclarationSpecifiers( { context.popTypeQualifier() });
×
153
}
×
154

155
void addDeclarationTypeQualifier(AbstractSyntaxTreeBuilderContext& context) {
×
156
    auto declarationSpecifiers = context.popDeclarationSpecifiers();
×
157
    auto typeQualifier = context.popTypeQualifier();
×
158
    context.pushDeclarationSpecifiers( { typeQualifier, declarationSpecifiers });
×
159
}
×
160

161
void identifierDeclarator(AbstractSyntaxTreeBuilderContext& context) {
1,420✔
162
    context.pushDirectDeclarator(std::make_unique<Identifier>(context.popTerminal()));
1,420✔
163
}
1,420✔
164

165
void arrayDeclarator(AbstractSyntaxTreeBuilderContext& context) {
×
166
    context.popTerminal();
×
167
    context.popTerminal();
×
168
    context.pushDirectDeclarator(std::make_unique<ArrayDeclarator>(context.popDirectDeclarator(), context.popExpression()));
×
169
}
×
170

171
void abstractArrayDeclarator(AbstractSyntaxTreeBuilderContext& context) {
×
172
    context.popTerminal();
×
173
    context.popTerminal();
×
174
    //context.pushDeclarator(std::make_unique<ArrayDeclarator>(context.popDirectDeclarator()));
175
    throw std::runtime_error { "abstract array declarator is not implemented yet" };
×
176
}
177

178
void functionDeclarator(AbstractSyntaxTreeBuilderContext& context) {
88✔
179
    context.popTerminal();
88✔
180
    context.popTerminal();
88✔
181
    auto arguments = context.popArgumentsDeclaration().first;
88✔
182
    // `(void)` is an empty parameter list, not a single void parameter.
183
    if (arguments.size() == 1 && arguments.front().isVoid()) {
88✔
184
        arguments.clear();
2✔
185
    }
186
    context.pushDirectDeclarator(std::make_unique<FunctionDeclarator>(context.popDirectDeclarator(), std::move(arguments)));
88✔
187
}
88✔
188

189
void noargFunctionDeclarator(AbstractSyntaxTreeBuilderContext& context) {
478✔
190
    context.popTerminal();
478✔
191
    context.popTerminal();
478✔
192
    context.pushDirectDeclarator(std::make_unique<FunctionDeclarator>(context.popDirectDeclarator()));
478✔
193
}
478✔
194

195
void pointerToDeclarator(AbstractSyntaxTreeBuilderContext& context) {
70✔
196
    context.pushDeclarator(std::make_unique<Declarator>(context.popDirectDeclarator(), context.popPointers()));
70✔
197
}
70✔
198

199
void declarator(AbstractSyntaxTreeBuilderContext& context) {
1,356✔
200
    context.pushDeclarator(std::make_unique<Declarator>(context.popDirectDeclarator()));
1,356✔
201
}
1,356✔
202

203
void parameterDeclaration(AbstractSyntaxTreeBuilderContext& context) {
188✔
204
    context.pushFormalArgument(FormalArgument { context.popDeclarationSpecifiers(), context.popDeclarator() });
188✔
205
}
188✔
206

207
void abstractParameterDeclaration(AbstractSyntaxTreeBuilderContext& context) {
2✔
208
    // `<decl_specs> <abstract_declarator>` — e.g. `int *` as a parameter type.
209
    context.pushFormalArgument(FormalArgument { context.popDeclarationSpecifiers(), context.popDeclarator() });
2✔
210
}
2✔
211

212
// abstract_declarator ::= <pointer>  (unnamed pointer parameter / type name)
213
void abstractPointerDeclarator(AbstractSyntaxTreeBuilderContext& context) {
2✔
214
    context.pushDeclarator(std::make_unique<Declarator>(
2✔
215
            std::make_unique<Identifier>(TerminalSymbol { "id", "", translation_unit::Context { "", 0 } }),
12✔
216
            context.popPointers()));
4✔
217
}
2✔
218

219
void parameterBaseTypeDeclaration(AbstractSyntaxTreeBuilderContext& context) {
8✔
220
    context.pushFormalArgument(FormalArgument { context.popDeclarationSpecifiers() });
8✔
221
}
8✔
222

223
void formalArguments(AbstractSyntaxTreeBuilderContext& context) {
88✔
224
    FormalArguments formalArguments;
88✔
225
    formalArguments.push_back(context.popFormalArgument());
88✔
226
    context.pushFormalArguments(std::move(formalArguments));
88✔
227
}
88✔
228

229
void addFormalArgument(AbstractSyntaxTreeBuilderContext& context) {
110✔
230
    context.popTerminal();
110✔
231
    auto formalArguments = context.popFormalArguments();
110✔
232
    formalArguments.push_back(context.popFormalArgument());
110✔
233
    context.pushFormalArguments(std::move(formalArguments));
110✔
234
}
110✔
235

236
void formalArgumentsDeclaration(AbstractSyntaxTreeBuilderContext& context) {
88✔
237
    context.pushArgumentsDeclaration(std::make_pair(context.popFormalArguments(), false));
88✔
238
}
88✔
239

240
void formalArgumentsWithVararg(AbstractSyntaxTreeBuilderContext& context) {
×
241
    context.popTerminal();
×
242
    context.popTerminal();
×
243
    //context.pushArgumentsDeclaration(std::make_pair(context.popFormalArguments(), true));
244
    throw std::runtime_error { "formalArgumentsWithVararg is not implemented yet" };
×
245
}
246

247
void integerConstant(AbstractSyntaxTreeBuilderContext& context) {
1,470✔
248
    auto constant = context.popTerminal();
1,470✔
249
    context.pushConstant( { constant.value, type::signedInteger(), constant.context });
1,470✔
250
}
1,470✔
251

252
void characterConstant(AbstractSyntaxTreeBuilderContext& context) {
14✔
253
    auto constant = context.popTerminal();
14✔
254
    context.pushConstant( { constant.value, type::signedCharacter(), constant.context });
14✔
255
}
14✔
256

257
void floatConstant(AbstractSyntaxTreeBuilderContext& context) {
×
258
    auto constant = context.popTerminal();
×
259
    throw std::runtime_error { "floating constants not implemented yet" };
×
260
    // context.pushConstant( { constant.value, type::floating(), constant.context });
261
}
×
262

263
void enumerationConstant(AbstractSyntaxTreeBuilderContext& context) {
×
264
    auto constant = context.popTerminal();
×
265
    throw std::runtime_error { "enumerationConstant is not implemented yet" };
×
266
}
×
267

268
void identifierExpression(AbstractSyntaxTreeBuilderContext& context) {
2,942✔
269
    auto identifier = context.popTerminal();
2,942✔
270
    context.pushExpression(std::make_unique<IdentifierExpression>(identifier.value, identifier.context));
2,942✔
271
}
2,942✔
272

273
void constantExpression(AbstractSyntaxTreeBuilderContext& context) {
1,484✔
274
    context.pushExpression(std::make_unique<ConstantExpression>(context.popConstant()));
1,484✔
275
}
1,484✔
276

277
void stringLiteralExpression(AbstractSyntaxTreeBuilderContext& context) {
870✔
278
    auto literal = context.popTerminal();
870✔
279
    context.pushExpression(std::make_unique<StringLiteralExpression>(literal.value, literal.context));
870✔
280
}
870✔
281

282
void arrayAccess(AbstractSyntaxTreeBuilderContext& context) {
2✔
283
    context.popTerminal(); // ]
2✔
284
    context.popTerminal(); // [
2✔
285
    auto subscriptExpression = context.popExpression();
2✔
286
    auto postfixExpression = context.popExpression();
2✔
287
    context.pushExpression(std::make_unique<ArrayAccess>(std::move(postfixExpression), std::move(subscriptExpression)));
2✔
288
}
2✔
289

290
void functionCall(AbstractSyntaxTreeBuilderContext& context) {
978✔
291
    context.popTerminal(); // )
978✔
292
    context.popTerminal(); // (
978✔
293
    context.pushExpression(std::make_unique<FunctionCall>(context.popExpression(), context.popActualArgumentsList()));
978✔
294
}
978✔
295

296
void noargFunctionCall(AbstractSyntaxTreeBuilderContext& context) {
24✔
297
    context.popTerminal(); // )
24✔
298
    context.popTerminal(); // (
24✔
299
    context.pushExpression(std::make_unique<FunctionCall>(context.popExpression()));
24✔
300
}
24✔
301

302
void directMemberAccess(AbstractSyntaxTreeBuilderContext& context) {
×
303
    throw std::runtime_error { "directMemberAccess is not implemented yet" };
×
304
}
305

306
void pointeeMemberAccess(AbstractSyntaxTreeBuilderContext& context) {
×
307
    throw std::runtime_error { "pointeeMemberAccess is not implemented yet" };
×
308
}
309

310
void postfixIncrementDecrement(AbstractSyntaxTreeBuilderContext& context) {
30✔
311
    context.pushExpression(std::make_unique<PostfixExpression>(context.popExpression(), std::make_unique<Operator>(context.popTerminal().type)));
30✔
312
}
30✔
313

314
void prefixIncrementDecrement(AbstractSyntaxTreeBuilderContext& context) {
28✔
315
    context.pushExpression(std::make_unique<PrefixExpression>(std::make_unique<Operator>(context.popTerminal().value), context.popExpression()));
28✔
316
}
28✔
317

318
void unaryExpression(AbstractSyntaxTreeBuilderContext& context) {
570✔
319
    context.pushExpression(std::make_unique<UnaryExpression>(std::make_unique<Operator>(context.popTerminal().value), context.popExpression()));
570✔
320
}
570✔
321

322
void sizeofExpression(AbstractSyntaxTreeBuilderContext& context) {
×
323
    throw std::runtime_error { "sizeofExpression is not implemented yet" };
×
324
}
325

326
void sizeofTypeExpression(AbstractSyntaxTreeBuilderContext& context) {
×
327
    throw std::runtime_error { "sizeofTypeExpression is not implemented yet" };
×
328
}
329

330
void typeCast(AbstractSyntaxTreeBuilderContext& context) {
×
331
    context.popTerminal(); // )
×
332
    //context.pushExpression(std::make_unique<TypeCast>(context.popTypeName(), context.popExpression()));
333
    context.popTerminal(); // (
×
334
    throw std::runtime_error { "typeCast is not implemented yet" };
×
335
}
336

337
void arithmeticExpression(AbstractSyntaxTreeBuilderContext& context) {
134✔
338
    auto rightHandSide = context.popExpression();
134✔
339
    auto leftHandSide = context.popExpression();
134✔
340
    auto arithmeticOperator = std::make_unique<Operator>(context.popTerminal().value);
134✔
341
    context.pushExpression(std::make_unique<ArithmeticExpression>(std::move(leftHandSide), std::move(arithmeticOperator), std::move(rightHandSide)));
134✔
342
}
134✔
343

344
void shiftExpression(AbstractSyntaxTreeBuilderContext& context) {
30✔
345
    auto additionExpression = context.popExpression();
30✔
346
    auto shiftExpression = context.popExpression();
30✔
347
    auto shiftOperator = std::make_unique<Operator>(context.popTerminal().value);
30✔
348
    context.pushExpression(std::make_unique<ShiftExpression>(std::move(shiftExpression), std::move(shiftOperator), std::move(additionExpression)));
30✔
349
}
30✔
350

351
void relationalExpression(AbstractSyntaxTreeBuilderContext& context) {
198✔
352
    auto rightHandSide = context.popExpression();
198✔
353
    auto leftHandSide = context.popExpression();
198✔
354
    auto comparisonOperator = std::make_unique<Operator>(context.popTerminal().value);
198✔
355
    context.pushExpression(std::make_unique<ComparisonExpression>(std::move(leftHandSide), std::move(comparisonOperator), std::move(rightHandSide)));
198✔
356
}
198✔
357

358
void bitwiseExpression(AbstractSyntaxTreeBuilderContext& context) {
16✔
359
    auto rightHandSide = context.popExpression();
16✔
360
    auto leftHandSide = context.popExpression();
16✔
361
    auto bitwiseOperator = std::make_unique<Operator>(context.popTerminal().value);
16✔
362
    context.pushExpression(std::make_unique<BitwiseExpression>(std::move(leftHandSide), std::move(bitwiseOperator), std::move(rightHandSide)));
16✔
363
}
16✔
364

365
void logicalAndExpression(AbstractSyntaxTreeBuilderContext& context) {
12✔
366
    context.popTerminal();
12✔
367
    auto rightHandSide = context.popExpression();
12✔
368
    auto leftHandSide = context.popExpression();
12✔
369
    context.pushExpression(std::make_unique<LogicalAndExpression>(std::move(leftHandSide), std::move(rightHandSide)));
12✔
370
}
12✔
371

372
void logicalOrExpression(AbstractSyntaxTreeBuilderContext& context) {
12✔
373
    context.popTerminal();
12✔
374
    auto rightHandSide = context.popExpression();
12✔
375
    auto leftHandSide = context.popExpression();
12✔
376
    context.pushExpression(std::make_unique<LogicalOrExpression>(std::move(leftHandSide), std::move(rightHandSide)));
12✔
377
}
12✔
378

379
void conditionalExpression(AbstractSyntaxTreeBuilderContext& context) {
×
380
    throw std::runtime_error { "conditionalExpression is not implemented yet" };
×
381
}
382

383
void assignmentExpression(AbstractSyntaxTreeBuilderContext& context) {
524✔
384
    auto rightHandSide = context.popExpression();
524✔
385
    auto leftHandSide = context.popExpression();
524✔
386
    auto assignmentOperator = std::make_unique<Operator>(context.popTerminal().value);
524✔
387
    context.pushExpression(
524✔
388
            std::make_unique<AssignmentExpression>(std::move(leftHandSide), std::move(assignmentOperator), std::move(rightHandSide)));
1,048✔
389
}
524✔
390

391
void initializer(AbstractSyntaxTreeBuilderContext& context) {
×
392
    throw std::runtime_error { "initializer is not implemented yet" };
×
393
}
394

395
void initializedDeclarator(AbstractSyntaxTreeBuilderContext& context) {
596✔
396
    auto declarator = context.popDeclarator();
596✔
397
    context.pushInitializedDeclarator(std::make_unique<InitializedDeclarator>(std::move(declarator)));
596✔
398
}
596✔
399

400
void initializedDeclaratorWithInitializer(AbstractSyntaxTreeBuilderContext& context) {
68✔
401
    auto declarator = context.popDeclarator();
68✔
402
    auto initializerExpression = context.popExpression();
68✔
403
    context.pushInitializedDeclarator(std::make_unique<InitializedDeclarator>(std::move(declarator), std::move(initializerExpression)));
68✔
404
}
68✔
405

406
void initializedDeclaratorList(AbstractSyntaxTreeBuilderContext& context) {
542✔
407
    std::vector<std::unique_ptr<InitializedDeclarator>> declarators;
542✔
408
    declarators.push_back(context.popInitializedDeclarator());
542✔
409
    context.pushInitializedDeclarators(std::move(declarators));
542✔
410
}
542✔
411

412
void addToInitializedDeclaratorList(AbstractSyntaxTreeBuilderContext& context) {
122✔
413
    context.popTerminal();
122✔
414
    auto initializedDeclarators = context.popInitializedDeclarators();
122✔
415
    initializedDeclarators.push_back(context.popInitializedDeclarator());
122✔
416
    context.pushInitializedDeclarators(std::move(initializedDeclarators));
122✔
417
}
122✔
418

419
void initializedDeclaration(AbstractSyntaxTreeBuilderContext& context) {
542✔
420
    context.popTerminal();
542✔
421
    auto declarationSpecifiers = context.popDeclarationSpecifiers();
542✔
422
    auto initializedDeclarators = context.popInitializedDeclarators();
542✔
423
    context.pushDeclaration(std::make_unique<Declaration>(declarationSpecifiers, std::move(initializedDeclarators)));
542✔
424
}
542✔
425

426
void declaration(AbstractSyntaxTreeBuilderContext& context) {
×
427
    context.popTerminal();
×
428
    auto declarationSpecifiers = context.popDeclarationSpecifiers();
×
429
    context.pushDeclaration(std::make_unique<Declaration>(declarationSpecifiers));
×
430
}
×
431

432
void declarationList(AbstractSyntaxTreeBuilderContext& context) {
320✔
433
    std::vector<std::unique_ptr<Declaration>> declarations;
320✔
434
    declarations.push_back(context.popDeclaration());
320✔
435
    context.pushDeclarationList(std::move(declarations));
320✔
436
}
320✔
437

438
void addDeclarationToList(AbstractSyntaxTreeBuilderContext& context) {
108✔
439
    auto declarations = context.popDeclarationList();
108✔
440
    declarations.push_back(context.popDeclaration());
108✔
441
    context.pushDeclarationList(std::move(declarations));
108✔
442
}
108✔
443

444
void expressionList(AbstractSyntaxTreeBuilderContext& context) {
2✔
445
    context.popTerminal();
2✔
446
    auto rightHandSide = context.popExpression();
2✔
447
    auto leftHandSide = context.popExpression();
2✔
448
    context.pushExpression(std::make_unique<ExpressionList>(std::move(leftHandSide), std::move(rightHandSide)));
2✔
449
}
2✔
450

451
void pointer(AbstractSyntaxTreeBuilderContext& context) {
72✔
452
    context.popTerminal();
72✔
453
    context.newPointer(Pointer { });
72✔
454
}
72✔
455

456
void pointerToPointer(AbstractSyntaxTreeBuilderContext& context) {
×
457
    context.popTerminal();
×
458
    context.pointerToPointer(Pointer { });
×
459
}
×
460

461
void qualifiedPointer(AbstractSyntaxTreeBuilderContext& context) {
×
462
    context.popTerminal();
×
463
    context.newPointer(context.popTypeQualifierList());
×
464
}
×
465

466
void qualifiedPointerToPointer(AbstractSyntaxTreeBuilderContext& context) {
×
467
    context.popTerminal();
×
468
    context.pointerToPointer( { context.popTypeQualifierList() });
×
469
}
×
470

471
void ifStatement(AbstractSyntaxTreeBuilderContext& context) {
38✔
472
    context.popTerminal();
38✔
473
    context.popTerminal();
38✔
474
    context.popTerminal();
38✔
475
    context.pushStatement(std::make_unique<IfStatement>(context.popExpression(), context.popStatement()));
38✔
476
}
38✔
477

478
void ifElseStatement(AbstractSyntaxTreeBuilderContext& context) {
18✔
479
    context.popTerminal();
18✔
480
    context.popTerminal();
18✔
481
    context.popTerminal();
18✔
482
    context.popTerminal();
18✔
483
    auto falsyStatement = context.popStatement();
18✔
484
    auto truthyStatement = context.popStatement();
18✔
485
    context.pushStatement(std::make_unique<IfElseStatement>(context.popExpression(), std::move(truthyStatement), std::move(falsyStatement)));
18✔
486
}
18✔
487

488
void whileLoopStatement(AbstractSyntaxTreeBuilderContext& context) {
26✔
489
    context.popTerminal();
26✔
490
    context.popTerminal();
26✔
491
    context.popTerminal();
26✔
492
    auto loopHeader = std::make_unique<WhileLoopHeader>(context.popExpression());
26✔
493
    auto body = context.popStatement();
26✔
494
    context.pushStatement(std::make_unique<LoopStatement>(std::move(loopHeader), std::move(body)));
26✔
495
}
26✔
496

497
void statementList(AbstractSyntaxTreeBuilderContext& context) {
692✔
498
    context.newStatementList(context.popStatement());
692✔
499
}
692✔
500

501
void addToStatementList(AbstractSyntaxTreeBuilderContext& context) {
1,460✔
502
    context.addToStatementList(context.popStatement());
1,460✔
503
}
1,460✔
504

505
void returnExpressionStatement(AbstractSyntaxTreeBuilderContext& context) {
546✔
506
    context.popTerminal();
546✔
507
    context.popTerminal();
546✔
508
    context.pushStatement(std::make_unique<ReturnStatement>(context.popExpression()));
546✔
509
}
546✔
510

511
void returnVoidStatement(AbstractSyntaxTreeBuilderContext& context) {
22✔
512
    context.popTerminal();
22✔
513
    context.popTerminal();
22✔
514
    context.pushStatement(std::make_unique<VoidReturnStatement>());
22✔
515
}
22✔
516

517
void createActualArgumentsList(AbstractSyntaxTreeBuilderContext& context) {
978✔
518
    context.newActualArgumentsList(context.popExpression());
978✔
519
}
978✔
520

521
void addToActualArgumentsList(AbstractSyntaxTreeBuilderContext& context) {
1,170✔
522
    context.popTerminal();
1,170✔
523
    context.addToActualArgumentsList(context.popExpression());
1,170✔
524
}
1,170✔
525

526
void declarationCompound(AbstractSyntaxTreeBuilderContext& context) {
×
527
    context.popTerminal();
×
528
    context.popTerminal();
×
529
    context.pushStatement(std::make_unique<Block>(context.popDeclarationList(), std::vector<std::unique_ptr<AbstractSyntaxTreeNode>> { }));
×
530
}
×
531

532
void statementCompound(AbstractSyntaxTreeBuilderContext& context) {
374✔
533
    context.popTerminal();
374✔
534
    context.popTerminal();
374✔
535
    context.pushStatement(std::make_unique<Block>(std::vector<std::unique_ptr<Declaration>> { }, context.popStatementList()));
374✔
536
}
374✔
537

538
void fullCompound(AbstractSyntaxTreeBuilderContext& context) {
318✔
539
    context.popTerminal();
318✔
540
    context.popTerminal();
318✔
541
    auto declarations = context.popDeclarationList();
318✔
542
    auto statements = context.popStatementList();
318✔
543
    context.pushStatement(std::make_unique<Block>(std::move(declarations), std::move(statements)));
318✔
544
}
318✔
545

546
void emptyCompound(AbstractSyntaxTreeBuilderContext& context) {
12✔
547
    context.popTerminal();
12✔
548
    context.popTerminal();
12✔
549
    context.pushStatement(std::make_unique<Block>(
12✔
550
                std::vector<std::unique_ptr<Declaration>> { },
12✔
551
                std::vector<std::unique_ptr<AbstractSyntaxTreeNode>>{}));
12✔
552
}
12✔
553

554
void expressionStatement(AbstractSyntaxTreeBuilderContext& context) {
1,434✔
555
    context.popTerminal();
1,434✔
556
    context.pushStatement(context.popExpression());
1,434✔
557
}
1,434✔
558

559
void emptyStatement(AbstractSyntaxTreeBuilderContext& context) {
14✔
560
    context.popTerminal();
14✔
561
    // Null statement `;` still occupies a statement slot so parents (if/while/for/stat_list)
562
    // can pop a body without under-flowing the AST statement stack.
563
    context.pushStatement(std::make_unique<Block>(
14✔
564
            std::vector<std::unique_ptr<Declaration>> { },
14✔
565
            std::vector<std::unique_ptr<AbstractSyntaxTreeNode>> { }));
14✔
566
}
14✔
567

568
void functionDefinition(AbstractSyntaxTreeBuilderContext& context) {
560✔
569
    auto declarationSpecifiers = context.popDeclarationSpecifiers();
560✔
570
    auto declarator = context.popDeclarator();
560✔
571
    auto statement = context.popStatement();
560✔
572
    context.pushStatement(std::make_unique<FunctionDefinition>(std::move(declarationSpecifiers), std::move(declarator), std::move(statement)));
560✔
573
}
560✔
574

575
void defaultReturnTypeFunctionDefinition(AbstractSyntaxTreeBuilderContext& context) {
×
576
    DeclarationSpecifiers defaultReturnTypeSpecifiers { TypeSpecifier { type::signedInteger(), "int" } };
×
577
    context.pushStatement(std::make_unique<FunctionDefinition>(defaultReturnTypeSpecifiers, context.popDeclarator(), context.popStatement()));
×
578
}
×
579

580
void externalFunctionDefinition(AbstractSyntaxTreeBuilderContext& context) {
560✔
581
    context.pushExternalDeclaration(context.popStatement());
560✔
582
}
560✔
583

584
void externalDeclaration(AbstractSyntaxTreeBuilderContext& context) {
114✔
585
    context.pushExternalDeclaration(context.popDeclaration());
114✔
586
}
114✔
587

588
void translationUnit(AbstractSyntaxTreeBuilderContext& context) {
448✔
589
    context.addToTranslationUnit(context.popExternalDeclaration());
448✔
590
}
448✔
591

592
void addToTranslationUnit(AbstractSyntaxTreeBuilderContext& context) {
226✔
593
    context.addToTranslationUnit(context.popExternalDeclaration());
226✔
594
}
226✔
595

596
ContextualSyntaxNodeBuilder::ContextualSyntaxNodeBuilder(const parser::Grammar& grammar) {
456✔
597
    this->grammar = &grammar;
456✔
598

599
    int s_type_specifier = grammar.symbolId("<type_spec>");
456✔
600
    nodeCreatorRegistry[s_type_specifier][{ grammar.symbolId("short") }] = shortType;
1,824✔
601
    nodeCreatorRegistry[s_type_specifier][{ grammar.symbolId("int") }] = integerType;
1,824✔
602
    nodeCreatorRegistry[s_type_specifier][{ grammar.symbolId("long") }] = longType;
1,824✔
603
    nodeCreatorRegistry[s_type_specifier][{ grammar.symbolId("char") }] = characterType;
1,824✔
604
    nodeCreatorRegistry[s_type_specifier][{ grammar.symbolId("void") }] = voidType;
1,824✔
605
    nodeCreatorRegistry[s_type_specifier][{ grammar.symbolId("float") }] = floatType;
1,824✔
606
    nodeCreatorRegistry[s_type_specifier][{ grammar.symbolId("double") }] = doubleType;
1,824✔
607
    nodeCreatorRegistry[s_type_specifier][{ grammar.symbolId("signed") }] = signedType;
1,824✔
608
    nodeCreatorRegistry[s_type_specifier][{ grammar.symbolId("unsigned") }] = unsignedType;
1,824✔
609
    nodeCreatorRegistry[s_type_specifier][{ grammar.symbolId("typedef_name") }] = typedefName;
1,824✔
610
    nodeCreatorRegistry[s_type_specifier][{ grammar.symbolId("<struct_or_union_spec>") }] = structOrUnionType;
1,824✔
611
    nodeCreatorRegistry[s_type_specifier][{ grammar.symbolId("<enum_spec>") }] = enumType;
2,280✔
612

613
    int s_type_qualifier = grammar.symbolId("<type_qualifier>");
456✔
614
    nodeCreatorRegistry[s_type_qualifier][{ grammar.symbolId("const") }] = constQualifier;
1,824✔
615
    nodeCreatorRegistry[s_type_qualifier][{ grammar.symbolId("volatile") }] = volatileQualifier;
2,280✔
616

617
    int s_decl_specs = grammar.symbolId("<decl_specs>");
456✔
618
    nodeCreatorRegistry[s_decl_specs][{ s_type_specifier }] = declarationTypeSpecifier;
912✔
619
    nodeCreatorRegistry[s_decl_specs][{ s_type_specifier, s_decl_specs }] = addDeclarationTypeSpecifier;
912✔
620
    nodeCreatorRegistry[s_decl_specs][{ grammar.symbolId("<storage_class_spec>") }] = declarationStorageClassSpecifier;
1,824✔
621
    nodeCreatorRegistry[s_decl_specs][{ grammar.symbolId("<storage_class_spec>"), s_decl_specs }] = addDeclarationStorageClassSpecifier;
1,824✔
622
    nodeCreatorRegistry[s_decl_specs][{ s_type_qualifier }] = declarationTypeQualifier;
912✔
623
    nodeCreatorRegistry[s_decl_specs][{ s_type_qualifier, s_decl_specs }] = addDeclarationTypeQualifier;
1,368✔
624

625
    int s_direct_declarator = grammar.symbolId("<direct_declarator>");
912✔
626
    int s_declarator = grammar.symbolId("<declarator>");
912✔
627
    int s_param_type_list = grammar.symbolId("<param_type_list>");
912✔
628
    int s_identifier = grammar.symbolId("id");
912✔
629
    int s_open_paren = grammar.symbolId("(");
912✔
630
    int s_close_paren = grammar.symbolId(")");
912✔
631
    int s_open_bracket = grammar.symbolId("[");
912✔
632
    int s_close_bracket = grammar.symbolId("]");
456✔
633

634
    nodeCreatorRegistry[s_direct_declarator][{ s_identifier }] = identifierDeclarator;
912✔
635
    nodeCreatorRegistry[s_direct_declarator][{ s_open_paren, s_declarator, s_close_paren }] = parenthesizedDeclarator;
912✔
636
    nodeCreatorRegistry[s_direct_declarator][{ s_direct_declarator, s_open_bracket, grammar.symbolId("<const_exp>"), s_close_bracket }] = arrayDeclarator;
1,824✔
637
    nodeCreatorRegistry[s_direct_declarator][{ s_direct_declarator, s_open_bracket, s_close_bracket }] = abstractArrayDeclarator;
912✔
638
    nodeCreatorRegistry[s_direct_declarator][{ s_direct_declarator, s_open_paren, s_param_type_list, s_close_paren }] = functionDeclarator;
912✔
639
    nodeCreatorRegistry[s_direct_declarator][{ s_direct_declarator, s_open_paren, s_close_paren }] = noargFunctionDeclarator;
1,368✔
640

641
    int s_pointer = grammar.symbolId("<pointer>" );
456✔
642
    nodeCreatorRegistry[s_declarator][{ s_pointer, s_direct_declarator }] = pointerToDeclarator;
912✔
643
    nodeCreatorRegistry[s_declarator][{ s_direct_declarator }] = declarator;
1,368✔
644

645
    int s_param_decl = grammar.symbolId("<param_decl>");
912✔
646
    int s_abstract_declarator = grammar.symbolId("<abstract_declarator>");
456✔
647
    nodeCreatorRegistry[s_param_decl][{ s_decl_specs, s_declarator }] = parameterDeclaration;
912✔
648
    nodeCreatorRegistry[s_param_decl][{ s_decl_specs, s_abstract_declarator }] = abstractParameterDeclaration;
912✔
649
    nodeCreatorRegistry[s_param_decl][{ s_decl_specs }] = parameterBaseTypeDeclaration;
912✔
650

651
    // Minimal abstract declarators used in parameter types (e.g. `int f(int *)`).
652
    nodeCreatorRegistry[s_abstract_declarator][{ s_pointer }] = abstractPointerDeclarator;
1,368✔
653

654
    int s_param_list = grammar.symbolId("<param_list>");
912✔
655
    int s_comma = grammar.symbolId(",");
456✔
656
    nodeCreatorRegistry[s_param_list][{ s_param_decl }] = formalArguments;
912✔
657
    nodeCreatorRegistry[s_param_list][{ s_param_list, s_comma, s_param_decl }] = addFormalArgument;
912✔
658

659
    nodeCreatorRegistry[s_param_type_list][{ s_param_list }] = formalArgumentsDeclaration;
912✔
660
    nodeCreatorRegistry[s_param_type_list][{ s_param_list, s_comma, grammar.symbolId("...") }] = formalArgumentsWithVararg;
2,280✔
661

662
    // K&R identifier parameter list: `f(a, b)` — not the modern `f(int a, int b)`.
663
    int s_id_list = grammar.symbolId("<id_list>");
456✔
664
    nodeCreatorRegistry[s_id_list][{ s_identifier }] = notImplementedYet("K&R identifier parameter lists");
1,368✔
665
    nodeCreatorRegistry[s_id_list][{ s_id_list, s_comma, s_identifier }] = notImplementedYet("K&R identifier parameter lists");
1,368✔
666
    nodeCreatorRegistry[s_direct_declarator][{ s_direct_declarator, s_open_paren, s_id_list, s_close_paren }] =
1,368✔
667
            notImplementedYet("K&R identifier parameter lists");
1,368✔
668

669
    int s_constant = grammar.symbolId("<const>");
456✔
670
    nodeCreatorRegistry[s_constant][{ grammar.symbolId("int_const") }] = integerConstant;
1,824✔
671
    nodeCreatorRegistry[s_constant][{ grammar.symbolId("char_const") }] = characterConstant;
1,824✔
672
    nodeCreatorRegistry[s_constant][{ grammar.symbolId("float_const") }] = floatConstant;
1,824✔
673
    nodeCreatorRegistry[s_constant][{ grammar.symbolId("enumeration_const") }] = enumerationConstant;
2,280✔
674

675
    int s_exp = grammar.symbolId("<exp>");
912✔
676
    int s_primary_exp = grammar.symbolId("<primary_exp>");
456✔
677
    nodeCreatorRegistry[s_primary_exp][{ s_identifier }] = identifierExpression;
912✔
678
    nodeCreatorRegistry[s_primary_exp][{ s_constant }] = constantExpression;
912✔
679
    nodeCreatorRegistry[s_primary_exp][{ grammar.symbolId("string") }] = stringLiteralExpression;
1,824✔
680
    nodeCreatorRegistry[s_primary_exp][{ s_open_paren, s_exp, s_close_paren }] = parenthesizedExpression;
1,368✔
681

682
    int s_argument_exp_list = grammar.symbolId("<argument_exp_list>");
912✔
683
    int s_postfix_exp = grammar.symbolId("<postfix_exp>");
456✔
684
    nodeCreatorRegistry[s_postfix_exp][{ s_primary_exp }] = doNothing;
912✔
685
    nodeCreatorRegistry[s_postfix_exp][{ s_postfix_exp, s_open_bracket, s_exp, s_close_bracket }] = arrayAccess;
912✔
686
    nodeCreatorRegistry[s_postfix_exp][{ s_postfix_exp, s_open_paren, s_argument_exp_list, s_close_paren }] = functionCall;
912✔
687
    nodeCreatorRegistry[s_postfix_exp][{ s_postfix_exp, s_open_paren, s_close_paren }] = noargFunctionCall;
912✔
688
    nodeCreatorRegistry[s_postfix_exp][{ s_postfix_exp, grammar.symbolId(".") }] = directMemberAccess;
1,824✔
689
    nodeCreatorRegistry[s_postfix_exp][{ s_postfix_exp, grammar.symbolId("->") }] = pointeeMemberAccess;
1,824✔
690
    nodeCreatorRegistry[s_postfix_exp][{ s_postfix_exp, grammar.symbolId("++") }] = postfixIncrementDecrement;
1,824✔
691
    nodeCreatorRegistry[s_postfix_exp][{ s_postfix_exp, grammar.symbolId("--") }] = postfixIncrementDecrement;
2,280✔
692

693
    int s_cast_exp = grammar.symbolId("<cast_exp>");
912✔
694
    int s_unary_exp = grammar.symbolId("<unary_exp>");
912✔
695
    int s_unary_operator = grammar.symbolId("<unary_operator>");
456✔
696
    nodeCreatorRegistry[s_unary_exp][{ s_postfix_exp }] = doNothing;
912✔
697
    nodeCreatorRegistry[s_unary_exp][{ grammar.symbolId("++"), s_unary_exp }] = prefixIncrementDecrement;
1,824✔
698
    nodeCreatorRegistry[s_unary_exp][{ grammar.symbolId("--"), s_unary_exp }] = prefixIncrementDecrement;
1,824✔
699
    nodeCreatorRegistry[s_unary_exp][{ s_unary_operator, s_cast_exp }] = unaryExpression;
912✔
700
    nodeCreatorRegistry[s_unary_exp][{ grammar.symbolId("sizeof"), s_unary_exp }] = sizeofExpression;
1,824✔
701
    nodeCreatorRegistry[s_unary_exp][{ grammar.symbolId("sizeof"), s_open_paren, grammar.symbolId("<type_name>"), s_close_paren }] = sizeofTypeExpression;
2,736✔
702

703
    nodeCreatorRegistry[s_cast_exp][{ s_unary_exp }] = doNothing;
912✔
704
    nodeCreatorRegistry[s_cast_exp][{ s_open_paren, grammar.symbolId("<type_name>"), s_close_paren, s_cast_exp }] = typeCast;
2,280✔
705

706
    // type_name / spec_qualifier_list feed casts and sizeof(type); stub until type names are built.
707
    int s_spec_qualifier_list = grammar.symbolId("<spec_qualifier_list>");
912✔
708
    int s_type_name = grammar.symbolId("<type_name>");
456✔
709
    nodeCreatorRegistry[s_spec_qualifier_list][{ s_type_specifier }] = notImplementedYet("type names (casts/sizeof)");
1,368✔
710
    nodeCreatorRegistry[s_spec_qualifier_list][{ s_type_specifier, s_spec_qualifier_list }] =
1,368✔
711
            notImplementedYet("type names (casts/sizeof)");
1,368✔
712
    nodeCreatorRegistry[s_spec_qualifier_list][{ s_type_qualifier }] = notImplementedYet("type names (casts/sizeof)");
1,368✔
713
    nodeCreatorRegistry[s_spec_qualifier_list][{ s_type_qualifier, s_spec_qualifier_list }] =
1,368✔
714
            notImplementedYet("type names (casts/sizeof)");
1,368✔
715
    nodeCreatorRegistry[s_type_name][{ s_spec_qualifier_list }] = notImplementedYet("type names (casts/sizeof)");
1,368✔
716
    nodeCreatorRegistry[s_type_name][{ s_spec_qualifier_list, s_abstract_declarator }] =
1,368✔
717
            notImplementedYet("type names (casts/sizeof)");
1,368✔
718

719
    int s_mult_exp = grammar.symbolId("<mult_exp>");
456✔
720
    nodeCreatorRegistry[s_mult_exp][{ s_cast_exp }] = doNothing;
912✔
721
    nodeCreatorRegistry[s_mult_exp][{ s_mult_exp, grammar.symbolId("*"), s_cast_exp }] = arithmeticExpression;
1,824✔
722
    nodeCreatorRegistry[s_mult_exp][{ s_mult_exp, grammar.symbolId("/"), s_cast_exp }] = arithmeticExpression;
1,824✔
723
    nodeCreatorRegistry[s_mult_exp][{ s_mult_exp, grammar.symbolId("%"), s_cast_exp }] = arithmeticExpression;
2,280✔
724

725
    int s_additive_exp = grammar.symbolId("<additive_exp>");
456✔
726
    nodeCreatorRegistry[s_additive_exp][{ s_mult_exp }] = doNothing;
912✔
727
    nodeCreatorRegistry[s_additive_exp][{ s_additive_exp, grammar.symbolId("+"), s_mult_exp }] = arithmeticExpression;
1,824✔
728
    nodeCreatorRegistry[s_additive_exp][{ s_additive_exp, grammar.symbolId("-"), s_mult_exp }] = arithmeticExpression;
2,280✔
729

730
    int s_shift_exp = grammar.symbolId("<shift_expression>");
456✔
731
    nodeCreatorRegistry[s_shift_exp][{ s_additive_exp }] = doNothing;
912✔
732
    nodeCreatorRegistry[s_shift_exp][{ s_shift_exp, grammar.symbolId("<<"), s_additive_exp }] = shiftExpression;
1,824✔
733
    nodeCreatorRegistry[s_shift_exp][{ s_shift_exp, grammar.symbolId(">>"), s_additive_exp }] = shiftExpression;
2,280✔
734

735
    int s_relational_exp = grammar.symbolId("<relational_exp>");
456✔
736
    nodeCreatorRegistry[s_relational_exp][{ s_shift_exp }] = doNothing;
912✔
737
    nodeCreatorRegistry[s_relational_exp][{ s_relational_exp, grammar.symbolId("<"), s_shift_exp }] = relationalExpression;
1,824✔
738
    nodeCreatorRegistry[s_relational_exp][{ s_relational_exp, grammar.symbolId(">"), s_shift_exp }] = relationalExpression;
1,824✔
739
    nodeCreatorRegistry[s_relational_exp][{ s_relational_exp, grammar.symbolId("<="), s_shift_exp }] = relationalExpression;
1,824✔
740
    nodeCreatorRegistry[s_relational_exp][{ s_relational_exp, grammar.symbolId(">="), s_shift_exp }] = relationalExpression;
2,280✔
741

742
    int s_equality_exp = grammar.symbolId("<equality_exp>");
456✔
743
    nodeCreatorRegistry[s_equality_exp][{ s_relational_exp }] = doNothing;
912✔
744
    nodeCreatorRegistry[s_equality_exp][{ s_equality_exp, grammar.symbolId("=="), s_relational_exp }] = relationalExpression;
1,824✔
745
    nodeCreatorRegistry[s_equality_exp][{ s_equality_exp, grammar.symbolId("!="), s_relational_exp }] = relationalExpression;
2,280✔
746

747
    int s_and_exp = grammar.symbolId("<and_exp>");
456✔
748
    nodeCreatorRegistry[s_and_exp][{ s_equality_exp }] = doNothing;
912✔
749
    nodeCreatorRegistry[s_and_exp][{ s_and_exp, grammar.symbolId("&"), s_equality_exp }] = bitwiseExpression;
2,280✔
750

751
    int s_exclusive_or_exp = grammar.symbolId("<exclusive_or_exp>");
456✔
752
    nodeCreatorRegistry[s_exclusive_or_exp][{ s_and_exp }] = doNothing;
912✔
753
    nodeCreatorRegistry[s_exclusive_or_exp][{ s_exclusive_or_exp, grammar.symbolId("^"), s_and_exp }] = bitwiseExpression;
2,280✔
754

755
    int s_inclusive_or_exp = grammar.symbolId("<inclusive_or_exp>");
456✔
756
    nodeCreatorRegistry[s_inclusive_or_exp][{ s_exclusive_or_exp }] = doNothing;
912✔
757
    nodeCreatorRegistry[s_inclusive_or_exp][{ s_inclusive_or_exp, grammar.symbolId("|"), s_exclusive_or_exp }] = bitwiseExpression;
2,280✔
758

759
    int s_logical_and_exp = grammar.symbolId("<logical_and_exp>");
456✔
760
    nodeCreatorRegistry[s_logical_and_exp][{ s_inclusive_or_exp }] = doNothing;
912✔
761
    nodeCreatorRegistry[s_logical_and_exp][{ s_logical_and_exp, grammar.symbolId("&&"), s_inclusive_or_exp }] = logicalAndExpression;
2,280✔
762

763
    int s_logical_or_exp = grammar.symbolId("<logical_or_exp>");
456✔
764
    nodeCreatorRegistry[s_logical_or_exp][{ s_logical_and_exp }] = doNothing;
912✔
765
    nodeCreatorRegistry[s_logical_or_exp][{ s_logical_or_exp, grammar.symbolId("||"), s_logical_and_exp }] = logicalOrExpression;
2,280✔
766

767
    int s_conditional_exp = grammar.symbolId("<conditional_exp>");
456✔
768
    nodeCreatorRegistry[s_conditional_exp][{ s_logical_or_exp }] = doNothing;
912✔
769
    nodeCreatorRegistry[s_conditional_exp][{ s_logical_or_exp, grammar.symbolId("?"), s_exp, grammar.symbolId(":"), s_conditional_exp }] = conditionalExpression;
3,192✔
770

771
    int s_assignment = grammar.symbolId("<assignment_exp>");
912✔
772
    int s_assignment_operator = grammar.symbolId("<assignment_operator>");
456✔
773
    nodeCreatorRegistry[s_assignment][{ s_conditional_exp }] = doNothing;
912✔
774
    nodeCreatorRegistry[s_assignment][{ s_unary_exp, s_assignment_operator, s_assignment }] = assignmentExpression;
1,368✔
775

776
    int s_initializer = grammar.symbolId("<initializer>");
912✔
777
    int s_open_brace = grammar.symbolId("{");
912✔
778
    int s_close_brace = grammar.symbolId("}");
456✔
779
    nodeCreatorRegistry[s_initializer][{ s_assignment }] = doNothing;
912✔
780
    nodeCreatorRegistry[s_initializer][{ s_open_brace, grammar.symbolId("<initializer_list>"), s_close_brace }] = initializer;
2,280✔
781

782
    int s_init_declarator = grammar.symbolId("<init_declarator>");
456✔
783
    nodeCreatorRegistry[s_init_declarator][{ s_declarator }] = initializedDeclarator;
912✔
784
    nodeCreatorRegistry[s_init_declarator][{ s_declarator, grammar.symbolId("="), s_initializer }] = initializedDeclaratorWithInitializer;
2,280✔
785

786
    int s_init_declarator_list = grammar.symbolId("<init_declarator_list>");
456✔
787
    nodeCreatorRegistry[s_init_declarator_list][{ s_init_declarator }] = initializedDeclaratorList;
912✔
788
    nodeCreatorRegistry[s_init_declarator_list][{ s_init_declarator_list, s_comma, s_init_declarator }] = addToInitializedDeclaratorList;
1,368✔
789

790
    int s_decl = grammar.symbolId("<decl>");
912✔
791
    int s_semicolon = grammar.symbolId(";");
456✔
792
    nodeCreatorRegistry[s_decl][{ s_decl_specs, s_init_declarator_list, s_semicolon }] = initializedDeclaration;
912✔
793
    nodeCreatorRegistry[s_decl][{ s_decl_specs, s_semicolon }] = declaration;
1,368✔
794

795
    int s_decl_list = grammar.symbolId("<decl_list>");
456✔
796
    nodeCreatorRegistry[s_decl_list][{ s_decl }] = declarationList;
912✔
797
    nodeCreatorRegistry[s_decl_list][{ s_decl_list, s_decl }] = addDeclarationToList;
912✔
798

799
    nodeCreatorRegistry[s_exp][{ s_assignment }] = doNothing;
912✔
800
    nodeCreatorRegistry[s_exp][{ s_exp, s_comma, s_assignment }] = expressionList;
1,368✔
801

802
    int s_type_qualifier_list = grammar.symbolId("<type_qualifier_list>");
456✔
803
    nodeCreatorRegistry[s_type_qualifier_list][{ s_type_qualifier }] = typeQualifierList;
912✔
804
    nodeCreatorRegistry[s_type_qualifier_list][{ s_type_qualifier_list, s_type_qualifier }] = addTypeQualifierToList;
912✔
805

806
    nodeCreatorRegistry[s_pointer][{ grammar.symbolId("*"), s_type_qualifier_list }] = qualifiedPointer;
1,824✔
807
    nodeCreatorRegistry[s_pointer][{ grammar.symbolId("*") }] = pointer;
1,824✔
808
    nodeCreatorRegistry[s_pointer][{ grammar.symbolId("*"), s_type_qualifier_list, s_pointer }] = qualifiedPointerToPointer;
1,824✔
809
    nodeCreatorRegistry[s_pointer][{ grammar.symbolId("*"), s_pointer }] = pointerToPointer;
1,824✔
810

811
    nodeCreatorRegistry[s_unary_operator][{ grammar.symbolId("&") }] = doNothing;
1,824✔
812
    nodeCreatorRegistry[s_unary_operator][{ grammar.symbolId("*") }] = doNothing;
1,824✔
813
    nodeCreatorRegistry[s_unary_operator][{ grammar.symbolId("+") }] = doNothing;
1,824✔
814
    nodeCreatorRegistry[s_unary_operator][{ grammar.symbolId("-") }] = doNothing;
1,824✔
815
    nodeCreatorRegistry[s_unary_operator][{ grammar.symbolId("~") }] = doNothing;
1,824✔
816
    nodeCreatorRegistry[s_unary_operator][{ grammar.symbolId("!") }] = doNothing;
1,824✔
817

818
    nodeCreatorRegistry[s_assignment_operator][{ grammar.symbolId("=") }] = doNothing;
1,824✔
819
    nodeCreatorRegistry[s_assignment_operator][{ grammar.symbolId("*=") }] = doNothing;
1,824✔
820
    nodeCreatorRegistry[s_assignment_operator][{ grammar.symbolId("/=") }] = doNothing;
1,824✔
821
    nodeCreatorRegistry[s_assignment_operator][{ grammar.symbolId("%=") }] = doNothing;
1,824✔
822
    nodeCreatorRegistry[s_assignment_operator][{ grammar.symbolId("+=") }] = doNothing;
1,824✔
823
    nodeCreatorRegistry[s_assignment_operator][{ grammar.symbolId("-=") }] = doNothing;
1,824✔
824
    nodeCreatorRegistry[s_assignment_operator][{ grammar.symbolId("<<=") }] = doNothing;
1,824✔
825
    nodeCreatorRegistry[s_assignment_operator][{ grammar.symbolId(">>=") }] = doNothing;
1,824✔
826
    nodeCreatorRegistry[s_assignment_operator][{ grammar.symbolId("&=") }] = doNothing;
1,824✔
827
    nodeCreatorRegistry[s_assignment_operator][{ grammar.symbolId("^=") }] = doNothing;
1,824✔
828
    nodeCreatorRegistry[s_assignment_operator][{ grammar.symbolId("|=") }] = doNothing;
2,280✔
829

830
    int s_exp_stat = grammar.symbolId("<exp_stat>");
456✔
831
    nodeCreatorRegistry[s_exp_stat][{ s_exp, s_semicolon }] = expressionStatement;
912✔
832
    nodeCreatorRegistry[s_exp_stat][{ s_semicolon }] = emptyStatement;
1,368✔
833

834
    int s_matched = grammar.symbolId("<matched>");
912✔
835
    int s_unmatched = grammar.symbolId("<unmatched>");
912✔
836
    int s_stat = grammar.symbolId("<stat>");
912✔
837
    int s_compound_stat = grammar.symbolId("<compound_stat>");
912✔
838
    int s_jump_stat = grammar.symbolId("<jump_stat>");
912✔
839
    int s_if = grammar.symbolId("if");
456✔
840
    nodeCreatorRegistry[s_matched][{s_if, s_open_paren, s_exp, s_close_paren, s_matched, grammar.symbolId("else"), s_matched }] = ifElseStatement;
1,824✔
841
    nodeCreatorRegistry[s_unmatched][{s_if, s_open_paren, s_exp, s_close_paren, s_stat }] = ifStatement;
912✔
842
    //nodeCreatorRegistry[s_matched][{ grammar.symbolId("switch"), s_open_paren, s_exp, s_close_paren, s_matched }] = switchStatement;
843
    //nodeCreatorRegistry[s_matched][{ grammar.symbolId("<labeled_stat_matched>") }] = labeledStatement; // ??
844
    nodeCreatorRegistry[s_matched][{ s_exp_stat }] = doNothing;
912✔
845
    nodeCreatorRegistry[s_matched][{ s_compound_stat }] = doNothing;
912✔
846
    nodeCreatorRegistry[s_matched][{ s_jump_stat }] = doNothing;
912✔
847

848
    nodeCreatorRegistry[s_stat][{ s_matched }] = doNothing;
912✔
849
    nodeCreatorRegistry[s_stat][{ s_unmatched }] = doNothing;
1,368✔
850

851
    int s_stat_list = grammar.symbolId("<stat_list>");
456✔
852
    nodeCreatorRegistry[s_stat_list][{ s_stat }] = statementList;
912✔
853
    nodeCreatorRegistry[s_stat_list][{ s_stat_list, s_stat }] = addToStatementList;
1,368✔
854

855
    int s_return = grammar.symbolId("return");
456✔
856
    //nodeCreatorRegistry[s_jump_stat][{ grammar.symbolId("goto"), s_identifier, s_semicolon }] = gotoStatement;
857
    nodeCreatorRegistry[s_jump_stat][{ grammar.symbolId("continue"), s_semicolon }] = loopJumpStatement;
1,824✔
858
    nodeCreatorRegistry[s_jump_stat][{ grammar.symbolId("break"), s_semicolon }] = loopJumpStatement;
1,824✔
859
    nodeCreatorRegistry[s_jump_stat][{ s_return, s_exp, s_semicolon }] = returnExpressionStatement;
912✔
860
    nodeCreatorRegistry[s_jump_stat][{ s_return, s_semicolon }] = returnVoidStatement;
912✔
861

862
    nodeCreatorRegistry[s_argument_exp_list][{ s_assignment }] = createActualArgumentsList;
912✔
863
    nodeCreatorRegistry[s_argument_exp_list][{ s_argument_exp_list, s_comma, s_assignment }] = addToActualArgumentsList;
912✔
864

865
    nodeCreatorRegistry[s_compound_stat][{ s_open_brace, s_decl_list, s_stat_list, s_close_brace}] = fullCompound;
912✔
866
    nodeCreatorRegistry[s_compound_stat][{ s_open_brace, s_stat_list, s_close_brace}] = statementCompound;
912✔
867
    nodeCreatorRegistry[s_compound_stat][{ s_open_brace, s_decl_list, s_close_brace}] = declarationCompound;
912✔
868
    nodeCreatorRegistry[s_compound_stat][{ s_open_brace, s_close_brace}] = emptyCompound;
1,368✔
869

870
    int s_function_definition = grammar.symbolId("<function_definition>");
456✔
871
    nodeCreatorRegistry[s_function_definition][{ s_decl_specs, s_declarator, s_compound_stat }] = functionDefinition;
912✔
872
    nodeCreatorRegistry[s_function_definition][{ s_declarator, s_compound_stat }] = defaultReturnTypeFunctionDefinition;
912✔
873
    // K&R definitions: `int f(a) int a; { ... }` (parameter decls between declarator and body).
874
    nodeCreatorRegistry[s_function_definition][{ s_decl_specs, s_declarator, s_decl_list, s_compound_stat }] =
1,368✔
875
            notImplementedYet("K&R style function definitions");
1,368✔
876
    nodeCreatorRegistry[s_function_definition][{ s_declarator, s_decl_list, s_compound_stat }] =
1,368✔
877
            notImplementedYet("K&R style function definitions");
1,368✔
878

879
    int s_external_decl = grammar.symbolId("<external_decl>");
456✔
880
    nodeCreatorRegistry[s_external_decl][{ s_function_definition }] = externalFunctionDefinition;
912✔
881
    nodeCreatorRegistry[s_external_decl][{ s_decl }] = externalDeclaration;
1,368✔
882

883
    int s_translation_unit = grammar.symbolId("<translation_unit>");
456✔
884
    nodeCreatorRegistry[s_translation_unit][{ s_external_decl }] = translationUnit;
912✔
885
    nodeCreatorRegistry[s_translation_unit][{ s_translation_unit, s_external_decl }] = addToTranslationUnit;
1,368✔
886

887
    int s_iteration_stat_matched = grammar.symbolId("<iteration_stat_matched>");
912✔
888
    int s_iteration_stat_unmatched = grammar.symbolId("<iteration_stat_unmatched>");
456✔
889
    nodeCreatorRegistry[s_matched][{ s_iteration_stat_matched }] = doNothing;
912✔
890
    nodeCreatorRegistry[s_unmatched][{ s_iteration_stat_unmatched }] = doNothing;
1,368✔
891

892
    int s_while = grammar.symbolId("while");
912✔
893
    int s_for = grammar.symbolId("for");
456✔
894
    nodeCreatorRegistry[s_iteration_stat_matched][{ s_while, s_open_paren, s_exp, s_close_paren, s_matched }] = whileLoopStatement;
912✔
895
    nodeCreatorRegistry[s_iteration_stat_unmatched][{ s_while, s_open_paren, s_exp, s_close_paren, s_unmatched }] = whileLoopStatement;
912✔
896

897
    auto forLoop = [](bool hasInit, bool hasClause, bool hasIncrement) {
3,648✔
898
        return [=](AbstractSyntaxTreeBuilderContext& context) {
40✔
899
            for (int i = 0; i < 5; ++i) {
240✔
900
                context.popTerminal();  // for ( ; ; ) punctuation
200✔
901
            }
902
            auto increment = hasIncrement ? context.popExpression() : nullptr;
40✔
903
            auto clause = hasClause ? context.popExpression() : nullptr;
40✔
904
            auto initialization = hasInit ? context.popExpression() : nullptr;
40✔
905
            auto loopHeader = std::make_unique<ForLoopHeader>(std::move(initialization), std::move(clause), std::move(increment));
40✔
906
            auto body = context.popStatement();
40✔
907
            context.pushStatement(std::make_unique<LoopStatement>(std::move(loopHeader), std::move(body)));
40✔
908
        };
3,688✔
909
    };
910
    auto registerFor = [&](const std::vector<int>& prod, std::function<void(AbstractSyntaxTreeBuilderContext&)> creator) {
3,648✔
911
        nodeCreatorRegistry[s_iteration_stat_matched][prod] = creator;
3,648✔
912
        auto unmatchedProd = prod;
3,648✔
913
        unmatchedProd.back() = s_unmatched;
3,648✔
914
        nodeCreatorRegistry[s_iteration_stat_unmatched][unmatchedProd] = creator;
3,648✔
915
    };
3,648✔
916
    registerFor({ s_for, s_open_paren, s_exp, s_semicolon, s_exp, s_semicolon, s_exp, s_close_paren, s_matched }, forLoop(true,  true,  true));
1,368✔
917
    registerFor({ s_for, s_open_paren, s_exp, s_semicolon, s_exp, s_semicolon, s_close_paren, s_matched }, forLoop(true,  true,  false));
1,368✔
918
    registerFor({ s_for, s_open_paren, s_exp, s_semicolon, s_semicolon, s_exp, s_close_paren, s_matched }, forLoop(true,  false, true));
1,368✔
919
    registerFor({ s_for, s_open_paren, s_exp, s_semicolon, s_semicolon, s_close_paren, s_matched }, forLoop(true,  false, false));
1,368✔
920
    registerFor({ s_for, s_open_paren, s_semicolon, s_exp, s_semicolon, s_exp, s_close_paren, s_matched }, forLoop(false, true,  true));
1,368✔
921
    registerFor({ s_for, s_open_paren, s_semicolon, s_exp, s_semicolon, s_close_paren, s_matched }, forLoop(false, true,  false));
1,368✔
922
    registerFor({ s_for, s_open_paren, s_semicolon, s_semicolon, s_exp, s_close_paren, s_matched }, forLoop(false, false, true));
1,368✔
923
    registerFor({ s_for, s_open_paren, s_semicolon, s_semicolon, s_close_paren, s_matched }, forLoop(false, false, false));
1,368✔
924
}
456✔
925

926
ContextualSyntaxNodeBuilder::~ContextualSyntaxNodeBuilder() = default;
456✔
927

928
void ContextualSyntaxNodeBuilder::updateContext(const parser::Production& production, AbstractSyntaxTreeBuilderContext& context) const {
105,550✔
929
    try {
930
        nodeCreatorRegistry.at(production.getDefiningSymbol()).at(production.producedSequence())(context);
105,550✔
931
    } catch (std::out_of_range& exception) {
6✔
932
        noCreatorDefined(production);
×
933
    }
×
934
}
105,544✔
935

936
void ContextualSyntaxNodeBuilder::noCreatorDefined(const parser::Production& production) const {
×
937
    throw std::runtime_error {
NEW
938
            "language construct not implemented yet (production `" + grammar->str(production) + "`)" };
×
939
}
940

941
void ContextualSyntaxNodeBuilder::loopJumpStatement(AbstractSyntaxTreeBuilderContext& context) {
10✔
942
    context.popTerminal(); // ;
10✔
943
    context.pushStatement(std::make_unique<JumpStatement>(context.popTerminal())); // break | continue
10✔
944
}
10✔
945

946
} /* namespace ast */
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc