1 module TTSListener;
2 
3 import RuleTranslatorBaseListener;
4 import RuleTranslatorParser: RuleTranslatorParser;
5 import RuleWriter: RuleWriter;
6 import antlr.v4.runtime.ParserRuleContext;
7 import antlr.v4.runtime.tree.ErrorNode;
8 import antlr.v4.runtime.tree.TerminalNode;
9 import std.algorithm.iteration;
10 import std.array;
11 import std.container : SList;
12 import std.format;
13 import std.stdio;
14 import std..string;
15 
16 /**
17  * This class provides an empty implementation of {@link RuleTranslatorListener},
18  * which can be extended to create a listener which only needs to handle a subset
19  * of the available methods.
20  */
21 public class TTSListener : RuleTranslatorBaseListener {
22 
23     debug __gshared short counter;
24 
25     private auto stack = SList!(string[])();
26 
27     struct RuleSetting
28     {
29         string language;
30         string ruleName;
31         string className;
32         string baseName;
33     }
34 
35     private RuleSetting ruleSetting;
36 
37     struct LoopElement
38     {
39         string foreachType;
40         string foreachElementType;
41         ushort foreachIndex;  // index must not start at 0
42     }
43 
44     private auto loopStack = SList!(LoopElement)();
45 
46     private string foreachElementName;
47 
48     private string dottedName;
49 
50     private ushort indentLevel;
51 
52     private bool funcdefFlag;
53 
54     private bool trailerMode;
55 
56     private bool ruleRequired = true;
57 
58     private bool ruleExists;
59 
60     public RuleWriter writer;
61 
62     public string withPropertyName;
63 
64     public string arguments;
65 
66     string[] startText = [
67                           "\n",
68                           "override string[] rule" ~
69                           "(${arguments})\n",
70                           "{\n",
71                           "    output.clear;\n\n",
72                           "    with(${withPropertyName})\n",
73                           "    {\n"
74                           ];
75 
76     string[] closingText = [
77                             "\n",
78                             "static this()\n",
79                             "{\n",
80                             "    auto inst = new ${class}();\n",
81                             "    inst.type = \"${rule}\";\n",
82                             "    inst.language = \"${language}\";\n",
83                             "    Repository.register(inst);\n",
84                             "}\n"
85                             ];
86 
87     /**
88      * {@inheritDoc}
89      *
90      * <p>The default implementation does nothing.</p>
91      */
92     override public void enterFile_input(RuleTranslatorParser.File_inputContext ctx) {
93         writer.put("module ");
94     }
95 
96     /**
97      * {@inheritDoc}
98      *
99      * <p>The default implementation does nothing.</p>
100      */
101     override public void exitFile_input(RuleTranslatorParser.File_inputContext ctx) {
102         debug {
103             writefln("%s exitFile_input:", counter++);
104             writefln("\truleRequired = %s", ruleRequired);
105             writefln("\truleExits = %s", ruleExists);
106         }
107         writer.indentLevel = -- indentLevel;
108         writer.putnl("}");
109         if(ruleExists) {
110             with(ruleSetting) {
111                 closingText.each!((ref n) => n = n.replace("${class}",
112                                                            className ? className : ruleName));
113                 closingText.each!((ref n) => n = n.replace("${rule}", ruleName));
114                 closingText.each!((ref n) => n = n.replace("${language}", language));
115             }
116             writer.putnl("return output.data;");
117             writer.indentLevel = -- indentLevel;
118             writer.putnl("}");
119             writer.put(closingText);
120             writer.indentLevel = -- indentLevel;
121             writer.putnl("}");
122         }
123         writer.print;
124         writer.clear;
125     }
126 
127     /**
128      * {@inheritDoc}
129      *
130      * <p>The default implementation does nothing.</p>
131      */
132     override public void exitRule_setting(RuleTranslatorParser.Rule_settingContext ctx) {
133         with(ruleSetting) {
134             if (language)
135                 writer.putnl(format("%s.%s;\n",
136                                     language,
137                                     className ? className : ruleName
138                                     )
139                              );
140             else
141                 writer.putnl(format("%s;\n",
142                                     className ? className : ruleName
143                                     )
144                              );
145         }
146         writer.putnl("import std.array;");
147         writer.putnl("import std.conv;");
148         writer.putnl("import std.datetime;");
149         writer.putnl("import rule.Repository;");
150         writer.putnl("import rule.GeneratedRule;\n");
151         writer.putnl("auto iterate(R)(R range)");
152         writer.putnl("{");
153         writer.putnl("    import std.algorithm : map;");
154         writer.putnl("    import std.range : enumerate;");
155         writer.putnl("    import std.typecons : tuple;\n");
156 
157         writer.putnl("    return enumerate(range)");
158         writer.putnl("        .map!(a => tuple!(\"value\", \"first\", \"last\")(a.value, a.index == 0, a.index + 1 == range.length));");
159         writer.putnl("}");
160     }
161 
162     /**
163      * {@inheritDoc}
164      *
165      * <p>The default implementation does nothing.</p>
166      */
167     override public void enterClass_name(RuleTranslatorParser.Class_nameContext ctx) {
168         ruleSetting.className = ctx.getText;
169     }
170 
171     /**
172      * {@inheritDoc}
173      *
174      * <p>The default implementation does nothing.</p>
175      */
176     override public void enterRule_name(RuleTranslatorParser.Rule_nameContext ctx) {
177         ruleSetting.ruleName = ctx.getText;
178     }
179 
180     /**
181      * {@inheritDoc}
182      *
183      * <p>The default implementation does nothing.</p>
184      */
185     override public void enterLanguage(RuleTranslatorParser.LanguageContext ctx) {
186         ruleSetting.language = "";
187     }
188     /**
189      * {@inheritDoc}
190      *
191      * <p>The default implementation does nothing.</p>
192      */
193     override public void exitLanguage(RuleTranslatorParser.LanguageContext ctx) {
194         ruleSetting.language = ctx.getText;
195     }
196 
197     /**
198      * {@inheritDoc}
199      *
200      * <p>The default implementation does nothing.</p>
201      */
202     override public void enterImport_stmt(RuleTranslatorParser.Import_stmtContext ctx) {
203         string app;
204         foreach(el; ctx.children[2..$])
205             app ~= el.getText;
206         writer.putnl(format("import %s;", app));
207     }
208 
209     /**
210      * {@inheritDoc}
211      *
212      * <p>The default implementation does nothing.</p>
213      */
214     override public void enterBase_rules(RuleTranslatorParser.Base_rulesContext ctx) {
215         ruleSetting.baseName = ctx.getText;
216     }
217 
218     /**
219      * {@inheritDoc}
220      *
221      * <p>The default implementation does nothing.</p>
222      */
223     override public void enterImport_stmts(RuleTranslatorParser.Import_stmtsContext ctx) { }
224 
225     /**
226      * {@inheritDoc}
227      *
228      * <p>The default implementation does nothing.</p>
229      */
230     override public void exitImport_stmts(RuleTranslatorParser.Import_stmtsContext ctx) {
231         if(ruleSetting.className)
232             writer.putnl(format("\nclass %s : %s\n{", ruleSetting.className, ruleSetting.baseName));
233         else
234             writer.putnl(format("\nclass %s : GeneratedRule\n{", ruleSetting.ruleName));
235         writer.indentLevel = ++ indentLevel;
236     }
237 
238 
239     /**
240      * {@inheritDoc}
241      *
242      * <p>The default implementation does nothing.</p>
243      */
244     override public void exitFunctionName(RuleTranslatorParser.FunctionNameContext ctx) {
245         writer.put(ctx.getText);
246     }
247     /**
248      * {@inheritDoc}
249      *
250      * <p>The default implementation does nothing.</p>
251      */
252     override public void enterStmt(RuleTranslatorParser.StmtContext ctx) {
253         debug {
254             writefln("%s enterStmt:", counter++);
255             writefln("\truleRequired = %s", ruleRequired);
256             writefln("\truleExits = %s", ruleExists);
257         }
258         if (ruleRequired) {
259             startText.each!((ref n) => n = n.replace("${withPropertyName}", withPropertyName));
260             startText.each!((ref n) => n = n.replace("${arguments}", arguments));
261             writer.put(startText);
262             writer.indentLevel = ++ indentLevel;
263             writer.indentLevel = ++ indentLevel;
264             ruleExists = true;
265             ruleRequired = false;
266         }
267     }
268     /**
269      * {@inheritDoc}
270      *
271      * <p>The default implementation does nothing.</p>
272      */
273     override public void enterFuncdef(RuleTranslatorParser.FuncdefContext ctx) {
274         writer.putnl("");
275         writer.put("void ");
276         funcdefFlag = true;
277         ruleRequired = false;
278     }
279 
280     /**
281      * {@inheritDoc}
282      *
283      * <p>The default implementation does nothing.</p>
284      */
285     override public void exitFuncdef(RuleTranslatorParser.FuncdefContext ctx) {
286         writer.indentLevel = -- indentLevel;
287         writer.putnl("}");
288         ruleRequired = true;
289     }
290 
291     /**
292      * {@inheritDoc}
293      *
294      * <p>The default implementation does nothing.</p>
295      */
296     override public void enterParameters(RuleTranslatorParser.ParametersContext ctx) {
297         if (funcdefFlag)
298             {
299                 auto spl = splitter(ctx.getText[1..($-1)], ',');
300                 writer.putnl('(' ~ spl.map!(a => "T_" ~ a).join(", ") ~ ')');
301                 writer.putnl("    (" ~ spl.map!(a => "T_" ~ a ~ ' ' ~ a).join(", ") ~ ')');
302                 writer.putnl("{");
303                 writer.indentLevel = ++ indentLevel;
304                 funcdefFlag = false;
305             }
306     }
307 
308     /**
309      * {@inheritDoc}
310      *
311      * <p>The default implementation does nothing.</p>
312      */
313     override public void enterString_stmt(RuleTranslatorParser.String_stmtContext ctx) {
314         if (!stack.empty) {
315             stack.front ~= format("append(%s)", ctx.children[0].getText);
316             debug {
317                 writefln("%s enterString_stmt:", counter++);
318                 foreach(el; stack.opSlice)
319                     writefln("\t%s", el);
320             }
321         }
322     }
323 
324     /**
325      * {@inheritDoc}
326      *
327      * <p>The default implementation does nothing.</p>
328      */
329     override public void exitVar_stmt(RuleTranslatorParser.Var_stmtContext ctx) {
330         if (!stack.empty) {
331             stack.front ~= format("append(%s)", dottedName);
332         }
333         debug {
334             writefln("%s exitVar_stmt:", counter++);
335             writefln("\tdottedName = %s", dottedName);
336         }
337     }
338 
339     /**
340      * When the name of the variable is equal to the foreach element,
341      * we need to append '.value' property
342      */
343     override public void enterFirst_part_of_dotted_name(RuleTranslatorParser.First_part_of_dotted_nameContext ctx) {
344         dottedName = ctx.getText;
345         if (!loopStack.empty) {
346             import std.algorithm : map;
347             import std.algorithm: canFind;
348             if (array(map!(a => a.foreachElementType)(loopStack[])).canFind(ctx.getText)) {
349                 dottedName ~= ".value";
350             }
351         }
352         debug {
353             writefln("%s enterFirst_part_of_dotted_name:", counter++);
354             writefln("\ttext = %s", ctx.getText);
355             writefln("\tdottedName = %s", dottedName);
356             foreach(el; stack.opSlice)
357                 writefln("\t%s", el);
358         }
359     }
360     /**
361      * {@inheritDoc}
362      *
363      * <p>The default implementation does nothing.</p>
364      */
365     override public void enterDotted_name_part(RuleTranslatorParser.Dotted_name_partContext ctx) {
366         dottedName ~= "." ~ ctx.getText;
367         debug {
368             writefln("%s enterDotted_name_part:", counter++);
369             writefln("\ttext = %s", ctx.getText);
370             writefln("\tdottedName = %s", dottedName);
371             foreach(el; stack.opSlice)
372                 writefln("\t%s", el);
373         }
374     }
375 
376     /**
377      * {@inheritDoc}
378      *
379      * <p>The default implementation does nothing.</p>
380      */
381     override public void enterIf_stmt(RuleTranslatorParser.If_stmtContext ctx) {
382         writer.put("if (");
383         debug {
384             writefln("%s enterIf_stmt:", counter++);
385             foreach(el; stack.opSlice)
386                 writefln("\t%s", el);
387         }
388     }
389     /**
390      * {@inheritDoc}
391      *
392      * <p>The default implementation does nothing.</p>
393      */
394     override public void exitIf_stmt(RuleTranslatorParser.If_stmtContext ctx) {
395         writer.indentLevel = -- indentLevel;
396         writer.putnl("}");
397         debug {
398             writefln("%s exitIf_stmt:", counter++);
399             foreach(el; stack.opSlice)
400                 writefln("\t%s", el);
401         }
402     }
403 
404 
405     /**
406      * {@inheritDoc}
407      *
408      * <p>The default implementation does nothing.</p>
409      */
410     override public void exitAtom_dotted_name(RuleTranslatorParser.Atom_dotted_nameContext ctx) {
411         if (!stack.empty) {
412             stack.front ~= dottedName;
413             debug {
414                 writefln("%s exitAtom_dotted_name:", counter++);
415                 foreach(el; stack.opSlice)
416                     writefln("\t%s", el);
417             }
418         }
419     }
420 
421     /**
422      * {@inheritDoc}
423      *
424      * <p>The default implementation does nothing.</p>
425      */
426     override public void enterFunct_name(RuleTranslatorParser.Funct_nameContext ctx) {
427         if (!stack.empty) {
428             stack.front ~= ctx.getText;
429             debug {
430                 writefln("%s enterFunct_name: %s", counter++, ctx.getText);
431                 foreach(el; stack.opSlice)
432                     writefln("\t%s", el);
433             }
434         }
435     }
436     /**
437      * {@inheritDoc}
438      *
439      * <p>The default implementation does nothing.</p>
440      */
441     override public void enterCondition(RuleTranslatorParser.ConditionContext ctx) {
442         string[] conditionBuf;
443         stack.insert(conditionBuf);
444         debug {
445             writefln("%s enterCondition:", counter++);
446             foreach(el; stack.opSlice)
447                 writefln("\t%s", el);
448         }
449     }
450 
451     /**
452      * {@inheritDoc}
453      *
454      * <p>The default implementation does nothing.</p>
455      */
456     override public void exitCondition(RuleTranslatorParser.ConditionContext ctx) {
457         writer.put(stack.front.join);
458         writer.putnl(")");
459         stack.removeFront;
460         writer.putnl("{");
461         writer.indentLevel = ++ indentLevel;
462         debug {
463             writefln("%s exitCondition:", counter++);
464             foreach(el; stack.opSlice)
465                 writefln("\t%s", el);
466         }
467     }
468 
469     /**
470      * {@inheritDoc}
471      *
472      * <p>The default implementation does nothing.</p>
473      */
474     override public void enterNot(RuleTranslatorParser.NotContext ctx) {
475         stack.front ~= "!";
476         debug {
477             writefln("%s enterNot:", counter++);
478             foreach(el; stack.opSlice)
479                 writefln("\t%s", el);
480         }
481     }
482 
483     /**
484      * {@inheritDoc}
485      *
486      * <p>The default implementation does nothing.</p>
487      */
488     override public void enterFunct_parameters(RuleTranslatorParser.Funct_parametersContext ctx) {
489         if (!stack.empty) {
490             string[] s;
491             stack.insert(s);
492             debug {
493                 writefln("%s enterFunct_parameters: %s", counter++, ctx.getText);
494                 foreach(el; stack.opSlice)
495                     writefln("\t%s", el);
496             }
497         }
498     }
499     /**
500      * {@inheritDoc}
501      *
502      * <p>The default implementation does nothing.</p>
503      */
504     override public void exitFunct_parameters(RuleTranslatorParser.Funct_parametersContext ctx) {
505         if (!stack.empty) {
506             auto x = stack.front.join(", ");
507             stack.removeFront;
508             stack.front ~= "(" ~ x ~ ")";
509             debug {
510                 writefln("%s exitFunct_parameters:", counter++);
511                 foreach(el; stack.opSlice)
512                     writefln("\t%s", el);
513             }
514         }
515     }
516 
517     /**
518      * {@inheritDoc}
519      *
520      * <p>The default implementation does nothing.</p>
521      */
522     override public void enterTfpdef_number(RuleTranslatorParser.Tfpdef_numberContext ctx) {
523         if (!stack.empty) {
524             stack.front ~= ctx.getText;
525             debug {
526                 writefln("%s enterTfpdef_number(%s):", counter++, trailerMode);
527                 foreach(el; stack.opSlice)
528                     writefln("\t%s", el);
529             }
530         }
531     }
532 
533     /**
534      * {@inheritDoc}
535      *
536      * <p>The default implementation does nothing.</p>
537      */
538     override public void exitTfpdef_name(RuleTranslatorParser.Tfpdef_nameContext ctx) {
539         if (!stack.empty) {
540             stack.front ~= dottedName;
541             debug {
542                 writefln("%s exitTfpdefName:", counter++);
543                 foreach(el; stack.opSlice)
544                     writefln("\t%s", el);
545             }
546         }
547     }
548 
549     /**
550      * {@inheritDoc}
551      *
552      * <p>The default implementation does nothing.</p>
553      */
554     override public void enterTfpdef_string(RuleTranslatorParser.Tfpdef_stringContext ctx) {
555         if (!stack.empty) {
556             stack.front ~= ctx.getText;
557             debug {
558                 writefln("%s enterTfpdef_string:", counter++);
559                 foreach(el; stack.opSlice)
560                     writefln("\t%s", el);
561             }
562         }
563     }
564 
565     /**
566      * {@inheritDoc}
567      *
568      * <p>The default implementation does nothing.</p>
569      */
570     override public void enterTfpdef_funct_stm(RuleTranslatorParser.Tfpdef_funct_stmContext ctx) {
571         if (!stack.empty) {
572             string[] s;
573             stack.insert(s);
574             debug {
575                 writefln("%s enterTfpdef_funct_stm:", counter++);
576                 foreach(el; stack.opSlice)
577                     writefln("\t%s", el);
578             }
579         }
580     }
581 
582     /**
583      * {@inheritDoc}
584      *
585      * <p>The default implementation does nothing.</p>
586      */
587     override public void exitTfpdef_funct_stm(RuleTranslatorParser.Tfpdef_funct_stmContext ctx) {
588         if (!stack.empty) {
589             auto x = stack.front.join;
590             stack.removeFront;
591             stack.front ~= x;
592             debug {
593                 writefln("%s exitTfpdef_funct_stm:", counter++);
594                 foreach(el; stack.opSlice)
595                     writefln("\t%s", el);
596             }
597         }
598     }
599 
600     /**
601      * {@inheritDoc}
602      *
603      * <p>The default implementation does nothing.</p>
604      */
605     override public void enterElse_e(RuleTranslatorParser.Else_eContext ctx) {
606         writer.indentLevel = -- indentLevel;
607         writer.putnl("}");
608         writer.putnl("else");
609         writer.putnl("{");
610         writer.indentLevel = ++ indentLevel;
611         debug {
612             writefln("%s enterElse_e:", counter++);
613             foreach(el; stack.opSlice)
614                 writefln("\t%s", el);
615         }
616     }
617 
618     /**
619      * {@inheritDoc}
620      *
621      * <p>The default implementation does nothing.</p>
622      */
623     override public void enterElif_e(RuleTranslatorParser.Elif_eContext ctx) {
624         writer.indentLevel = -- indentLevel;
625         writer.putnl("}");
626         writer.put("else if (");
627         debug {
628             writefln("%s enterElif_e:", counter++);
629             foreach(el; stack.opSlice)
630                 writefln("\t%s", el);
631         }
632     }
633 
634     /**
635      * {@inheritDoc}
636      *
637      * <p>The default implementation does nothing.</p>
638      */
639     override public void enterOr_e(RuleTranslatorParser.Or_eContext ctx) {
640         if (!stack.empty) {
641             stack.front ~= " || ";
642         }
643     }
644 
645     /**
646      * {@inheritDoc}
647      *
648      * <p>The default implementation does nothing.</p>
649      */
650     override public void enterAnd_e(RuleTranslatorParser.And_eContext ctx) {
651         if (!stack.empty) {
652             stack.front ~= " && ";
653             debug {
654                 writefln("%s enterAnd_e:", counter++);
655                 foreach(el; stack.opSlice)
656                     writefln("\t%s", el);
657             }
658         }
659     }
660 
661     /**
662      * {@inheritDoc}
663      *
664      * <p>The default implementation does nothing.</p>
665      */
666     override public void enterLess_than(RuleTranslatorParser.Less_thanContext ctx) {
667         if (!stack.empty) {
668             stack.front ~= " < ";
669             debug {
670                 writefln("%s enterLess_than:", counter++);
671                 foreach(el; stack.opSlice)
672                     writefln("\t%s", el);
673             }
674         }
675     }
676 
677     /**
678      * {@inheritDoc}
679      *
680      * <p>The default implementation does nothing.</p>
681      */
682     override public void enterGreater_than(RuleTranslatorParser.Greater_thanContext ctx) {
683         if (!stack.empty) {
684             stack.front ~= " > ";
685             debug {
686                 writefln("%s enterGreater_than:", counter++);
687                 foreach(el; stack.opSlice)
688                     writefln("\t%s", el);
689             }
690         }
691     }
692 
693     /**
694      * {@inheritDoc}
695      *
696      * <p>The default implementation does nothing.</p>
697      */
698     override public void enterGreater_equal(RuleTranslatorParser.Greater_equalContext ctx) {
699         if (!stack.empty) {
700             stack.front ~= " >= ";
701             debug {
702                 writefln("%s enterGreater_equal:", counter++);
703                 foreach(el; stack.opSlice)
704                     writefln("\t%s", el);
705             }
706         }
707     }
708 
709     /**
710      * {@inheritDoc}
711      *
712      * <p>The default implementation does nothing.</p>
713      */
714     override public void enterLess_equal(RuleTranslatorParser.Less_equalContext ctx) {
715         if (!stack.empty) {
716             stack.front ~= " <= ";
717             debug {
718                 writefln("%s enterLess_equal:", counter++);
719                 foreach(el; stack.opSlice)
720                     writefln("\t%s", el);
721             }
722         }
723     }
724 
725     /**
726      * {@inheritDoc}
727      *
728      * <p>The default implementation does nothing.</p>
729      */
730     override public void enterEquals(RuleTranslatorParser.EqualsContext ctx) {
731         if (!stack.empty) {
732             stack.front ~= " == ";
733             debug {
734                 writefln("%s enterEquals:", counter++);
735                 foreach(el; stack.opSlice)
736                     writefln("\t%s", el);
737             }
738         }
739     }
740 
741     /**
742      * {@inheritDoc}
743      *
744      * <p>The default implementation does nothing.</p>
745      */
746     override public void enterNot_equal(RuleTranslatorParser.Not_equalContext ctx) {
747         if (!stack.empty) {
748             stack.front ~= " != ";
749             debug {
750                 writefln("%s enterNot_equal:", counter++);
751                 foreach(el; stack.opSlice)
752                     writefln("\t%s", el);
753             }
754         }
755     }
756 
757     /**
758      * {@inheritDoc}
759      *
760      * <p>The default implementation does nothing.</p>
761      */
762     override public void enterDot_e(RuleTranslatorParser.Dot_eContext ctx) {
763         if (!stack.empty) {
764             stack.front ~= ".";
765             debug {
766                 writefln("%s enterDot_e:", counter++);
767                 foreach(el; stack.opSlice)
768                     writefln("\t%s", el);
769             }
770         }
771     }
772 
773     /**
774      * {@inheritDoc}
775      *
776      * <p>The default implementation does nothing.</p>
777      */
778     override public void enterSmall_stmt(RuleTranslatorParser.Small_stmtContext ctx) {
779         string[] conditionBuf;
780         stack.insert(conditionBuf);
781         debug {
782             writefln("%s enterSmall_stmt:", counter++);
783             foreach(el; stack.opSlice)
784                 writefln("\t%s", el);
785         }
786     }
787 
788     /**
789      * {@inheritDoc}
790      *
791      * <p>The default implementation does nothing.</p>
792      */
793     override public void exitSmall_stmt(RuleTranslatorParser.Small_stmtContext ctx) {
794         if (!stack.empty) {
795             writer.put(stack.front.join);
796             writer.putnl(";");
797             stack.removeFront;
798             debug {
799                 writefln("%s exitSmall_stmt:", counter++);
800                 foreach(el; stack.opSlice)
801                     writefln("\t%s", el);
802             }
803         }
804     }
805 
806     /**
807      * {@inheritDoc}
808      *
809      * <p>The default implementation does nothing.</p>
810      */
811     override public void enterBlock_stmt(RuleTranslatorParser.Block_stmtContext ctx) {
812         string[] conditionBuf;
813         stack.insert(conditionBuf);
814         debug {
815             writefln("%s enterBlock_stmt:", counter++);
816             foreach(el; stack.opSlice)
817                 writefln("\t%s", el);
818         }
819     }
820     /**
821      * {@inheritDoc}
822      *
823      * <p>The default implementation does nothing.</p>
824      */
825     override public void exitBlock_stmt(RuleTranslatorParser.Block_stmtContext ctx) {
826         if (!stack.empty) {
827             writer.putnl(stack.front.join);
828             stack.removeFront;
829             debug {
830                 writefln("%s exitBlock_stmt:", counter++);
831                 foreach(el; stack.opSlice)
832                     writefln("\t%s", el);
833             }
834         }}
835     /**
836      * {@inheritDoc}
837      *
838      * <p>The default implementation does nothing.</p>
839      */
840     override public void enterNumber_e(RuleTranslatorParser.Number_eContext ctx) {
841         if (!stack.empty && !trailerMode) {
842             stack.front ~= ctx.getText;
843             debug {
844                 writefln("%s enterNumber_e(%s):", counter++, trailerMode);
845                 foreach(el; stack.opSlice)
846                     writefln("\t%s", el);
847             }
848         }
849     }
850 
851     /**
852      * {@inheritDoc}
853      *
854      * <p>The default implementation does nothing.</p>
855      */
856     override public void enterString_e(RuleTranslatorParser.String_eContext ctx) {
857         if (!stack.empty)
858             stack.front ~= ctx.getText;
859         debug {
860             writefln("%s enterString_e:", counter++);
861             foreach(el; stack.opSlice)
862                 writefln("\t%s", el);
863         }
864     }
865 
866     /**
867      * {@inheritDoc}
868      *
869      * <p>The default implementation does nothing.</p>
870      */
871     override public void enterAtom_funct_stmt(RuleTranslatorParser.Atom_funct_stmtContext ctx) {
872         if (!stack.empty) {
873             string[] s;
874             stack.insert(s);
875             debug {
876                 writefln("%s enterAtom_funct_stmt:", counter++);
877                 foreach(el; stack.opSlice)
878                     writefln("\t%s", el);
879             }
880         }
881     }
882 
883     /**
884      * {@inheritDoc}
885      *
886      * <p>The default implementation does nothing.</p>
887      */
888     override public void exitAtom_funct_stmt(RuleTranslatorParser.Atom_funct_stmtContext ctx) {
889         if (!stack.empty) {
890             auto x = stack.front;
891             stack.removeFront;
892             stack.front ~= x;
893             debug {
894                 writefln("%s exitAtom_funct_stmt:", counter++);
895                 foreach(el; stack.opSlice)
896                     writefln("\t%s", el);
897             }
898         }
899     }
900 
901     /**
902      * {@inheritDoc}
903      *
904      * <p>The default implementation does nothing.</p>
905      */
906     override public void enterTrue_e(RuleTranslatorParser.True_eContext ctx) {
907         if (!stack.empty)
908             stack.front ~= "true";
909         debug {
910             writefln("%s enterTrue_e:", counter++);
911             foreach(el; stack.opSlice)
912                 writefln("\t%s", el);
913         }
914     }
915 
916     /**
917      * {@inheritDoc}
918      *
919      * <p>The default implementation does nothing.</p>
920      */
921     override public void enterFalse_e(RuleTranslatorParser.False_eContext ctx) {
922         if (!stack.empty)
923             stack.front ~= "false";
924         debug {
925             writefln("%s enterFalse_e:", counter++);
926             foreach(el; stack.opSlice)
927                 writefln("\t%s", el);
928         }
929     }
930 
931     /**
932      * {@inheritDoc}
933      *
934      * <p>The default implementation does nothing.</p>
935      */
936     override public void enterFor_stmt(RuleTranslatorParser.For_stmtContext ctx) {
937         LoopElement l;
938         loopStack.insert(l);
939         writer.put("foreach (");
940     }
941 
942     /**
943      * {@inheritDoc}
944      *
945      * <p>The default implementation does nothing.</p>
946      */
947     override public void exitFor_stmt(RuleTranslatorParser.For_stmtContext ctx) {
948         writer.indentLevel = -- indentLevel;
949         writer.putnl("}");
950         debug {
951             writefln("%s exitFor_stm:", counter++);
952             foreach(el; loopStack.opSlice)
953                 writefln("\t%s", el);
954         }
955         loopStack.removeFront;
956     }
957 
958     /**
959      * {@inheritDoc}
960      *
961      * <p>The default implementation does nothing.</p>
962      */
963     override public void enterFor_exprlist(RuleTranslatorParser.For_exprlistContext ctx) {
964         foreachElementName = ctx.getText;
965     }
966 
967     /**
968      * {@inheritDoc}
969      *
970      * <p>The default implementation does nothing.</p>
971      */
972     override public void enterFor_testlist(RuleTranslatorParser.For_testlistContext ctx) {
973         LoopElement l;
974         l.foreachElementType = foreachElementName;
975         l.foreachType = ctx.getText;
976         l.foreachIndex = 0;
977         loopStack.front = l;
978         debug {
979             writefln("%s enterFor_testlist loop stack:", counter++);
980             foreach(el; loopStack.opSlice)
981                 writefln("\t%s", el);
982         }
983     }
984 
985     /**
986      * {@inheritDoc}
987      *
988      * <p>The default implementation does nothing.</p>
989      */
990     override public void exitFor_testlist(RuleTranslatorParser.For_testlistContext ctx)
991     {
992         writer.putnl(format("%s; %s.iterate)",
993                             loopStack.front.foreachElementType,
994                             loopStack.front.foreachType,
995                             )
996                      );
997         writer.putnl("{");
998         writer.indentLevel = ++ indentLevel;
999         debug {
1000             writefln("%s exitFor_testlist:", counter++);
1001             foreach(el; loopStack.opSlice)
1002                 writefln("\t%s", el);
1003         }
1004     }
1005 
1006     /**
1007      * {@inheritDoc}
1008      *
1009      * <p>The default implementation does nothing.</p>
1010      */
1011     override public void enterFirst_e(RuleTranslatorParser.First_eContext ctx) {
1012         if (!stack.empty)
1013             stack.front ~= format("%s.first",
1014                                   loopStack.front.foreachElementType,
1015                                   );
1016     }
1017 
1018     /**
1019      * {@inheritDoc}
1020      *
1021      * <p>The default implementation does nothing.</p>
1022      */
1023     override public void enterLast_e(RuleTranslatorParser.Last_eContext ctx) {
1024         if (!stack.empty)
1025             stack.front ~= format("%s.last",
1026                                   loopStack.front.foreachElementType);
1027     }
1028     /**
1029      * {@inheritDoc}
1030      *
1031      * <p>The default implementation does nothing.</p>
1032      */
1033     override public void enterAdd(RuleTranslatorParser.AddContext ctx) {
1034         if (!stack.empty) {
1035             stack.front ~= " + ";
1036             debug {
1037                 writefln("%s enterAdd:", counter++);
1038                 foreach(el; stack.opSlice)
1039                     writefln("\t%s", el);
1040             }
1041         }
1042     }
1043 
1044     /**
1045      * {@inheritDoc}
1046      *
1047      * <p>The default implementation does nothing.</p>
1048      */
1049     override public void enterMinus(RuleTranslatorParser.MinusContext ctx) {
1050         if (!stack.empty) {
1051             stack.front ~= " - ";
1052             debug {
1053                 writefln("%s enterMinus:", counter++);
1054                 foreach(el; stack.opSlice)
1055                     writefln("\t%s", el);
1056             }
1057         }
1058     }
1059 
1060     /**
1061      * {@inheritDoc}
1062      *
1063      * <p>The default implementation does nothing.</p>
1064      */
1065     override public void enterTrailer(RuleTranslatorParser.TrailerContext ctx) {
1066         trailerMode = true;
1067     }
1068     /**
1069      * {@inheritDoc}
1070      *
1071      * <p>The default implementation does nothing.</p>
1072      */
1073     override public void exitTrailer(RuleTranslatorParser.TrailerContext ctx) {
1074         trailerMode = false;
1075     }
1076 }