5 // Transform ANTLR-generated types to corresponding IR types recursively
\r
7 Type getType(TocParser::TypeContext * ctx);
\r
8 Variable getVariable(TocParser::VarContext * ctx);
\r
9 Body getBody(TocParser::BodyContext * ctx, std::shared_ptr<Context> parent);
\r
10 Function getFunction(TocParser::FuncContext * ctx, std::shared_ptr<Context> parent);
\r
11 Struct getStruct(TocParser::StructDeclContext * ctx, std::shared_ptr<Context> parent);
\r
12 Namespace getNamespace(TocParser::NamespaceDeclContext * ctx, std::shared_ptr<Context> parent);
\r
13 Program getProgram(TocParser::ProgContext * ctx, std::shared_ptr<Context> parent);
\r
16 Expr getExpr(TocParser::FuncExprContext * ctx);
\r
17 Expr getExpr(TocParser::MethodExprContext * ctx);
\r
18 Expr getExpr(TocParser::LitExprContext * ctx);
\r
19 Expr getExpr(TocParser::ParenExprContext * ctx);
\r
20 Expr getExpr(TocParser::DotExprContext * ctx);
\r
21 Expr getExpr(TocParser::PrefixOpExprContext * ctx);
\r
22 Expr getExpr(TocParser::PostfixOpExprContext * ctx);
\r
23 Expr getExpr(TocParser::BinaryOpExprContext * ctx);
\r
24 Expr getExpr(TocParser::TernaryOpExprContext * ctx);
\r
25 Expr getExpr(TocParser::BracketExprContext * ctx);
\r
26 Expr getExpr(TocParser::IdentifierExprContext * ctx);
\r
27 Expr getExpr(TocParser::ExprContext * ctx);
\r
29 Stmt getStmt(TocParser::StmtContext * ctx, std::shared_ptr<Context> parent);
\r
31 // all of these functions get the relevant information
\r
32 // from the parse tree and call each other for sub expressions
\r
33 // the getVariable is called for variable declarations and parameter definitions
\r
34 // for example, because they have the same rule in the grammar file
\r
36 Type getType(TocParser::TypeContext * ctx)
\r
39 for (auto n : ctx->namespaceSpecifier())
\r
40 result.namespacePrefixes.push_back(n->typeName()->getText());
\r
41 result.name = ctx->typeName()->NAME()->toString();
\r
42 for (auto m : ctx->typeModifier())
\r
44 bool isPointer = m->getText() == "*";
\r
45 bool isStaticArray = m->INT_LIT() != nullptr;
\r
47 result.modifiers.emplace_back(
\r
48 isPointer ? TypeModifierType::Pointer : TypeModifierType::Array,
\r
50 isStaticArray ? atoi(m->INT_LIT()->toString().c_str()) : -1
\r
53 if (ctx->genericInstantiation() != nullptr)
\r
55 for (auto g : ctx->genericInstantiation()->type())
\r
57 result.genericInstantiation.push_back(getType(g));
\r
62 Variable getVariable(TocParser::VarContext * ctx)
\r
65 result.name = ctx->varName()->NAME()->toString();
\r
66 result.type = getType(ctx->type());
\r
69 Body getBody(TocParser::BodyContext * ctx, std::shared_ptr<Context> parent)
\r
72 result.ctx = std::make_unique<Context>();
\r
73 result.ctx->parent = parent;
\r
74 for (auto s : ctx->stmt())
\r
76 if (s->varDecl() != nullptr)
\r
78 result.ctx->variables.push_back(getVariable(s->varDecl()->var()));
\r
79 if (s->varDecl()->var()->expr() != nullptr)
\r
80 result.statements.push_back(getStmt(s, result.ctx));
\r
84 result.statements.push_back(getStmt(s, result.ctx));
\r
89 Function getFunction(TocParser::FuncContext * ctx, std::shared_ptr<Context> parent)
\r
92 result.name = ctx->funcName()->NAME()->toString();
\r
93 result.returnType = getType(ctx->type());
\r
94 if (ctx->genericDecl() != nullptr)
\r
96 for (auto t : ctx->genericDecl()->typeName())
\r
98 result.genericTypeNames.push_back(t->getText());
\r
102 if (!ctx->parameter()->var().empty())
\r
104 for (auto p : ctx->parameter()->var())
\r
105 result.parameters.push_back(getVariable(p));
\r
108 if (ctx->body() != nullptr)
\r
110 result.body = getBody(ctx->body(), parent);
\r
111 result.defined = true;
\r
115 result.defined = false;
\r
119 Struct getStruct(TocParser::StructDeclContext * ctx, std::shared_ptr<Context> parent)
\r
122 result.name = ctx->structName()->NAME()->toString();
\r
123 if (ctx->genericDecl() != nullptr)
\r
125 for (auto t : ctx->genericDecl()->typeName())
\r
127 result.genericTypeNames.push_back(t->getText());
\r
131 for (auto m : ctx->structMember())
\r
133 if (m->structVar() != nullptr)
\r
135 result.members.push_back({
\r
136 getVariable(m->structVar()->var()),
\r
137 m->privateDecl() != nullptr
\r
140 if (m->structMethod() != nullptr)
\r
142 result.methods.push_back({
\r
143 getFunction(m->structMethod()->func(), parent),
\r
144 m->privateDecl() != nullptr
\r
150 Namespace getNamespace(TocParser::NamespaceDeclContext * ctx, std::shared_ptr<Context> parent)
\r
153 result.ctx = std::make_unique<Context>();
\r
154 result.name = ctx->typeName()->getText();
\r
155 result.ctx->name = result.name;
\r
156 for (auto d : ctx->decl())
\r
158 if (d->varDecl() != nullptr)
\r
160 result.ctx->variables.push_back(getVariable(d->varDecl()->var()));
\r
162 if (d->funcDecl() != nullptr)
\r
164 result.ctx->functions.push_back(getFunction(d->funcDecl()->func(), result.ctx));
\r
166 if (d->structDecl() != nullptr)
\r
168 result.ctx->structs.push_back(getStruct(d->structDecl(), result.ctx));
\r
170 if (d->namespaceDecl() != nullptr)
\r
172 result.ctx->namespaces.push_back(getNamespace(d->namespaceDecl(), result.ctx));
\r
177 Program getProgram(TocParser::ProgContext * ctx, std::shared_ptr<Context> parent)
\r
180 result.ctx = std::make_unique<Context>();
\r
181 for (auto d : ctx->decl())
\r
183 if (d->varDecl() != nullptr)
\r
185 result.ctx->variables.push_back(getVariable(d->varDecl()->var()));
\r
187 if (d->funcDecl() != nullptr)
\r
189 result.ctx->functions.push_back(getFunction(d->funcDecl()->func(), result.ctx));
\r
191 if (d->structDecl() != nullptr)
\r
193 result.ctx->structs.push_back(getStruct(d->structDecl(), result.ctx));
\r
195 if (d->namespaceDecl() != nullptr)
\r
197 result.ctx->namespaces.push_back(getNamespace(d->namespaceDecl(), result.ctx));
\r
202 template<typename OpType>
\r
203 OpType getOperatorType(const std::string & s, std::string typeStrings[])
\r
205 for (int i = 0; i < (int)OpType::COUNT; i++)
\r
207 if (typeStrings[i] == s)
\r
212 return OpType::COUNT;
\r
226 // Expressions are somewhat of an exception, because some of their
\r
227 // grammar rules are recursive, so they have to be defined
\r
228 // in a single rule using Labels (https://github.com/antlr/antlr4/blob/master/doc/parser-rules.md#alternative-labels)
\r
229 // Because this results in a polymorphic type, getExpr for the base expression type
\r
230 // is always called and from there the polymorphic type is determined at runtime
\r
231 Expr getExpr(TocParser::FuncExprContext * ctx)
\r
234 result.type = ExprType::Func;
\r
235 for (auto n : ctx->namespaceSpecifier())
\r
236 result._func.namespacePrefixes.push_back(n->typeName()->getText());
\r
237 result._func.functionName = ctx->funcName()->NAME()->toString();
\r
238 if (ctx->genericInstantiation() != nullptr)
\r
240 for (auto g : ctx->genericInstantiation()->type())
\r
242 result._func.genericInstantiation.push_back(getType(g));
\r
245 for (auto e : ctx->expr())
\r
246 result._func.arguments.push_back(getExpr(e));
\r
249 Expr getExpr(TocParser::MethodExprContext * ctx)
\r
252 result.type = ExprType::Method;
\r
253 result._method.expr = std::make_unique<Expr>(getExpr(ctx->expr(0)));
\r
254 result._method.methodName = ctx->funcName()->NAME()->toString();
\r
255 if (ctx->genericInstantiation() != nullptr)
\r
257 for (auto g : ctx->genericInstantiation()->type())
\r
259 result._method.genericInstantiation.push_back(getType(g));
\r
262 for (int i = 1; i < ctx->expr().size(); i++)
\r
263 result._method.arguments.push_back(getExpr(ctx->expr(i)));
\r
266 Expr getExpr(TocParser::LitExprContext * ctx)
\r
269 result.type = ExprType::Lit;
\r
270 if (ctx->literal()->INT_LIT() != nullptr)
\r
272 result._lit.type = LitType::Int;
\r
273 result._lit._int = atoi(ctx->literal()->INT_LIT()->toString().c_str());
\r
275 else if (ctx->literal()->DECIMAL_LIT() != nullptr)
\r
277 result._lit.type = LitType::Decimal;
\r
278 result._lit._decimal = atof(ctx->literal()->DECIMAL_LIT()->toString().c_str());
\r
280 else if (ctx->literal()->StringLit() != nullptr)
\r
282 result._lit.type = LitType::String;
\r
283 result._lit._string = ctx->literal()->StringLit()->toString();
\r
285 else if (ctx->literal()->BOOL_LIT() != nullptr)
\r
287 result._lit.type = LitType::Bool;
\r
288 result._lit._bool = ctx->literal()->BOOL_LIT()->toString() == "true";
\r
292 Expr getExpr(TocParser::ParenExprContext * ctx)
\r
295 result.type = ExprType::Paren;
\r
296 result._paren.expr = std::make_unique<Expr>(getExpr(ctx->expr()));
\r
299 Expr getExpr(TocParser::DotExprContext * ctx)
\r
302 result.type = ExprType::Dot;
\r
303 result._dot.expr = std::make_unique<Expr>(getExpr(ctx->expr()));
\r
304 result._dot.identifier = ctx->varName()->getText();
\r
305 result._dot.isPointer = ctx->arrow() != nullptr;
\r
308 Expr getExpr(TocParser::PrefixOpExprContext * ctx)
\r
311 result.type = ExprType::PrefixOp;
\r
312 result._prefixOp.expr = std::make_unique<Expr>(getExpr(ctx->expr()));
\r
313 result._prefixOp.type = getOperatorType<PrefixOperatorType>(
\r
314 ctx->prefix_op()->getText(),
\r
315 PrefixOperatorTypeStrings);
\r
318 Expr getExpr(TocParser::PostfixOpExprContext * ctx)
\r
321 result.type = ExprType::PostfixOp;
\r
322 result._postfixOp.expr = std::make_unique<Expr>(getExpr(ctx->expr()));
\r
323 result._postfixOp.type = getOperatorType<PostfixOperatorType>(
\r
324 ctx->postfix_op()->getText(),
\r
325 PostfixOperatorTypeStrings);
\r
328 Expr getExpr(TocParser::BinaryOpExprContext * ctx)
\r
331 result.type = ExprType::BinaryOp;
\r
332 result._binaryOp.lexpr = std::make_unique<Expr>(getExpr(ctx->expr(0)));
\r
333 result._binaryOp.rexpr = std::make_unique<Expr>(getExpr(ctx->expr(1)));
\r
334 result._binaryOp.type = getOperatorType<BinaryOperatorType>(
\r
335 ctx->binary_op()->getText(),
\r
336 BinaryOperatorTypeStrings);
\r
339 Expr getExpr(TocParser::TernaryOpExprContext * ctx)
\r
342 result.type = ExprType::TernaryOp;
\r
343 result._ternaryOp.lexpr = std::make_unique<Expr>(getExpr(ctx->expr(0)));
\r
344 result._ternaryOp.rexprTrue = std::make_unique<Expr>(getExpr(ctx->expr(1)));
\r
345 result._ternaryOp.rexprFalse = std::make_unique<Expr>(getExpr(ctx->expr(2)));
\r
348 Expr getExpr(TocParser::BracketExprContext * ctx)
\r
351 result.type = ExprType::Bracket;
\r
352 result._brackets.lexpr = std::make_unique<Expr>(getExpr(ctx->expr(0)));
\r
353 result._brackets.rexpr = std::make_unique<Expr>(getExpr(ctx->expr(1)));
\r
356 Expr getExpr(TocParser::IdentifierExprContext * ctx)
\r
359 result.type = ExprType::Identifier;
\r
360 for (auto n : ctx->namespaceSpecifier())
\r
361 result._identifier.namespacePrefixes.push_back(n->typeName()->getText());
\r
362 result._identifier.identifier = ctx->varName()->getText();
\r
375 // this is always called for Expression rules
\r
376 // attempt dynamic_cast at runtime and call corresponding
\r
378 Expr getExpr(TocParser::ExprContext * ctx)
\r
381 if (dynamic_cast<TocParser::FuncExprContext *>(ctx) != nullptr)
\r
382 result = getExpr(dynamic_cast<TocParser::FuncExprContext *>(ctx));
\r
383 if (dynamic_cast<TocParser::MethodExprContext *>(ctx) != nullptr)
\r
384 result = getExpr(dynamic_cast<TocParser::MethodExprContext *>(ctx));
\r
385 if (dynamic_cast<TocParser::LitExprContext *>(ctx) != nullptr)
\r
386 result = getExpr(dynamic_cast<TocParser::LitExprContext *>(ctx));
\r
387 if (dynamic_cast<TocParser::ParenExprContext *>(ctx) != nullptr)
\r
388 result = getExpr(dynamic_cast<TocParser::ParenExprContext *>(ctx));
\r
389 if (dynamic_cast<TocParser::DotExprContext *>(ctx) != nullptr)
\r
390 result = getExpr(dynamic_cast<TocParser::DotExprContext *>(ctx));
\r
391 if (dynamic_cast<TocParser::PrefixOpExprContext *>(ctx) != nullptr)
\r
392 result = getExpr(dynamic_cast<TocParser::PrefixOpExprContext *>(ctx));
\r
393 if (dynamic_cast<TocParser::PostfixOpExprContext *>(ctx) != nullptr)
\r
394 result = getExpr(dynamic_cast<TocParser::PostfixOpExprContext *>(ctx));
\r
395 if (dynamic_cast<TocParser::BinaryOpExprContext *>(ctx) != nullptr)
\r
396 result = getExpr(dynamic_cast<TocParser::BinaryOpExprContext *>(ctx));
\r
397 if (dynamic_cast<TocParser::TernaryOpExprContext *>(ctx) != nullptr)
\r
398 result = getExpr(dynamic_cast<TocParser::TernaryOpExprContext *>(ctx));
\r
399 if (dynamic_cast<TocParser::BracketExprContext *>(ctx) != nullptr)
\r
400 result = getExpr(dynamic_cast<TocParser::BracketExprContext *>(ctx));
\r
401 if (dynamic_cast<TocParser::IdentifierExprContext *>(ctx) != nullptr)
\r
402 result = getExpr(dynamic_cast<TocParser::IdentifierExprContext *>(ctx));
\r
405 Stmt getStmt(TocParser::StmtContext * ctx, std::shared_ptr<Context> parent)
\r
408 if (ctx->varDecl() != nullptr && ctx->varDecl()->var()->expr() != nullptr)
\r
410 result.type = StmtType::Assign;
\r
411 result._assign.lexpr.type = ExprType::Identifier;
\r
412 result._assign.lexpr._identifier.identifier = ctx->varDecl()->var()->varName()->getText();
\r
413 result._assign.rexpr = getExpr(ctx->varDecl()->var()->expr());
\r
415 if (ctx->ifStmt() != nullptr)
\r
417 result.type = StmtType::If;
\r
418 result._if.condition = getExpr(ctx->ifStmt()->expr());
\r
419 result._if.body = getBody(ctx->ifStmt()->body(), parent);
\r
420 for (auto ei : ctx->ifStmt()->elseIfStmt())
\r
422 result._if.elses.emplace_back(
\r
424 std::make_unique<Expr>(getExpr(ei->expr())),
\r
425 getBody(ei->body(), parent)
\r
428 if (ctx->ifStmt()->elseStmt() != nullptr)
\r
430 result._if.elses.emplace_back(
\r
433 getBody(ctx->ifStmt()->elseStmt()->body(), parent)
\r
437 if (ctx->switchStmt() != nullptr)
\r
439 result.type = StmtType::Switch;
\r
440 result._switch.ident = std::make_unique<Expr>(getExpr(ctx->switchStmt()->expr()));
\r
441 for (auto c : ctx->switchStmt()->switchBody()->switchCase())
\r
443 result._switch.cases.emplace_back(
\r
444 std::make_unique<Expr>(getExpr(c->expr())),
\r
445 getBody(c->body(), parent)
\r
449 if (ctx->forStmt() != nullptr)
\r
451 result.type = StmtType::For;
\r
452 result._for.init = std::make_unique<AssignStmt>();
\r
453 result._for.init->lexpr.type = ExprType::Identifier;
\r
454 result._for.init->lexpr._identifier.identifier = ctx->forStmt()->varInit()->varName()->getText();
\r
455 result._for.init->rexpr = getExpr(ctx->forStmt()->varInit()->expr());
\r
456 result._for.condition = std::make_unique<Expr>(getExpr(ctx->forStmt()->expr(0)));
\r
457 result._for.action = std::make_unique<Expr>(getExpr(ctx->forStmt()->expr(1)));
\r
458 result._for.body = getBody(ctx->forStmt()->body(), parent);
\r
460 if (ctx->whileStmt() != nullptr)
\r
462 result.type = StmtType::While;
\r
463 result._while.condition = getExpr(ctx->whileStmt()->expr());
\r
464 result._while.body = getBody(ctx->whileStmt()->body(), parent);
\r
466 if (ctx->assignStmt() != nullptr)
\r
468 result.type = StmtType::Assign;
\r
469 result._assign.lexpr = getExpr(ctx->assignStmt()->expr(0));
\r
470 result._assign.rexpr = getExpr(ctx->assignStmt()->expr(1));
\r
472 if (ctx->returnStmt() != nullptr)
\r
474 result.type = StmtType::Return;
\r
475 result._return.expr = getExpr(ctx->returnStmt()->expr());
\r
477 if (ctx->expr() != nullptr)
\r
479 result.type = StmtType::Expr;
\r
480 result._expr = getExpr(ctx->expr());
\r