xref: /aosp_15_r20/prebuilts/build-tools/common/bison/skeletons/lalr1.d (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
1 # D skeleton for Bison -*- autoconf -*-
2 
3 # Copyright (C) 2007-2012, 2019-2021 Free Software Foundation, Inc.
4 
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 
18 m4_include(b4_skeletonsdir/[d.m4])
19 
20 b4_header_if([b4_complain([%header/%defines does not make sense in D])])
21 
22 # parse.lac
23 b4_percent_define_default([[parse.lac]], [[none]])
24 b4_percent_define_check_values([[[[parse.lac]], [[full]], [[none]]]])
25 b4_define_flag_if([lac])
26 m4_define([b4_lac_flag],
27           [m4_if(b4_percent_define_get([[parse.lac]]),
28                  [none], [[0]], [[1]])])
29 
30 
31 ## --------------- ##
32 ## api.push-pull.  ##
33 ## --------------- ##
34 
35 b4_percent_define_default([[api.push-pull]], [[pull]])
36 b4_percent_define_check_values([[[[api.push-pull]],
37                                  [[pull]], [[push]], [[both]]]])
38 
39 # Define m4 conditional macros that encode the value
40 # of the api.push-pull flag.
41 b4_define_flag_if([pull]) m4_define([b4_pull_flag], [[1]])
42 b4_define_flag_if([push]) m4_define([b4_push_flag], [[1]])
43 m4_case(b4_percent_define_get([[api.push-pull]]),
44         [pull], [m4_define([b4_push_flag], [[0]])],
45         [push], [m4_define([b4_pull_flag], [[0]])])
46 
47 # Define a macro to be true when api.push-pull has the value "both".
48 m4_define([b4_both_if],[b4_push_if([b4_pull_if([$1],[$2])],[$2])])
49 
50 # Handle BISON_USE_PUSH_FOR_PULL for the test suite.  So that push parsing
51 # tests function as written, do not let BISON_USE_PUSH_FOR_PULL modify the
52 # behavior of Bison at all when push parsing is already requested.
53 b4_define_flag_if([use_push_for_pull])
54 b4_use_push_for_pull_if([
55   b4_push_if([m4_define([b4_use_push_for_pull_flag], [[0]])],
56              [m4_define([b4_push_flag], [[1]])])])
57 
58 
59 # Define a macro to encapsulate the parse state variables.  This
60 # allows them to be defined either in parse() when doing pull parsing,
61 # or as class instance variable when doing push parsing.
62 b4_output_begin([b4_parser_file_name])
63 b4_copyright([Skeleton implementation for Bison LALR(1) parsers in D],
64              [2007-2012, 2019-2021])[
65 ]b4_disclaimer[
66 ]b4_percent_define_ifdef([package], [module b4_percent_define_get([package]);
67 ])[
68 version(D_Version2) {
69 } else {
70   static assert(false, "need compiler for D Version 2");
71 }
72 
73 ]b4_user_pre_prologue[
74 ]b4_user_post_prologue[
75 ]b4_percent_code_get([[imports]])[
76 import std.format;
77 import std.conv;
78 
79 /**
80  * Handle error message internationalisation.
81  */
82 static if (!is(typeof(YY_))) {
83   version(YYENABLE_NLS)
84   {
85     version(ENABLE_NLS)
86     {
87       extern(C) char* dgettext(const char*, const char*);
88       string YY_(const char* s)
89       {
90         return to!string(dgettext("bison-runtime", s));
91       }
92     }
93   }
94   static if (!is(typeof(YY_)))
95   {
96     pragma(inline, true)
97     string YY_(string msg) { return msg; }
98   }
99 }
100 
101 /**
102  * A Bison parser, automatically generated from <tt>]m4_bpatsubst(b4_file_name, [^"\(.*\)"$], [\1])[</tt>.
103  *
104  * @@author LALR (1) parser skeleton written by Paolo Bonzini.
105  * Port to D language was done by Oliver Mangold.
106  */
107 
108 /**
109  * Communication interface between the scanner and the Bison-generated
110  * parser <tt>]b4_parser_class[</tt>.
111  */
112 public interface Lexer
113 {
114   /**
115    * Entry point for the scanner.  Returns the token identifier corresponding
116    * to the next token and prepares to return the semantic value
117    * ]b4_locations_if([and beginning/ending positions ])[of the token.
118    * @@return the token identifier corresponding to the next token. */
119   Symbol yylex ();
120 
121   /**
122    * Entry point for error reporting.  Emits an error
123    * ]b4_locations_if([referring to the given location ])[in a user-defined way.
124    *]b4_locations_if([[
125    * @@param loc The location of the element to which the
126    *                error message is related]])[
127    * @@param s The string for the error message.  */
128    void yyerror (]b4_locations_if([[const Location loc, ]])[string s);
129 ]b4_parse_error_bmatch([custom], [[
130   /**
131    * Build and emit a "syntax error" message in a user-defined way.
132    *
133    * @@param ctx  The context of the error.
134    */
135   void reportSyntaxError(]b4_parser_class[.Context ctx);
136 ]])[
137 }
138 
139 ]b4_public_types_declare[
140 
141 ]b4_locations_if([b4_position_type_if([[
142 static assert(__traits(compiles,
143               (new Position[1])[0]=(new Position[1])[0]),
144               "struct/class Position must be default-constructible "
145               "and assignable");
146 static assert(__traits(compiles, (new string[1])[0]=(new Position).toString()),
147               "error: struct/class Position must have toString method");
148 ]], [[
149   /**
150    * A struct denoting a point in the input.*/
151 public struct ]b4_position_type[ {
152 
153   /** The column index within the line of input.  */
154   public int column = 1;
155   /** The line number within an input file.  */
156   public int line = 1;
157   /** The name of the input file.  */
158   public string filename = null;
159 
160   /**
161    * A string representation of the position. */
162   public string toString() const {
163     if (filename)
164       return format("%s:%d.%d", filename, line, column);
165     else
166       return format("%d.%d", line, column);
167   }
168 }
169 ]])b4_location_type_if([[
170 static assert(__traits(compiles, (new Location((new Position[1])[0]))) &&
171               __traits(compiles, (new Location((new Position[1])[0], (new Position[1])[0]))),
172               "error: struct/class Location must have "
173               "default constructor and constructors this(Position) and this(Position, Position).");
174 static assert(__traits(compiles, (new Location[1])[0].begin=(new Location[1])[0].begin) &&
175               __traits(compiles, (new Location[1])[0].begin=(new Location[1])[0].end) &&
176               __traits(compiles, (new Location[1])[0].end=(new Location[1])[0].begin) &&
177               __traits(compiles, (new Location[1])[0].end=(new Location[1])[0].end),
178               "error: struct/class Location must have assignment-compatible "
179               "members/properties 'begin' and 'end'.");
180 static assert(__traits(compiles, (new string[1])[0]=(new Location[1])[0].toString()),
181               "error: struct/class Location must have toString method.");
182 
183 private immutable bool yy_location_is_class = !__traits(compiles, *(new Location((new Position[1])[0])));]], [[
184 /**
185  * A struct defining a pair of positions.  Positions, defined by the
186  * <code>Position</code> struct, denote a point in the input.
187  * Locations represent a part of the input through the beginning
188  * and ending positions.  */
189 public struct ]b4_location_type[
190 {
191   /** The first, inclusive, position in the range.  */
192   public Position begin;
193 
194   /** The first position beyond the range.  */
195   public Position end;
196 
197   /**
198    * Create a <code>Location</code> denoting an empty range located at
199    * a given point.
200    * @@param loc The position at which the range is anchored.  */
201   public this(Position loc)
202   {
203     this.begin = this.end = loc;
204   }
205 
206   /**
207    * Create a <code>Location</code> from the endpoints of the range.
208    * @@param begin The first position included in the range.
209    * @@param end   The first position beyond the range.  */
210   public this(Position begin, Position end)
211   {
212     this.begin = begin;
213     this.end = end;
214   }
215 
216   /**
217    * Reset initial location to final location.
218    */
219   public void step()
220   {
221     this.begin = this.end;
222   }
223 
224   /**
225    * A representation of the location.
226    */
227   public string toString() const
228   {
229     auto end_col = 0 < end.column ? end.column - 1 : 0;
230     auto res = begin.toString ();
231     if (end.filename && begin.filename != end.filename)
232       res ~= "-" ~ format("%s:%d.%d", end.filename, end.line, end_col);
233     else if (begin.line < end.line)
234       res ~= "-" ~ format("%d.%d", end.line, end_col);
235     else if (begin.column < end_col)
236       res ~= "-" ~ format("%d", end_col);
237     return res;
238   }
239 }
240 
241 private immutable bool yy_location_is_class = false;
242 
243 ]])])[]b4_value_type_setup[]m4_ifdef([b4_user_union_members], [private union YYSemanticType
244 {
245 b4_user_union_members
246 };],
247 [m4_if(b4_tag_seen_flag, 0,
248 [[private alias int YYSemanticType;]])])[
249 ]b4_token_enums[
250 ]b4_parser_class_declaration[
251 {
252   ]b4_identification[
253 
254 ]b4_declare_symbol_enum[
255 
256 ]b4_locations_if([[
257   private final Location yylloc_from_stack (ref YYStack rhs, int n)
258   {
259     static if (yy_location_is_class) {
260       if (n > 0)
261         return new Location (rhs.locationAt (n-1).begin, rhs.locationAt (0).end);
262       else
263         return new Location (rhs.locationAt (0).end);
264     } else {
265       if (n > 0)
266         return Location (rhs.locationAt (n-1).begin, rhs.locationAt (0).end);
267       else
268         return Location (rhs.locationAt (0).end);
269     }
270   }]])[
271 
272 ]b4_lexer_if([[  private class YYLexer implements Lexer {
273 ]b4_percent_code_get([[lexer]])[
274   }
275 ]])[
276   /** The object doing lexical analysis for us.  */
277   private Lexer yylexer;
278 
279 ]b4_parse_param_vars[
280 
281 ]b4_lexer_if([[
282   /**
283    * Instantiate the Bison-generated parser.
284    */
285   public this] (b4_parse_param_decl([b4_lex_param_decl])[) {
286 ]b4_percent_code_get([[init]])[]b4_lac_if([[
287     this.yylacStack = new int[];
288     this.yylacEstablished = false;]])[
289     this (new YYLexer(]b4_lex_param_call[));
290   }
291 ]])[
292 
293   /**
294    * Instantiate the Bison-generated parser.
295    * @@param yylexer The scanner that will supply tokens to the parser.
296    */
297   ]b4_lexer_if([[protected]], [[public]]) [this (]b4_parse_param_decl([[Lexer yylexer]])[) {
298     this.yylexer = yylexer;]b4_parse_trace_if([[
299     this.yyDebugStream = stderr;]])[
300 ]b4_parse_param_cons[
301   }
302 ]b4_parse_trace_if([[
303   import std.stdio;
304   private File yyDebugStream;
305 
306   /**
307    * The <tt>File</tt> on which the debugging output is
308    * printed.
309    */
310   public File getDebugStream () { return yyDebugStream; }
311 
312   /**
313    * Set the <tt>std.File</tt> on which the debug output is printed.
314    * @@param s The stream that is used for debugging output.
315    */
316   public final void setDebugStream(File s) { yyDebugStream = s; }
317 
318   private int yydebug = 0;
319 
320   /**
321    * Answer the verbosity of the debugging output; 0 means that all kinds of
322    * output from the parser are suppressed.
323    */
324   public final int getDebugLevel() { return yydebug; }
325 
326   /**
327    * Set the verbosity of the debugging output; 0 means that all kinds of
328    * output from the parser are suppressed.
329    * @@param level The verbosity level for debugging output.
330    */
331   public final void setDebugLevel(int level) { yydebug = level; }
332 
333   protected final void yycdebug (string s) {
334     if (0 < yydebug)
335       yyDebugStream.write (s);
336   }
337 
338   protected final void yycdebugln (string s) {
339     if (0 < yydebug)
340       yyDebugStream.writeln (s);
341   }
342 ]])[
343   private final ]b4_parser_class[.Symbol yylex () {
344     return yylexer.yylex ();
345   }
346 
347   protected final void yyerror (]b4_locations_if([[const Location loc, ]])[string s) {
348     yylexer.yyerror (]b4_locations_if([loc, ])[s);
349   }
350 
351   /**
352    * The number of syntax errors so far.
353    */
354   public int numberOfErrors() const { return yynerrs_; }
355   private int yynerrs_ = 0;
356 
357   /**
358    * Returned by a Bison action in order to stop the parsing process and
359    * return success (<tt>true</tt>).  */
360   public static immutable int YYACCEPT = 0;
361 
362   /**
363    * Returned by a Bison action in order to stop the parsing process and
364    * return failure (<tt>false</tt>).  */
365   public static immutable int YYABORT = 1;
366 ]b4_push_if([
367   /**
368    * Returned by a Bison action in order to request a new token.
369    */
370   public static immutable int YYPUSH_MORE = 4;])[
371 
372   /**
373    * Returned by a Bison action in order to start error recovery without
374    * printing an error message.  */
375   public static immutable int YYERROR = 2;
376 
377   // Internal return codes that are not supported for user semantic
378   // actions.
379   private static immutable int YYERRLAB = 3;
380   private static immutable int YYNEWSTATE = 4;
381   private static immutable int YYDEFAULT = 5;
382   private static immutable int YYREDUCE = 6;
383   private static immutable int YYERRLAB1 = 7;
384   private static immutable int YYRETURN = 8;
385 ]b4_push_if([[  private static immutable int YYGETTOKEN = 9; /* Signify that a new token is expected when doing push-parsing.  */]])[
386 
387 ]b4_locations_if([
388   private static immutable YYSemanticType yy_semantic_null;])[
389   private int yyerrstatus_ = 0;
390 
391   private void yyerrok()
392   {
393     yyerrstatus_ = 0;
394   }
395 
396   // Lookahead symbol kind.
397   SymbolKind yytoken = ]b4_symbol(empty, kind)[;
398 
399   /* State.  */
400   int yyn = 0;
401   int yylen = 0;
402   int yystate = 0;
403 
404   YYStack yystack;
405 
406   int label = YYNEWSTATE;
407 
408   /* Error handling.  */
409 ]b4_locations_if([[
410   /// The location where the error started.
411   Location yyerrloc;
412 
413   /// Location of the lookahead.
414   Location yylloc;
415 
416   /// @@$.
417   Location yyloc;]])[
418 
419   /// Semantic value of the lookahead.
420   Value yylval;
421 
422   /**
423    * Whether error recovery is being done.  In this state, the parser
424    * reads token until it reaches a known state, and then restarts normal
425    * operation.  */
426   public final bool recovering ()
427   {
428     return yyerrstatus_ == 0;
429   }
430 
431   /** Compute post-reduction state.
432    * @@param yystate   the current state
433    * @@param yysym     the nonterminal to push on the stack
434    */
435   private int yyLRGotoState(int yystate, int yysym) {
436     int yyr = yypgoto_[yysym - yyntokens_] + yystate;
437     if (0 <= yyr && yyr <= yylast_ && yycheck_[yyr] == yystate)
438       return yytable_[yyr];
439     else
440       return yydefgoto_[yysym - yyntokens_];
441   }
442 
443   private int yyaction (int yyn, ref YYStack yystack, int yylen)
444   {
445     Value yyval;]b4_locations_if([[
446     Location yyloc = yylloc_from_stack (yystack, yylen);]])[
447 
448     /* If YYLEN is nonzero, implement the default value of the action:
449        `$$ = $1'.  Otherwise, use the top of the stack.
450 
451        Otherwise, the following line sets YYVAL to garbage.
452        This behavior is undocumented and Bison
453        users should not rely upon it.  */
454     if (yylen > 0)
455       yyval = yystack.valueAt (yylen - 1);
456     else
457       yyval = yystack.valueAt (0);
458 
459 ]b4_parse_trace_if([[
460     yy_reduce_print (yyn, yystack);]])[
461 
462     switch (yyn)
463     {
464 ]b4_user_actions[
465       default: break;
466     }
467 
468 ]b4_parse_trace_if([[
469     yy_symbol_print ("-> $$ =", to!SymbolKind (yyr1_[yyn]), yyval]b4_locations_if([, yyloc])[);]])[
470 
471     yystack.pop (yylen);
472     yylen = 0;
473 
474     /* Shift the result of the reduction.  */
475     int yystate = yyLRGotoState(yystack.stateAt(0), yyr1_[yyn]);
476     yystack.push (yystate, yyval]b4_locations_if([, yyloc])[);
477     return YYNEWSTATE;
478   }
479 
480 ]b4_parse_trace_if([[
481   /*--------------------------------.
482   | Print this symbol on YYOUTPUT.  |
483   `--------------------------------*/
484 
485   private final void yy_symbol_print (string s, SymbolKind yykind,
486     ref Value yyval]b4_locations_if([, ref Location yyloc])[)
487   {
488     if (0 < yydebug)
489     {
490       File yyo = yyDebugStream;
491       yyo.write(s);
492       yyo.write(yykind < yyntokens_ ? " token " : " nterm ");
493       yyo.write(format("%s", yykind));
494       yyo.write(" ("]b4_locations_if([ ~ yyloc.toString() ~ ": "])[);
495       ]b4_symbol_actions([printer])[
496       yyo.write(")\n");
497     }
498   }
499 ]])[
500 ]b4_symbol_type_define[
501 ]b4_push_if([[
502   /**
503    * Push Parse input from external lexer
504    *
505    * @@param yyla current Symbol
506    *
507    * @@return <tt>YYACCEPT, YYABORT, YYPUSH_MORE</tt>
508    */
509   public int pushParse(Symbol yyla)]], [[
510   /**
511    * Parse input from the scanner that was specified at object construction
512    * time.  Return whether the end of the input was reached successfully.
513    *
514    * @@return <tt>true</tt> if the parsing succeeds.  Note that this does not
515    *          imply that there were no syntax errors.
516    */
517   public bool parse()]])[
518   {]b4_push_if([[
519     if (!this.pushParseInitialized)
520     {
521       pushParseInitialize();
522       yyerrstatus_ = 0;
523     }
524     else
525       label = YYGETTOKEN;
526 
527     bool push_token_consumed = true;
528 ]], [[  bool yyresult;]b4_lac_if([[
529     // Discard the LAC context in case there still is one left from a
530     // previous invocation.
531     yylacDiscard("init");]])[]b4_parse_trace_if([[
532 
533     yycdebugln ("Starting parse");]])[
534     yyerrstatus_ = 0;
535 
536 ]m4_ifdef([b4_initial_action], [
537 m4_pushdef([b4_at_dollar],     [yylloc])dnl
538 m4_pushdef([b4_dollar_dollar], [yylval])dnl
539     /* User initialization code.  */
540     b4_user_initial_action
541 m4_popdef([b4_dollar_dollar])dnl
542 m4_popdef([b4_at_dollar])])dnl
543 
544   [  /* Initialize the stack.  */
545     yystack.push (yystate, yylval]b4_locations_if([, yylloc])[);
546 
547     label = YYNEWSTATE;]])[
548     for (;;)
549       final switch (label)
550       {
551         /* New state.  Unlike in the C/C++ skeletons, the state is already
552            pushed when we come here.  */
553       case YYNEWSTATE:]b4_parse_trace_if([[
554         yycdebugln (format("Entering state %d", yystate));
555         if (0 < yydebug)
556           yystack.print (yyDebugStream);]])[
557 
558         /* Accept?  */
559         if (yystate == yyfinal_)]b4_push_if([[
560         {
561           label = YYACCEPT;
562           break;
563         }]], [[
564           return true;]])[
565 
566         /* Take a decision.  First try without lookahead.  */
567         yyn = yypact_[yystate];
568         if (yyPactValueIsDefault(yyn))
569         {
570           label = YYDEFAULT;
571           break;
572         }]b4_push_if([[
573         goto case;
574 
575         case YYGETTOKEN:]])[
576 
577         /* Read a lookahead token.  */
578         if (yytoken == ]b4_symbol(empty, kind)[)
579         {]b4_push_if([[
580           if (!push_token_consumed)
581             return YYPUSH_MORE;]])[]b4_parse_trace_if([[
582           yycdebugln ("Reading a token");]])[]b4_push_if([[
583           yytoken = yyla.token;
584           yylval = yyla.value;]b4_locations_if([[
585           yylloc = yyla.location;]])[
586           push_token_consumed = false;]], [[
587           Symbol yysymbol = yylex();
588           yytoken = yysymbol.token();
589           yylval = yysymbol.value();]b4_locations_if([[
590           yylloc = yysymbol.location();]])[]])[
591         }
592 
593         /* Token already converted to internal form.  */]b4_parse_trace_if([[
594         yy_symbol_print ("Next token is", yytoken, yylval]b4_locations_if([, yylloc])[);]])[
595 
596         if (yytoken == ]b4_symbol(error, kind)[)
597         {
598           // The scanner already issued an error message, process directly
599           // to error recovery.  But do not keep the error token as
600           // lookahead, it is too special and may lead us to an endless
601           // loop in error recovery. */
602           yytoken = ]b4_symbol(undef, kind)[;]b4_locations_if([[
603           yyerrloc = yylloc;]])[
604           label = YYERRLAB1;
605         }
606         else
607         {
608           /* If the proper action on seeing token YYTOKEN is to reduce or to
609              detect an error, take that action.  */
610           yyn += yytoken;
611           if (yyn < 0 || yylast_ < yyn || yycheck_[yyn] != yytoken) {]b4_lac_if([[
612             if (!yylacEstablish(yystack, yytoken))
613               label = YYERRLAB;
614             else]])[
615               label = YYDEFAULT;
616           }
617           /* <= 0 means reduce or error.  */
618           else if ((yyn = yytable_[yyn]) <= 0)
619           {
620             if (yyTableValueIsError(yyn))
621               label = YYERRLAB;]b4_lac_if([[
622             else if (!yylacEstablish(yystack, yytoken))
623               label = YYERRLAB;]])[
624             else
625             {
626               yyn = -yyn;
627               label = YYREDUCE;
628             }
629           }
630           else
631           {
632             /* Shift the lookahead token.  */]b4_parse_trace_if([[
633             yy_symbol_print ("Shifting", yytoken, yylval]b4_locations_if([, yylloc])[);]])[
634 
635             /* Discard the token being shifted.  */
636             yytoken = ]b4_symbol(empty, kind)[;
637 
638             /* Count tokens shifted since error; after three, turn off error
639              * status.  */
640             if (yyerrstatus_ > 0)
641               --yyerrstatus_;
642 
643             yystate = yyn;
644             yystack.push (yystate, yylval]b4_locations_if([, yylloc])[);]b4_lac_if([[
645             yylacDiscard("shift");]])[
646             label = YYNEWSTATE;
647           }
648         }
649         break;
650 
651       /*-----------------------------------------------------------.
652       | yydefault -- do the default action for the current state.  |
653       `-----------------------------------------------------------*/
654       case YYDEFAULT:
655         yyn = yydefact_[yystate];
656         if (yyn == 0)
657           label = YYERRLAB;
658         else
659           label = YYREDUCE;
660         break;
661 
662       /*-----------------------------.
663       | yyreduce -- Do a reduction.  |
664       `-----------------------------*/
665       case YYREDUCE:
666         yylen = yyr2_[yyn];
667         label = yyaction (yyn, yystack, yylen);
668         yystate = yystack.stateAt (0);
669         break;
670 
671       /*--------------------------------------.
672       | yyerrlab -- here on detecting error.  |
673       `--------------------------------------*/
674       case YYERRLAB:
675         /* If not already recovering from an error, report this error.  */
676         if (yyerrstatus_ == 0)
677         {
678           ++yynerrs_;
679           yyreportSyntaxError(new Context(]b4_lac_if([[this, ]])[yystack, yytoken]b4_locations_if([[, yylloc]])[));
680         }
681 ]b4_locations_if([
682         yyerrloc = yylloc;])[
683         if (yyerrstatus_ == 3)
684         {
685           /* If just tried and failed to reuse lookahead token after an
686            * error, discard it.  */
687 
688           /* Return failure if at end of input.  */
689           if (yytoken == ]b4_symbol(eof, [kind])[)]b4_push_if([[
690           {
691             label = YYABORT;
692             break;
693           }]], [[
694           return false;]])[
695           else
696             yytoken = ]b4_symbol(empty, kind)[;
697         }
698 
699         /* Else will try to reuse lookahead token after shifting the error
700          * token.  */
701         label = YYERRLAB1;
702         break;
703 
704       /*-------------------------------------------------.
705       | errorlab -- error raised explicitly by YYERROR.  |
706       `-------------------------------------------------*/
707       case YYERROR:]b4_locations_if([
708         yyerrloc = yystack.locationAt (yylen - 1);])[
709         /* Do not reclaim the symbols of the rule which action triggered
710            this YYERROR.  */
711         yystack.pop (yylen);
712         yylen = 0;
713         yystate = yystack.stateAt (0);
714         label = YYERRLAB1;
715         break;
716 
717       /*-------------------------------------------------------------.
718       | yyerrlab1 -- common code for both syntax error and YYERROR.  |
719       `-------------------------------------------------------------*/
720       case YYERRLAB1:
721         yyerrstatus_ = 3;       /* Each real token shifted decrements this.  */
722 
723         // Pop stack until we find a state that shifts the error token.
724         for (;;)
725         {
726           yyn = yypact_[yystate];
727           if (!yyPactValueIsDefault(yyn))
728           {
729             yyn += ]b4_symbol(error, kind)[;
730             if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == ]b4_symbol(error, kind)[)
731             {
732               yyn = yytable_[yyn];
733               if (0 < yyn)
734                 break;
735                   }
736           }
737 
738           /* Pop the current state because it cannot handle the error token.  */
739           if (yystack.height == 1)]b4_push_if([[
740           {
741             label = YYABORT;
742             break;
743           }]],[[
744             return false;]])[
745 
746 ]b4_locations_if([          yyerrloc = yystack.locationAt (0);])[
747           yystack.pop ();
748           yystate = yystack.stateAt (0);]b4_parse_trace_if([[
749           if (0 < yydebug)
750             yystack.print (yyDebugStream);]])[
751         }]b4_push_if([[
752         if (label == YYABORT)
753           /* Leave the switch.  */
754           break;
755 ]])[
756 ]b4_locations_if([
757         /* Muck with the stack to setup for yylloc.  */
758         yystack.push (0, yy_semantic_null, yylloc);
759         yystack.push (0, yy_semantic_null, yyerrloc);
760         yyloc = yylloc_from_stack (yystack, 2);
761         yystack.pop (2);])[
762 
763         /* Shift the error token.  */]b4_lac_if([[
764         yylacDiscard("error recovery");]])[]b4_parse_trace_if([[
765         yy_symbol_print ("Shifting", to!SymbolKind (yystos_[yyn]), yylval]b4_locations_if([, yyloc])[);]])[
766         yystate = yyn;
767         yystack.push (yyn, yylval]b4_locations_if([, yyloc])[);
768         label = YYNEWSTATE;
769         break;
770 
771       /* Accept.  */
772       case YYACCEPT:]b4_push_if([[
773         this.pushParseInitialized = false;]b4_parse_trace_if([[
774         if (0 < yydebug)
775           yystack.print (yyDebugStream);]])[
776         return YYACCEPT;]], [[
777         yyresult = true;
778         label = YYRETURN;
779         break;]])[
780 
781       /* Abort.  */
782       case YYABORT:]b4_push_if([[
783         this.pushParseInitialized = false;]b4_parse_trace_if([[
784         if (0 < yydebug)
785           yystack.print (yyDebugStream);]])[
786         return YYABORT;]], [[
787         yyresult = false;
788         label = YYRETURN;
789         break;]])[
790 ]b4_push_if([[]], [[      ][case YYRETURN:]b4_parse_trace_if([[
791         if (0 < yydebug)
792           yystack.print (yyDebugStream);]])[
793         return yyresult;]])[
794     }
795     assert(0);
796   }
797 
798 ]b4_push_if([[
799   bool pushParseInitialized = false;
800 
801   /**
802    * (Re-)Initialize the state of the push parser.
803    */
804   public void pushParseInitialize()
805   {
806 
807     /* Lookahead and lookahead in internal form.  */
808     this.yytoken = ]b4_symbol(empty, kind)[;
809 
810     /* State.  */
811     this.yyn = 0;
812     this.yylen = 0;
813     this.yystate = 0;
814     destroy(this.yystack);
815     this.label = YYNEWSTATE;
816 ]b4_lac_if([[
817     destroy(this.yylacStack);
818     this.yylacEstablished = false;]])[
819 
820     /* Error handling.  */
821     this.yynerrs_ = 0;
822 ]b4_locations_if([
823     /* The location where the error started.  */
824     this.yyerrloc = Location(Position(), Position());
825     this.yylloc = Location(Position(), Position());])[
826 
827     /* Semantic value of the lookahead.  */
828     //destroy(this.yylval);
829 
830     /* Initialize the stack.  */
831     yystack.push(this.yystate, this.yylval]b4_locations_if([, this.yylloc])[);
832 
833     this.pushParseInitialized = true;
834   }]])[]b4_both_if([[
835   /**
836    * Parse input from the scanner that was specified at object construction
837    * time.  Return whether the end of the input was reached successfully.
838    * This version of parse() is defined only when api.push-push=both.
839    *
840    * @@return <tt>true</tt> if the parsing succeeds.  Note that this does not
841    *          imply that there were no syntax errors.
842    */
843   bool parse()
844   {
845     int status = 0;
846     do {
847       status = this.pushParse(yylex());
848     } while (status == YYPUSH_MORE);
849     return status == YYACCEPT;
850   }]])[
851 
852   // Generate an error message.
853   private final void yyreportSyntaxError(Context yyctx)
854   {]b4_parse_error_bmatch(
855 [custom], [[
856     yylexer.reportSyntaxError(yyctx);]],
857 [detailed], [[
858     if (yyctx.getToken() != ]b4_symbol(empty, kind)[)
859     {
860       // FIXME: This method of building the message is not compatible
861       // with internationalization.
862       immutable int argmax = 5;
863       SymbolKind[] yyarg = new SymbolKind[argmax];
864       int yycount = yysyntaxErrorArguments(yyctx, yyarg, argmax);
865       string res, yyformat;
866       switch (yycount)
867       {
868         case  1:
869           yyformat = YY_("syntax error, unexpected %s");
870           res = format(yyformat, yyarg[0]);
871          break;
872         case  2:
873           yyformat = YY_("syntax error, unexpected %s, expecting %s");
874           res = format(yyformat, yyarg[0], yyarg[1]);
875           break;
876         case  3:
877           yyformat = YY_("syntax error, unexpected %s, expecting %s or %s");
878           res = format(yyformat, yyarg[0], yyarg[1], yyarg[2]);
879           break;
880         case  4:
881           yyformat = YY_("syntax error, unexpected %s, expecting %s or %s or %s");
882           res = format(yyformat, yyarg[0], yyarg[1], yyarg[2], yyarg[3]);
883           break;
884         case  5:
885           yyformat = YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
886           res = format(yyformat, yyarg[0], yyarg[1], yyarg[2], yyarg[3], yyarg[4]);
887           break;
888         default:
889           res = YY_("syntax error");
890           break;
891       }
892       yyerror(]b4_locations_if([yyctx.getLocation(), ])[res);
893     }]],
894 [[simple]], [[
895     yyerror(]b4_locations_if([yyctx.getLocation(), ])[YY_("syntax error"));]])[
896   }
897 
898 ]b4_parse_error_bmatch(
899 [detailed], [[
900   private int yysyntaxErrorArguments(Context yyctx, SymbolKind[] yyarg, int yyargn) {
901     /* There are many possibilities here to consider:
902        - If this state is a consistent state with a default action,
903          then the only way this function was invoked is if the
904          default action is an error action.  In that case, don't
905          check for expected tokens because there are none.
906        - The only way there can be no lookahead present (in tok) is
907          if this state is a consistent state with a default action.
908          Thus, detecting the absence of a lookahead is sufficient to
909          determine that there is no unexpected or expected token to
910          report.  In that case, just report a simple "syntax error".
911        - Don't assume there isn't a lookahead just because this
912          state is a consistent state with a default action.  There
913          might have been a previous inconsistent state, consistent
914          state with a non-default action, or user semantic action
915          that manipulated yychar.  (However, yychar is currently out
916          of scope during semantic actions.)
917        - Of course, the expected token list depends on states to
918          have correct lookahead information, and it depends on the
919          parser not to perform extra reductions after fetching a
920          lookahead from the scanner and before detecting a syntax
921          error.  Thus, state merging (from LALR or IELR) and default
922          reductions corrupt the expected token list.  However, the
923          list is correct for canonical LR with one exception: it
924          will still contain any token that will not be accepted due
925          to an error action in a later state.
926     */
927     int yycount = 0;
928     if (yyctx.getToken() != ]b4_symbol(empty, kind)[)
929       {
930         if (yyarg !is null)
931           yyarg[yycount] = yyctx.getToken();
932         yycount += 1;
933         yycount += yyctx.getExpectedTokens(yyarg, 1, yyargn);
934       }
935     return yycount;
936   }
937 ]])[
938 
939 
940   /**
941    * Information needed to get the list of expected tokens and to forge
942    * a syntax error diagnostic.
943    */
944   public static final class Context
945   {]b4_lac_if([[
946     private ]b4_parser_class[ yyparser;]])[
947     private const(YYStack) yystack;
948     private SymbolKind yytoken;]b4_locations_if([[
949     private const(Location) yylocation;]])[
950 
951     this(]b4_lac_if([[]b4_parser_class[ parser, ]])[YYStack stack, SymbolKind kind]b4_locations_if([[, Location loc]])[)
952     {]b4_lac_if([[
953         yyparser = parser;]])[
954       yystack = stack;
955       yytoken = kind;]b4_locations_if([[
956       yylocation = loc;]])[
957     }
958 
959     final SymbolKind getToken() const
960     {
961       return yytoken;
962     }]b4_locations_if([[
963 
964     final const(Location) getLocation() const
965     {
966       return yylocation;
967     }]])[
968     /**
969      * Put in YYARG at most YYARGN of the expected tokens given the
970      * current YYCTX, and return the number of tokens stored in YYARG.  If
971      * YYARG is null, return the number of expected tokens (guaranteed to
972      * be less than YYNTOKENS).
973      */
974     int getExpectedTokens(SymbolKind[] yyarg, int yyargn)]b4_lac_if([[]], [[ const]])[
975     {
976       return getExpectedTokens(yyarg, 0, yyargn);
977     }
978 
979     int getExpectedTokens(SymbolKind[] yyarg, int yyoffset, int yyargn)]b4_lac_if([[]], [[ const]])[
980     {
981       int yycount = yyoffset;]b4_lac_if([b4_parse_trace_if([[
982       // Execute LAC once. We don't care if it is successful, we
983       // only do it for the sake of debugging output.
984 
985       if (!yyparser.yylacEstablished)
986         yyparser.yylacCheck(yystack, yytoken);
987 ]])[
988       for (int yyx = 0; yyx < yyntokens_; ++yyx)
989         {
990           SymbolKind yysym = SymbolKind(yyx);
991           if (yysym != ]b4_symbol(error, kind)[
992               && yysym != ]b4_symbol(undef, kind)[
993               && yyparser.yylacCheck(yystack, yysym))
994             {
995               if (yyarg == null)
996                 yycount += 1;
997               else if (yycount == yyargn)
998                 return 0;
999               else
1000                 yyarg[yycount++] = yysym;
1001             }
1002         }]], [[
1003       int yyn = yypact_[this.yystack.stateAt(0)];
1004       if (!yyPactValueIsDefault(yyn))
1005       {
1006         /* Start YYX at -YYN if negative to avoid negative
1007            indexes in YYCHECK.  In other words, skip the first
1008            -YYN actions for this state because they are default
1009            actions.  */
1010         int yyxbegin = yyn < 0 ? -yyn : 0;
1011         /* Stay within bounds of both yycheck and yytname.  */
1012         int yychecklim = yylast_ - yyn + 1;
1013         int yyxend = yychecklim < yyntokens_ ? yychecklim : yyntokens_;
1014         for (int yyx = yyxbegin; yyx < yyxend; ++yyx)
1015           if (yycheck_[yyx + yyn] == yyx && yyx != ]b4_symbol(error, kind)[
1016               && !yyTableValueIsError(yytable_[yyx + yyn]))
1017           {
1018             if (yyarg is null)
1019               ++yycount;
1020             else if (yycount == yyargn)
1021               return 0;
1022             else
1023               yyarg[yycount++] = SymbolKind(yyx);
1024           }
1025       }]])[
1026       if (yyarg !is null && yycount == yyoffset && yyoffset < yyargn)
1027         yyarg[yyoffset] = ]b4_symbol(empty, kind)[;
1028       return yycount - yyoffset;
1029     }
1030   }
1031 
1032 ]b4_lac_if([[
1033   /** Check the lookahead yytoken.
1034    * \returns  true iff the token will be eventually shifted.
1035    */
1036   bool yylacCheck(const YYStack yystack, SymbolKind yytoken)
1037   {
1038     // Logically, the yylacStack's lifetime is confined to this function.
1039     // Clear it, to get rid of potential left-overs from previous call.
1040     destroy(yylacStack);
1041     // Reduce until we encounter a shift and thereby accept the token.
1042 ]b4_parse_trace_if([[
1043     yycdebug("LAC: checking lookahead " ~ format("%s", yytoken) ~ ":");]])[
1044     int lacTop = 0;
1045     while (true)
1046     {
1047       int topState = (yylacStack.length == 0
1048                       ? yystack.stateAt(lacTop)
1049                       : yylacStack[$ - 1]);
1050       int yyrule = yypact_[topState];
1051       if (yyPactValueIsDefault(yyrule)
1052           || (yyrule += yytoken) < 0 || yylast_ < yyrule
1053           || yycheck_[yyrule] != yytoken)
1054       {
1055         // Use the default action.
1056         yyrule = yydefact_[+topState];
1057         if (yyrule == 0)
1058         {]b4_parse_trace_if([[
1059           yycdebugln(" Err");]])[
1060           return false;
1061         }
1062       }
1063       else
1064       {
1065         // Use the action from yytable.
1066         yyrule = yytable_[yyrule];
1067         if (yyTableValueIsError(yyrule))
1068         {]b4_parse_trace_if([[
1069           yycdebugln(" Err");]])[
1070           return false;
1071         }
1072         if (0 < yyrule)
1073         {]b4_parse_trace_if([[
1074           yycdebugln(" S" ~ to!string(yyrule));]])[
1075           return true;
1076         }
1077         yyrule = -yyrule;
1078       }
1079       // By now we know we have to simulate a reduce.
1080 ]b4_parse_trace_if([[
1081       yycdebug(" R" ~ to!string(yyrule - 1));]])[
1082       // Pop the corresponding number of values from the stack.
1083       {
1084         int yylen = yyr2_[yyrule];
1085         // First pop from the LAC stack as many tokens as possible.
1086         int lacSize = cast (int) yylacStack.length;
1087         if (yylen < lacSize)
1088         {
1089           yylacStack.length -= yylen;
1090           yylen = 0;
1091         }
1092         else if (lacSize != 0)
1093         {
1094           destroy(yylacStack);
1095           yylen -= lacSize;
1096         }
1097         // Only afterwards look at the main stack.
1098         // We simulate popping elements by incrementing lacTop.
1099         lacTop += yylen;
1100       }
1101       // Keep topState in sync with the updated stack.
1102       topState = (yylacStack.length == 0
1103                   ? yystack.stateAt(lacTop)
1104                   : yylacStack[$ - 1]);
1105       // Push the resulting state of the reduction.
1106       int state = yyLRGotoState(topState, yyr1_[yyrule]);]b4_parse_trace_if([[
1107       yycdebug(" G" ~ to!string(state));]])[
1108       yylacStack.length++;
1109       yylacStack[$ - 1] = state;
1110     }
1111   }
1112 
1113   /** Establish the initial context if no initial context currently exists.
1114    * \returns  true iff the token will be eventually shifted.
1115    */
1116   bool yylacEstablish(YYStack yystack, SymbolKind yytoken)
1117   {
1118   /* Establish the initial context for the current lookahead if no initial
1119      context is currently established.
1120 
1121      We define a context as a snapshot of the parser stacks.  We define
1122      the initial context for a lookahead as the context in which the
1123      parser initially examines that lookahead in order to select a
1124      syntactic action.  Thus, if the lookahead eventually proves
1125      syntactically unacceptable (possibly in a later context reached via a
1126      series of reductions), the initial context can be used to determine
1127      the exact set of tokens that would be syntactically acceptable in the
1128      lookahead's place.  Moreover, it is the context after which any
1129      further semantic actions would be erroneous because they would be
1130      determined by a syntactically unacceptable token.
1131 
1132      yylacEstablish should be invoked when a reduction is about to be
1133      performed in an inconsistent state (which, for the purposes of LAC,
1134      includes consistent states that don't know they're consistent because
1135      their default reductions have been disabled).
1136 
1137      For parse.lac=full, the implementation of yylacEstablish is as
1138      follows.  If no initial context is currently established for the
1139      current lookahead, then check if that lookahead can eventually be
1140      shifted if syntactic actions continue from the current context.  */
1141     if (yylacEstablished)
1142       return true;
1143     else
1144     {]b4_parse_trace_if([[
1145         yycdebugln("LAC: initial context established for " ~ format("%s", yytoken));]])[
1146         yylacEstablished = true;
1147         return yylacCheck(yystack, yytoken);
1148     }
1149   }
1150 
1151   /** Discard any previous initial lookahead context because of event.
1152    * \param event  the event which caused the lookahead to be discarded.
1153    *               Only used for debbuging output.  */
1154   void yylacDiscard(string event)
1155   {
1156   /* Discard any previous initial lookahead context because of Event,
1157      which may be a lookahead change or an invalidation of the currently
1158      established initial context for the current lookahead.
1159 
1160      The most common example of a lookahead change is a shift.  An example
1161      of both cases is syntax error recovery.  That is, a syntax error
1162      occurs when the lookahead is syntactically erroneous for the
1163      currently established initial context, so error recovery manipulates
1164      the parser stacks to try to find a new initial context in which the
1165      current lookahead is syntactically acceptable.  If it fails to find
1166      such a context, it discards the lookahead.  */
1167     if (yylacEstablished)
1168     {]b4_parse_trace_if([[
1169       yycdebugln("LAC: initial context discarded due to " ~ event);]])[
1170       yylacEstablished = false;
1171     }
1172   }
1173 
1174   /** The stack for LAC.
1175    * Logically, the yylacStack's lifetime is confined to the function
1176    * yylacCheck. We just store it as a member of this class to hold
1177    * on to the memory and to avoid frequent reallocations.
1178    */
1179   int[] yylacStack;
1180   /**  Whether an initial LAC context was established. */
1181   bool yylacEstablished;
1182 ]])[
1183 
1184   /**
1185    * Whether the given <code>yypact_</code> value indicates a defaulted state.
1186    * @@param yyvalue   the value to check
1187    */
1188   private static bool yyPactValueIsDefault(int yyvalue)
1189   {
1190     return yyvalue == yypact_ninf_;
1191   }
1192 
1193   /**
1194    * Whether the given <code>yytable_</code> value indicates a syntax error.
1195    * @@param yyvalue   the value to check
1196    */
1197   private static bool yyTableValueIsError(int yyvalue)
1198   {
1199     return yyvalue == yytable_ninf_;
1200   }
1201 
1202   /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
1203      STATE-NUM.  */
1204   private static immutable ]b4_int_type_for([b4_pact])[ yypact_ninf_ = ]b4_pact_ninf[;
1205 
1206   /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
1207      positive, shift that token.  If negative, reduce the rule which
1208      number is the opposite.  If YYTABLE_NINF_, syntax error.  */
1209   private static immutable ]b4_int_type_for([b4_table])[ yytable_ninf_ = ]b4_table_ninf[;
1210 
1211   ]b4_parser_tables_define[
1212 
1213 ]b4_parse_trace_if([[
1214   /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
1215   private static immutable ]b4_int_type_for([b4_rline])[[] yyrline_ =
1216   @{
1217   ]b4_rline[
1218   @};
1219 
1220   // Report on the debug stream that the rule yyrule is going to be reduced.
1221   private final void yy_reduce_print (int yyrule, ref YYStack yystack)
1222   {
1223     if (yydebug == 0)
1224       return;
1225 
1226     int yylno = yyrline_[yyrule];
1227     int yynrhs = yyr2_[yyrule];
1228     /* Print the symbols being reduced, and their result.  */
1229     yycdebugln (format("Reducing stack by rule %d (line %d):",
1230                 yyrule - 1, yylno));
1231 
1232     /* The symbols being reduced.  */
1233     for (int yyi = 0; yyi < yynrhs; yyi++)
1234       yy_symbol_print (format("   $%d =", yyi + 1),
1235                        to!SymbolKind (yystos_[yystack.stateAt(yynrhs - (yyi + 1))]),
1236                        ]b4_rhs_value(yynrhs, yyi + 1)b4_locations_if([,
1237                        b4_rhs_location(yynrhs, yyi + 1)])[);
1238   }
1239 ]])[
1240 
1241   private static auto yytranslate_ (int t)
1242   {
1243 ]b4_api_token_raw_if(
1244 [[    return SymbolKind(t);]],
1245 [[    /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
1246     immutable ]b4_int_type_for([b4_translate])[[] translate_table =
1247     @{
1248   ]b4_translate[
1249     @};
1250 
1251     // Last valid token kind.
1252     immutable int code_max = ]b4_code_max[;
1253 
1254     if (t <= 0)
1255       return ]b4_symbol(eof, kind)[;
1256     else if (t <= code_max)
1257       return SymbolKind(translate_table[t]);
1258     else
1259       return ]b4_symbol(undef, kind)[;]])[
1260   }
1261 
1262   private static immutable int yylast_ = ]b4_last[;
1263   private static immutable int yynnts_ = ]b4_nterms_number[;
1264   private static immutable int yyfinal_ = ]b4_final_state_number[;
1265   private static immutable int yyntokens_ = ]b4_tokens_number[;
1266 
1267   private final struct YYStackElement {
1268     int state;
1269     Value value;]b4_locations_if(
1270     b4_location_type[[] location;])[
1271   }
1272 
1273   private final struct YYStack {
1274     private YYStackElement[] stack = [];
1275 
1276     public final ulong height()
1277     {
1278       return stack.length;
1279     }
1280 
1281     public final void push (int state, Value value]dnl
1282   b4_locations_if([, ref Location loc])[)
1283     {
1284       stack ~= YYStackElement(state, value]b4_locations_if([, loc])[);
1285     }
1286 
1287     public final void pop ()
1288     {
1289       pop (1);
1290     }
1291 
1292     public final void pop (int num)
1293     {
1294       stack.length -= num;
1295     }
1296 
1297     public final int stateAt (int i) const
1298     {
1299       return stack[$-i-1].state;
1300     }
1301 
1302 ]b4_locations_if([[
1303     public final ref Location locationAt (int i)
1304     {
1305       return stack[$-i-1].location;
1306     }]])[
1307 
1308     public final ref Value valueAt (int i)
1309     {
1310       return stack[$-i-1].value;
1311     }
1312 ]b4_parse_trace_if([[
1313     // Print the state stack on the debug stream.
1314     public final void print (File stream)
1315     {
1316       stream.write ("Stack now");
1317       for (int i = 0; i < stack.length; i++)
1318         stream.write (" ", stack[i].state);
1319       stream.writeln ();
1320     }]])[
1321   }
1322 ]b4_percent_code_get[
1323 }
1324 ]b4_percent_code_get([[epilogue]])[]dnl
1325 b4_epilogue[]dnl
1326 b4_output_end
1327