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