]> gitweb.ps.run Git - toc/blob - src/repr_get.h
add antlr source code and ReadMe
[toc] / src / repr_get.h
1 #pragma once\r
2 \r
3 #include "repr.h"\r
4 \r
5 // Transform ANTLR-generated types to corresponding IR types recursively\r
6 \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
14 \r
15 \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
28 \r
29 Stmt                getStmt(TocParser::StmtContext * ctx, std::shared_ptr<Context> parent);\r
30 \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
35 \r
36 Type getType(TocParser::TypeContext * ctx)\r
37 {\r
38   Type result;\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
43   {\r
44     bool isPointer = m->getText() == "*";\r
45     bool isStaticArray = m->INT_LIT() != nullptr;\r
46 \r
47     result.modifiers.emplace_back(\r
48       isPointer ? TypeModifierType::Pointer : TypeModifierType::Array,\r
49       isStaticArray,\r
50       isStaticArray ? atoi(m->INT_LIT()->toString().c_str()) : -1\r
51     );\r
52   }\r
53   if (ctx->genericInstantiation() != nullptr)\r
54   {\r
55     for (auto g : ctx->genericInstantiation()->type())\r
56     {\r
57       result.genericInstantiation.push_back(getType(g));\r
58     }\r
59   }\r
60   return result;\r
61 }\r
62 Variable getVariable(TocParser::VarContext * ctx)\r
63 {\r
64   Variable result;\r
65   result.name = ctx->varName()->NAME()->toString();\r
66   result.type = getType(ctx->type());\r
67   return result;\r
68 }\r
69 Body getBody(TocParser::BodyContext * ctx, std::shared_ptr<Context> parent)\r
70 {\r
71   Body result;\r
72   result.ctx = std::make_unique<Context>();\r
73   result.ctx->parent = parent;\r
74   for (auto s : ctx->stmt())\r
75   {\r
76     if (s->varDecl() != nullptr)\r
77     {\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
81     }\r
82     else\r
83     {\r
84       result.statements.push_back(getStmt(s, result.ctx));\r
85     }\r
86   }\r
87   return result;\r
88 }\r
89 Function getFunction(TocParser::FuncContext * ctx, std::shared_ptr<Context> parent)\r
90 {\r
91   Function result;\r
92   result.name = ctx->funcName()->NAME()->toString();\r
93   result.returnType = getType(ctx->type());\r
94   if (ctx->genericDecl() != nullptr)\r
95   {\r
96     for (auto t : ctx->genericDecl()->typeName())\r
97     {\r
98       result.genericTypeNames.push_back(t->getText());\r
99     }\r
100   }\r
101 \r
102   if (!ctx->parameter()->var().empty())\r
103   {\r
104     for (auto p : ctx->parameter()->var())\r
105       result.parameters.push_back(getVariable(p));\r
106   }\r
107 \r
108   if (ctx->body() != nullptr)\r
109   {\r
110     result.body = getBody(ctx->body(), parent);\r
111     result.defined = true;\r
112   }\r
113   else\r
114   {\r
115     result.defined = false;\r
116   }\r
117   return result;\r
118 }\r
119 Struct getStruct(TocParser::StructDeclContext * ctx, std::shared_ptr<Context> parent)\r
120 {\r
121   Struct result;\r
122   result.name = ctx->structName()->NAME()->toString();\r
123   if (ctx->genericDecl() != nullptr)\r
124   {\r
125     for (auto t : ctx->genericDecl()->typeName())\r
126     {\r
127       result.genericTypeNames.push_back(t->getText());\r
128     }\r
129   }\r
130 \r
131   for (auto m : ctx->structMember())\r
132   {\r
133     if (m->structVar() != nullptr)\r
134     {\r
135       result.members.push_back({\r
136         getVariable(m->structVar()->var()),\r
137         m->privateDecl() != nullptr\r
138       });\r
139     }\r
140     if (m->structMethod() != nullptr)\r
141     {\r
142       result.methods.push_back({\r
143         getFunction(m->structMethod()->func(), parent),\r
144         m->privateDecl() != nullptr\r
145       });\r
146     }\r
147   }\r
148   return result;\r
149 }\r
150 Namespace getNamespace(TocParser::NamespaceDeclContext * ctx, std::shared_ptr<Context> parent)\r
151 {\r
152   Namespace result;\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
157   {\r
158     if (d->varDecl() != nullptr)\r
159     {\r
160       result.ctx->variables.push_back(getVariable(d->varDecl()->var()));\r
161     }\r
162     if (d->funcDecl() != nullptr)\r
163     {\r
164       result.ctx->functions.push_back(getFunction(d->funcDecl()->func(), result.ctx));\r
165     }\r
166     if (d->structDecl() != nullptr)\r
167     {\r
168       result.ctx->structs.push_back(getStruct(d->structDecl(), result.ctx));\r
169     }\r
170     if (d->namespaceDecl() != nullptr)\r
171     {\r
172       result.ctx->namespaces.push_back(getNamespace(d->namespaceDecl(), result.ctx));\r
173     }\r
174   }\r
175   return result;\r
176 }\r
177 Program getProgram(TocParser::ProgContext * ctx, std::shared_ptr<Context> parent)\r
178 {\r
179   Program result;\r
180   result.ctx = std::make_unique<Context>();\r
181   for (auto d : ctx->decl())\r
182   {\r
183     if (d->varDecl() != nullptr)\r
184     {\r
185       result.ctx->variables.push_back(getVariable(d->varDecl()->var()));\r
186     }\r
187     if (d->funcDecl() != nullptr)\r
188     {\r
189       result.ctx->functions.push_back(getFunction(d->funcDecl()->func(), result.ctx));\r
190     }\r
191     if (d->structDecl() != nullptr)\r
192     {\r
193       result.ctx->structs.push_back(getStruct(d->structDecl(), result.ctx));\r
194     }\r
195     if (d->namespaceDecl() != nullptr)\r
196     {\r
197       result.ctx->namespaces.push_back(getNamespace(d->namespaceDecl(), result.ctx));\r
198     }\r
199   }\r
200   return result;\r
201 }\r
202 template<typename OpType>\r
203 OpType getOperatorType(const std::string & s, std::string typeStrings[])\r
204 {\r
205   for (int i = 0; i < (int)OpType::COUNT; i++)\r
206   {\r
207     if (typeStrings[i] == s)\r
208     {\r
209       return (OpType)i;\r
210     }\r
211   }\r
212   return OpType::COUNT;\r
213 }\r
214 \r
215 \r
216 \r
217 \r
218 \r
219 \r
220 \r
221 \r
222 \r
223 \r
224 \r
225 \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
232 {\r
233   Expr result;\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
239   {\r
240     for (auto g : ctx->genericInstantiation()->type())\r
241     {\r
242       result._func.genericInstantiation.push_back(getType(g));\r
243     }\r
244   }\r
245   for (auto e : ctx->expr())\r
246     result._func.arguments.push_back(getExpr(e));\r
247   return result;\r
248 }\r
249 Expr getExpr(TocParser::MethodExprContext * ctx)\r
250 {\r
251   Expr result;\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
256   {\r
257     for (auto g : ctx->genericInstantiation()->type())\r
258     {\r
259       result._method.genericInstantiation.push_back(getType(g));\r
260     }\r
261   }\r
262   for (int i = 1; i < ctx->expr().size(); i++)\r
263     result._method.arguments.push_back(getExpr(ctx->expr(i)));\r
264   return result;\r
265 }\r
266 Expr getExpr(TocParser::LitExprContext * ctx)\r
267 {\r
268   Expr result;\r
269   result.type = ExprType::Lit;\r
270   if (ctx->literal()->INT_LIT() != nullptr)\r
271   {\r
272     result._lit.type = LitType::Int;\r
273     result._lit._int = atoi(ctx->literal()->INT_LIT()->toString().c_str());\r
274   }\r
275   else if (ctx->literal()->DECIMAL_LIT() != nullptr)\r
276   {\r
277     result._lit.type = LitType::Decimal;\r
278     result._lit._decimal = atof(ctx->literal()->DECIMAL_LIT()->toString().c_str());\r
279   }\r
280   else if (ctx->literal()->StringLit() != nullptr)\r
281   {\r
282     result._lit.type = LitType::String;\r
283     result._lit._string = ctx->literal()->StringLit()->toString();\r
284   }\r
285   else if (ctx->literal()->BOOL_LIT() != nullptr)\r
286   {\r
287     result._lit.type = LitType::Bool;\r
288     result._lit._bool = ctx->literal()->BOOL_LIT()->toString() == "true";\r
289   }\r
290   return result;\r
291 }\r
292 Expr getExpr(TocParser::ParenExprContext * ctx)\r
293 {\r
294   Expr result;\r
295   result.type = ExprType::Paren;\r
296   result._paren.expr = std::make_unique<Expr>(getExpr(ctx->expr()));\r
297   return result;\r
298 }\r
299 Expr getExpr(TocParser::DotExprContext * ctx)\r
300 {\r
301   Expr result;\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
306   return result;\r
307 }\r
308 Expr getExpr(TocParser::PrefixOpExprContext * ctx)\r
309 {\r
310   Expr result;\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
316   return result;\r
317 }\r
318 Expr getExpr(TocParser::PostfixOpExprContext * ctx)\r
319 {\r
320   Expr result;\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
326   return result;\r
327 }\r
328 Expr getExpr(TocParser::BinaryOpExprContext * ctx)\r
329 {\r
330   Expr result;\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
337   return result;\r
338 }\r
339 Expr getExpr(TocParser::TernaryOpExprContext * ctx)\r
340 {\r
341   Expr result;\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
346   return result;\r
347 }\r
348 Expr getExpr(TocParser::BracketExprContext * ctx)\r
349 {\r
350   Expr result;\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
354   return result;\r
355 }\r
356 Expr getExpr(TocParser::IdentifierExprContext * ctx)\r
357 {\r
358   Expr result;\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
363   return result;\r
364 }\r
365 \r
366 \r
367 \r
368 \r
369 \r
370 \r
371 \r
372 \r
373 \r
374 \r
375 // this is always called for Expression rules\r
376 // attempt dynamic_cast at runtime and call corresponding\r
377 // function\r
378 Expr getExpr(TocParser::ExprContext * ctx)\r
379 {\r
380   Expr result;\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
403   return result;\r
404 }\r
405 Stmt getStmt(TocParser::StmtContext * ctx, std::shared_ptr<Context> parent)\r
406 {\r
407   Stmt result;\r
408   if (ctx->varDecl() != nullptr && ctx->varDecl()->var()->expr() != nullptr)\r
409   {\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
414   }\r
415   if (ctx->ifStmt() != nullptr)\r
416   {\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
421     {\r
422       result._if.elses.emplace_back(\r
423         true,\r
424         std::make_unique<Expr>(getExpr(ei->expr())),\r
425         getBody(ei->body(), parent)\r
426       );\r
427     }\r
428     if (ctx->ifStmt()->elseStmt() != nullptr)\r
429     {\r
430       result._if.elses.emplace_back(\r
431         false,\r
432         nullptr,\r
433         getBody(ctx->ifStmt()->elseStmt()->body(), parent)\r
434       );\r
435     }\r
436   }\r
437   if (ctx->switchStmt() != nullptr)\r
438   {\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
442     {\r
443       result._switch.cases.emplace_back(\r
444         std::make_unique<Expr>(getExpr(c->expr())),\r
445         getBody(c->body(), parent)\r
446       );\r
447     }\r
448   }\r
449   if (ctx->forStmt() != nullptr)\r
450   {\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
459   }\r
460   if (ctx->whileStmt() != nullptr)\r
461   {\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
465   }\r
466   if (ctx->assignStmt() != nullptr)\r
467   {\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
471   }\r
472   if (ctx->returnStmt() != nullptr)\r
473   {\r
474     result.type = StmtType::Return;\r
475     result._return.expr = getExpr(ctx->returnStmt()->expr());\r
476   }\r
477   if (ctx->expr() != nullptr)\r
478   {\r
479     result.type = StmtType::Expr;\r
480     result._expr = getExpr(ctx->expr());\r
481   }\r
482   return result;\r
483 }