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 
21 b4_output_begin([b4_parser_file_name])
22 b4_copyright([Skeleton implementation for Bison LALR(1) parsers in D],
23              [2007-2012, 2019-2021])[
24 ]b4_disclaimer[
25 ]b4_percent_define_ifdef([package], [module b4_percent_define_get([package]);
26 ])[
27 version(D_Version2) {
28 } else {
29   static assert(false, "need compiler for D Version 2");
30 }
31 
32 ]b4_user_pre_prologue[
33 ]b4_user_post_prologue[
34 ]b4_percent_code_get([[imports]])[
35 import std.format;
36 
37 /**
38  * A Bison parser, automatically generated from <tt>]m4_bpatsubst(b4_file_name, [^"\(.*\)"$], [\1])[</tt>.
39  *
40  * @@author LALR (1) parser skeleton written by Paolo Bonzini.
41  * Port to D language was done by Oliver Mangold.
42  */
43 
44 /**
45  * Communication interface between the scanner and the Bison-generated
46  * parser <tt>]b4_parser_class[</tt>.
47  */
48 public interface Lexer
49 {]b4_locations_if([[
50   /**
51    * Method to retrieve the beginning position of the last scanned token.
52    * @@return the position at which the last scanned token starts.  */
53   @@property ]b4_position_type[ startPos ();
54 
55   /**
56    * Method to retrieve the ending position of the last scanned token.
57    * @@return the first position beyond the last scanned token.  */
58   @@property ]b4_position_type[ endPos ();
59 
60 ]])[
61   /**
62    * Method to retrieve the semantic value of the last scanned token.
63    * @@return the semantic value of the last scanned token.  */
64   @@property ]b4_yystype[ semanticVal ();
65 
66   /**
67    * Entry point for the scanner.  Returns the token identifier corresponding
68    * to the next token and prepares to return the semantic value
69    * ]b4_locations_if([and beginning/ending positions ])[of the token.
70    * @@return the token identifier corresponding to the next token. */
71   int yylex ();
72 
73   /**
74    * Entry point for error reporting.  Emits an error
75    * ]b4_locations_if([referring to the given location ])[in a user-defined way.
76    *]b4_locations_if([[
77    * @@param loc The location of the element to which the
78    *                error message is related]])[
79    * @@param s The string for the error message.  */
80    void yyerror (]b4_locations_if([b4_location_type[ loc, ]])[string s);
81 }
82 
83 ]b4_locations_if([b4_position_type_if([[
84 static assert(__traits(compiles,
85               (new ]b4_position_type[[1])[0]=(new ]b4_position_type[[1])[0]),
86               "struct/class ]b4_position_type[ must be default-constructible "
87               "and assignable");
88 static assert(__traits(compiles, (new string[1])[0]=(new ]b4_position_type[).toString()),
89               "error: struct/class ]b4_position_type[ must have toString method");
90 ]], [[
91   /**
92    * A struct denoting a point in the input.*/
93 public struct ]b4_position_type[ {
94 
95   /** The column index within the line of input.  */
96   public int column = 1;
97   /** The line number within an input file.  */
98   public int line = 1;
99   /** The name of the input file.  */
100   public string filename = null;
101 
102   /**
103    * A string representation of the position. */
104   public string toString() const {
105     if (filename)
106       return format("%s:%d.%d", filename, line, column);
107     else
108       return format("%d.%d", line, column);
109   }
110 }
111 ]])b4_location_type_if([[
112 static assert(__traits(compiles, (new ]b4_location_type[((new ]b4_position_type[[1])[0]))) &&
113               __traits(compiles, (new ]b4_location_type[((new ]b4_position_type[[1])[0], (new ]b4_position_type[[1])[0]))),
114               "error: struct/class ]b4_location_type[ must have "
115               "default constructor and constructors this(]b4_position_type[) and this(]b4_position_type[, ]b4_position_type[).");
116 static assert(__traits(compiles, (new ]b4_location_type[[1])[0].begin=(new ]b4_location_type[[1])[0].begin) &&
117               __traits(compiles, (new ]b4_location_type[[1])[0].begin=(new ]b4_location_type[[1])[0].end) &&
118               __traits(compiles, (new ]b4_location_type[[1])[0].end=(new ]b4_location_type[[1])[0].begin) &&
119               __traits(compiles, (new ]b4_location_type[[1])[0].end=(new ]b4_location_type[[1])[0].end),
120               "error: struct/class ]b4_location_type[ must have assignment-compatible "
121               "members/properties 'begin' and 'end'.");
122 static assert(__traits(compiles, (new string[1])[0]=(new ]b4_location_type[[1])[0].toString()),
123               "error: struct/class ]b4_location_type[ must have toString method.");
124 
125 private immutable bool yy_location_is_class = !__traits(compiles, *(new ]b4_location_type[((new ]b4_position_type[[1])[0])));]], [[
126 /**
127  * A class defining a pair of positions.  Positions, defined by the
128  * <code>]b4_position_type[</code> class, denote a point in the input.
129  * Locations represent a part of the input through the beginning
130  * and ending positions.  */
131 public class ]b4_location_type[
132 {
133   /** The first, inclusive, position in the range.  */
134   public ]b4_position_type[ begin;
135 
136   /** The first position beyond the range.  */
137   public ]b4_position_type[ end;
138 
139   /**
140    * Create a <code>]b4_location_type[</code> denoting an empty range located at
141    * a given point.
142    * @@param loc The position at which the range is anchored.  */
143   public this (]b4_position_type[ loc) {
144     this.begin = this.end = loc;
145   }
146 
147   public this () {
148   }
149 
150   /**
151    * Create a <code>]b4_location_type[</code> from the endpoints of the range.
152    * @@param begin The first position included in the range.
153    * @@param end   The first position beyond the range.  */
154   public this (]b4_position_type[ begin, ]b4_position_type[ end)
155   {
156     this.begin = begin;
157     this.end = end;
158   }
159 
160   /**
161    * A representation of the location. For this to be correct,
162    * <code>]b4_position_type[</code> should override the <code>toString</code>
163    * method.  */
164   public override string toString () const {
165     auto end_col = 0 < end.column ? end.column - 1 : 0;
166     auto res = begin.toString ();
167     if (end.filename && begin.filename != end.filename)
168       res ~= "-" ~ format("%s:%d.%d", end.filename, end.line, end_col);
169     else if (begin.line < end.line)
170       res ~= "-" ~ format("%d.%d", end.line, end_col);
171     else if (begin.column < end_col)
172       res ~= "-" ~ format("%d", end_col);
173     return res;
174   }
175 }
176 
177 private immutable bool yy_location_is_class = true;
178 
179 ]])])m4_ifdef([b4_user_union_members], [private union YYSemanticType
180 {
181 b4_user_union_members
182 };],
183 [m4_if(b4_tag_seen_flag, 0,
184 [[private alias int YYSemanticType;]])])[
185 ]b4_token_enums[
186 ]b4_parser_class_declaration[
187 {
188   ]b4_identification[
189 
190 ]b4_declare_symbol_enum[
191 
192 ]b4_locations_if([[
193   private final ]b4_location_type[ yylloc_from_stack (ref YYStack rhs, int n)
194   {
195     static if (yy_location_is_class) {
196       if (n > 0)
197         return new ]b4_location_type[ (rhs.locationAt (n-1).begin, rhs.locationAt (0).end);
198       else
199         return new ]b4_location_type[ (rhs.locationAt (0).end);
200     } else {
201       if (n > 0)
202         return ]b4_location_type[ (rhs.locationAt (n-1).begin, rhs.locationAt (0).end);
203       else
204         return ]b4_location_type[ (rhs.locationAt (0).end);
205     }
206   }]])[
207 
208 ]b4_lexer_if([[  private class YYLexer implements Lexer {
209 ]b4_percent_code_get([[lexer]])[
210   }
211 ]])[
212   /** The object doing lexical analysis for us.  */
213   private Lexer yylexer;
214 
215 ]b4_parse_param_vars[
216 
217 ]b4_lexer_if([[
218   /**
219    * Instantiate the Bison-generated parser.
220    */
221   public this] (b4_parse_param_decl([b4_lex_param_decl])[) {
222     this (new YYLexer(]b4_lex_param_call[));
223   }
224 ]])[
225 
226   /**
227    * Instantiate the Bison-generated parser.
228    * @@param yylexer The scanner that will supply tokens to the parser.
229    */
230   ]b4_lexer_if([[protected]], [[public]]) [this (]b4_parse_param_decl([[Lexer yylexer]])[) {
231     this.yylexer = yylexer;]b4_parse_trace_if([[
232     this.yyDebugStream = stderr;]])[
233 ]b4_parse_param_cons[
234   }
235 ]b4_parse_trace_if([[
236   private File yyDebugStream;
237 
238   /**
239    * The <tt>File</tt> on which the debugging output is
240    * printed.
241    */
242   public File getDebugStream () { return yyDebugStream; }
243 
244   /**
245    * Set the <tt>std.File</tt> on which the debug output is printed.
246    * @@param s The stream that is used for debugging output.
247    */
248   public final void setDebugStream(File s) { yyDebugStream = s; }
249 
250   private int yydebug = 0;
251 
252   /**
253    * Answer the verbosity of the debugging output; 0 means that all kinds of
254    * output from the parser are suppressed.
255    */
256   public final int getDebugLevel() { return yydebug; }
257 
258   /**
259    * Set the verbosity of the debugging output; 0 means that all kinds of
260    * output from the parser are suppressed.
261    * @@param level The verbosity level for debugging output.
262    */
263   public final void setDebugLevel(int level) { yydebug = level; }
264 
265   protected final void yycdebug (string s) {
266     if (0 < yydebug)
267       yyDebugStream.write (s);
268   }
269 
270   protected final void yycdebugln (string s) {
271     if (0 < yydebug)
272       yyDebugStream.writeln (s);
273   }
274 ]])[
275   private final int yylex () {
276     return yylexer.yylex ();
277   }
278 
279   protected final void yyerror (]b4_locations_if(ref [b4_location_type[ loc, ]])[string s) {
280     yylexer.yyerror (]b4_locations_if([loc, ])[s);
281   }
282 
283   /**
284    * Returned by a Bison action in order to stop the parsing process and
285    * return success (<tt>true</tt>).  */
286   public static immutable int YYACCEPT = 0;
287 
288   /**
289    * Returned by a Bison action in order to stop the parsing process and
290    * return failure (<tt>false</tt>).  */
291   public static immutable int YYABORT = 1;
292 
293   /**
294    * Returned by a Bison action in order to start error recovery without
295    * printing an error message.  */
296   public static immutable int YYERROR = 2;
297 
298   // Internal return codes that are not supported for user semantic
299   // actions.
300   private static immutable int YYERRLAB = 3;
301   private static immutable int YYNEWSTATE = 4;
302   private static immutable int YYDEFAULT = 5;
303   private static immutable int YYREDUCE = 6;
304   private static immutable int YYERRLAB1 = 7;
305   private static immutable int YYRETURN = 8;
306 ]b4_locations_if([
307   private static immutable YYSemanticType yy_semantic_null;])[
308   private int yyerrstatus_ = 0;
309 
310   /**
311    * Whether error recovery is being done.  In this state, the parser
312    * reads token until it reaches a known state, and then restarts normal
313    * operation.  */
314   public final bool recovering ()
315   {
316     return yyerrstatus_ == 0;
317   }
318 
319   private int yyaction (int yyn, ref YYStack yystack, int yylen)
320   {
321     ]b4_yystype[ yyval;]b4_locations_if([[
322     ]b4_location_type[ yyloc = yylloc_from_stack (yystack, yylen);]])[
323 
324     /* If YYLEN is nonzero, implement the default value of the action:
325        `$$ = $1'.  Otherwise, use the top of the stack.
326 
327        Otherwise, the following line sets YYVAL to garbage.
328        This behavior is undocumented and Bison
329        users should not rely upon it.  */
330     if (yylen > 0)
331       yyval = yystack.valueAt (yylen - 1);
332     else
333       yyval = yystack.valueAt (0);
334 
335 ]b4_parse_trace_if([[
336     yy_reduce_print (yyn, yystack);]])[
337 
338     switch (yyn)
339     {
340 ]b4_user_actions[
341       default: break;
342     }
343 
344 ]b4_parse_trace_if([[
345     import std.conv : to;
346     yy_symbol_print ("-> $$ =", to!SymbolKind (yyr1_[yyn]), yyval]b4_locations_if([, yyloc])[);]])[
347 
348     yystack.pop (yylen);
349     yylen = 0;
350 
351     /* Shift the result of the reduction.  */
352     yyn = yyr1_[yyn];
353     int yystate = yypgoto_[yyn - yyntokens_] + yystack.stateAt (0);
354     if (0 <= yystate && yystate <= yylast_
355         && yycheck_[yystate] == yystack.stateAt (0))
356       yystate = yytable_[yystate];
357     else
358       yystate = yydefgoto_[yyn - yyntokens_];
359 
360     yystack.push (yystate, yyval]b4_locations_if([, yyloc])[);
361     return YYNEWSTATE;
362   }
363 
364   /* Return YYSTR after stripping away unnecessary quotes and
365      backslashes, so that it's suitable for yyerror.  The heuristic is
366      that double-quoting is unnecessary unless the string contains an
367      apostrophe, a comma, or backslash (other than backslash-backslash).
368      YYSTR is taken from yytname.  */
369   private final string yytnamerr_ (string yystr)
370   {
371     if (yystr[0] == '"')
372       {
373         string yyr;
374       strip_quotes:
375         for (int i = 1; i < yystr.length; i++)
376           switch (yystr[i])
377             {
378             case '\'':
379             case ',':
380               break strip_quotes;
381 
382             case '\\':
383               if (yystr[++i] != '\\')
384                 break strip_quotes;
385               goto default;
386             default:
387               yyr ~= yystr[i];
388               break;
389 
390             case '"':
391               return yyr;
392             }
393       }
394     else if (yystr == "$end")
395       return "end of input";
396 
397     return yystr;
398   }
399 ]b4_parse_trace_if([[
400   /*--------------------------------.
401   | Print this symbol on YYOUTPUT.  |
402   `--------------------------------*/
403 
404   private final void yy_symbol_print (string s, SymbolKind yykind,
405     ref ]b4_yystype[ yyvaluep]dnl
406 b4_locations_if([, ref ]b4_location_type[ yylocationp])[)
407   {
408     if (0 < yydebug)
409     {
410       string message = s ~ (yykind < yyntokens_ ? " token " : " nterm ")
411               ~ yytname_[yykind] ~ " ("]b4_locations_if([
412               ~ yylocationp.toString() ~ ": "])[;
413       static if (__traits(compiles, message ~= yyvaluep.toString ()))
414               message ~= yyvaluep.toString ();
415       else
416               message ~= format ("%s", &yyvaluep);
417       message ~= ")";
418       yycdebugln (message);
419     }
420   }
421 ]])[
422   /**
423    * Parse input from the scanner that was specified at object construction
424    * time.  Return whether the end of the input was reached successfully.
425    *
426    * @@return <tt>true</tt> if the parsing succeeds.  Note that this does not
427    *          imply that there were no syntax errors.
428    */
429   public bool parse ()
430   {
431     // Lookahead token kind.
432     int yychar = TokenKind.YYEMPTY;
433     // Lookahead symbol kind.
434     SymbolKind yytoken = ]b4_symbol(-2, kind)[;
435 
436     /* State.  */
437     int yyn = 0;
438     int yylen = 0;
439     int yystate = 0;
440 
441     YYStack yystack;
442 
443     /* Error handling.  */
444     int yynerrs_ = 0;]b4_locations_if([[
445     /// The location where the error started.
446     ]b4_location_type[ yyerrloc = null;
447 
448     /// ]b4_location_type[ of the lookahead.
449     ]b4_location_type[ yylloc;
450 
451     /// @@$.
452     ]b4_location_type[ yyloc;]])[
453 
454     /// Semantic value of the lookahead.
455     ]b4_yystype[ yylval;
456 
457     bool yyresult;]b4_parse_trace_if([[
458 
459     yycdebugln ("Starting parse");]])[
460     yyerrstatus_ = 0;
461 
462 ]m4_ifdef([b4_initial_action], [
463 m4_pushdef([b4_at_dollar],     [yylloc])dnl
464 m4_pushdef([b4_dollar_dollar], [yylval])dnl
465     /* User initialization code.  */
466     b4_user_initial_action
467 m4_popdef([b4_dollar_dollar])dnl
468 m4_popdef([b4_at_dollar])])dnl
469 
470   [  /* Initialize the stack.  */
471     yystack.push (yystate, yylval]b4_locations_if([, yylloc])[);
472 
473     int label = YYNEWSTATE;
474     for (;;)
475       final switch (label)
476       {
477         /* New state.  Unlike in the C/C++ skeletons, the state is already
478            pushed when we come here.  */
479       case YYNEWSTATE:]b4_parse_trace_if([[
480         yycdebugln (format("Entering state %d", yystate));
481         if (0 < yydebug)
482           yystack.print (yyDebugStream);]])[
483 
484         /* Accept?  */
485         if (yystate == yyfinal_)
486           return true;
487 
488         /* Take a decision.  First try without lookahead.  */
489         yyn = yypact_[yystate];
490         if (yy_pact_value_is_default_ (yyn))
491         {
492           label = YYDEFAULT;
493           break;
494         }
495 
496         /* Read a lookahead token.  */
497         if (yychar == TokenKind.YYEMPTY)
498         {]b4_parse_trace_if([[
499           yycdebugln ("Reading a token");]])[
500           yychar = yylex ();]b4_locations_if([[
501           static if (yy_location_is_class) {
502             yylloc = new ]b4_location_type[(yylexer.startPos, yylexer.endPos);
503           } else {
504             yylloc = ]b4_location_type[(yylexer.startPos, yylexer.endPos);
505           }]])
506           yylval = yylexer.semanticVal;[
507         }
508 
509         /* Convert token to internal form.  */
510         yytoken = yytranslate_ (yychar);]b4_parse_trace_if([[
511         yy_symbol_print ("Next token is", yytoken, yylval]b4_locations_if([, yylloc])[);]])[
512 
513         if (yytoken == ]b4_symbol(1, kind)[)
514         {
515           // The scanner already issued an error message, process directly
516           // to error recovery.  But do not keep the error token as
517           // lookahead, it is too special and may lead us to an endless
518           // loop in error recovery. */
519           yychar = TokenKind.]b4_symbol(2, id)[;
520           yytoken = ]b4_symbol(2, kind)[;]b4_locations_if([[
521           yyerrloc = yylloc;]])[
522           label = YYERRLAB1;
523         }
524         else
525         {
526           /* If the proper action on seeing token YYTOKEN is to reduce or to
527              detect an error, take that action.  */
528           yyn += yytoken;
529           if (yyn < 0 || yylast_ < yyn || yycheck_[yyn] != yytoken)
530             label = YYDEFAULT;
531 
532           /* <= 0 means reduce or error.  */
533           else if ((yyn = yytable_[yyn]) <= 0)
534           {
535             if (yy_table_value_is_error_ (yyn))
536               label = YYERRLAB;
537             else
538             {
539               yyn = -yyn;
540               label = YYREDUCE;
541             }
542           }
543           else
544           {
545             /* Shift the lookahead token.  */]b4_parse_trace_if([[
546             yy_symbol_print ("Shifting", yytoken, yylval]b4_locations_if([, yylloc])[);]])[
547 
548             /* Discard the token being shifted.  */
549             yychar = TokenKind.YYEMPTY;
550 
551             /* Count tokens shifted since error; after three, turn off error
552              * status.  */
553             if (yyerrstatus_ > 0)
554               --yyerrstatus_;
555 
556             yystate = yyn;
557             yystack.push (yystate, yylval]b4_locations_if([, yylloc])[);
558             label = YYNEWSTATE;
559           }
560         }
561         break;
562 
563       /*-----------------------------------------------------------.
564       | yydefault -- do the default action for the current state.  |
565       `-----------------------------------------------------------*/
566       case YYDEFAULT:
567         yyn = yydefact_[yystate];
568         if (yyn == 0)
569           label = YYERRLAB;
570         else
571           label = YYREDUCE;
572         break;
573 
574       /*-----------------------------.
575       | yyreduce -- Do a reduction.  |
576       `-----------------------------*/
577       case YYREDUCE:
578         yylen = yyr2_[yyn];
579         label = yyaction (yyn, yystack, yylen);
580         yystate = yystack.stateAt (0);
581         break;
582 
583       /*--------------------------------------.
584       | yyerrlab -- here on detecting error.  |
585       `--------------------------------------*/
586       case YYERRLAB:
587         /* If not already recovering from an error, report this error.  */
588         if (yyerrstatus_ == 0)
589         {
590           ++yynerrs_;
591           if (yychar == TokenKind.]b4_symbol(-2, id)[)
592             yytoken = ]b4_symbol(-2, kind)[;
593           yyerror (]b4_locations_if([yylloc, ])[yysyntax_error (yystate, yytoken));
594         }
595 ]b4_locations_if([
596         yyerrloc = yylloc;])[
597         if (yyerrstatus_ == 3)
598         {
599           /* If just tried and failed to reuse lookahead token after an
600            * error, discard it.  */
601 
602           if (yychar <= TokenKind.]b4_symbol(0, [id])[)
603           {
604             /* Return failure if at end of input.  */
605             if (yychar == TokenKind.]b4_symbol(0, [id])[)
606              return false;
607           }
608           else
609             yychar = TokenKind.YYEMPTY;
610         }
611 
612         /* Else will try to reuse lookahead token after shifting the error
613          * token.  */
614         label = YYERRLAB1;
615         break;
616 
617       /*-------------------------------------------------.
618       | errorlab -- error raised explicitly by YYERROR.  |
619       `-------------------------------------------------*/
620       case YYERROR:]b4_locations_if([
621         yyerrloc = yystack.locationAt (yylen - 1);])[
622         /* Do not reclaim the symbols of the rule which action triggered
623            this YYERROR.  */
624         yystack.pop (yylen);
625         yylen = 0;
626         yystate = yystack.stateAt (0);
627         label = YYERRLAB1;
628         break;
629 
630       /*-------------------------------------------------------------.
631       | yyerrlab1 -- common code for both syntax error and YYERROR.  |
632       `-------------------------------------------------------------*/
633       case YYERRLAB1:
634         yyerrstatus_ = 3;       /* Each real token shifted decrements this.  */
635 
636         // Pop stack until we find a state that shifts the error token.
637         for (;;)
638         {
639           yyn = yypact_[yystate];
640           if (!yy_pact_value_is_default_ (yyn))
641           {
642             yyn += ]b4_symbol(1, kind)[;
643             if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == ]b4_symbol(1, kind)[)
644             {
645               yyn = yytable_[yyn];
646               if (0 < yyn)
647                 break;
648                   }
649           }
650 
651           /* Pop the current state because it cannot handle the error token.  */
652           if (yystack.height == 1)
653             return false;
654 
655 ]b4_locations_if([          yyerrloc = yystack.locationAt (0);])[
656           yystack.pop ();
657           yystate = yystack.stateAt (0);]b4_parse_trace_if([[
658           if (0 < yydebug)
659             yystack.print (yyDebugStream);]])[
660         }
661 
662 ]b4_locations_if([
663         /* Muck with the stack to setup for yylloc.  */
664         yystack.push (0, yy_semantic_null, yylloc);
665         yystack.push (0, yy_semantic_null, yyerrloc);
666         yyloc = yylloc_from_stack (yystack, 2);
667         yystack.pop (2);])[
668 
669         /* Shift the error token.  */]b4_parse_trace_if([[
670         import std.conv : to;
671         yy_symbol_print ("Shifting", to!SymbolKind (yystos_[yyn]), yylval]b4_locations_if([, yyloc])[);]])[
672         yystate = yyn;
673         yystack.push (yyn, yylval]b4_locations_if([, yyloc])[);
674         label = YYNEWSTATE;
675         break;
676 
677       /* Accept.  */
678       case YYACCEPT:
679         yyresult = true;
680         label = YYRETURN;
681         break;
682 
683       /* Abort.  */
684       case YYABORT:
685         yyresult = false;
686         label = YYRETURN;
687         break;
688 
689       case YYRETURN:]b4_parse_trace_if([[
690         if (0 < yydebug)
691           yystack.print (yyDebugStream);]])[
692         return yyresult;
693     }
694   }
695 
696   // Generate an error message.
697   private final string yysyntax_error (int yystate, SymbolKind tok)
698   {]b4_parse_error_case([verbose], [[
699     /* There are many possibilities here to consider:
700        - Assume YYFAIL is not used.  It's too flawed to consider.
701          See
702          <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
703          for details.  YYERROR is fine as it does not invoke this
704          function.
705        - If this state is a consistent state with a default action,
706          then the only way this function was invoked is if the
707          default action is an error action.  In that case, don't
708          check for expected tokens because there are none.
709        - The only way there can be no lookahead present (in tok) is
710          if this state is a consistent state with a default action.
711          Thus, detecting the absence of a lookahead is sufficient to
712          determine that there is no unexpected or expected token to
713          report.  In that case, just report a simple "syntax error".
714        - Don't assume there isn't a lookahead just because this
715          state is a consistent state with a default action.  There
716          might have been a previous inconsistent state, consistent
717          state with a non-default action, or user semantic action
718          that manipulated yychar.  (However, yychar is currently out
719          of scope during semantic actions.)
720        - Of course, the expected token list depends on states to
721          have correct lookahead information, and it depends on the
722          parser not to perform extra reductions after fetching a
723          lookahead from the scanner and before detecting a syntax
724          error.  Thus, state merging (from LALR or IELR) and default
725          reductions corrupt the expected token list.  However, the
726          list is correct for canonical LR with one exception: it
727          will still contain any token that will not be accepted due
728          to an error action in a later state.
729       */
730     if (tok != ]b4_symbol(-2, kind)[)
731     {
732       // FIXME: This method of building the message is not compatible
733       // with internationalization.
734       string res = "syntax error, unexpected ";
735       res ~= yytnamerr_ (yytname_[tok]);
736       int yyn = yypact_[yystate];
737       if (!yy_pact_value_is_default_ (yyn))
738       {
739         /* Start YYX at -YYN if negative to avoid negative
740            indexes in YYCHECK.  In other words, skip the first
741            -YYN actions for this state because they are default
742            actions.  */
743         int yyxbegin = yyn < 0 ? -yyn : 0;
744         /* Stay within bounds of both yycheck and yytname.  */
745         int yychecklim = yylast_ - yyn + 1;
746         int yyxend = yychecklim < yyntokens_ ? yychecklim : yyntokens_;
747         int count = 0;
748         for (int x = yyxbegin; x < yyxend; ++x)
749           if (yycheck_[x + yyn] == x && x != ]b4_symbol(1, kind)[
750               && !yy_table_value_is_error_ (yytable_[x + yyn]))
751              ++count;
752           if (count < 5)
753           {
754              count = 0;
755              for (int x = yyxbegin; x < yyxend; ++x)
756                if (yycheck_[x + yyn] == x && x != ]b4_symbol(1, kind)[
757                    && !yy_table_value_is_error_ (yytable_[x + yyn]))
758                {
759                   res ~= count++ == 0 ? ", expecting " : " or ";
760                   res ~= yytnamerr_ (yytname_[x]);
761                }
762           }
763       }
764       return res;
765     }]])[
766     return "syntax error";
767   }
768 
769   /**
770    * Whether the given <code>yypact_</code> value indicates a defaulted state.
771    * @@param yyvalue   the value to check
772    */
773   private static bool yy_pact_value_is_default_ (int yyvalue)
774   {
775     return yyvalue == yypact_ninf_;
776   }
777 
778   /**
779    * Whether the given <code>yytable_</code> value indicates a syntax error.
780    * @@param yyvalue   the value to check
781    */
782   private static bool yy_table_value_is_error_ (int yyvalue)
783   {
784     return yyvalue == yytable_ninf_;
785   }
786 
787   /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
788      STATE-NUM.  */
789   private static immutable ]b4_int_type_for([b4_pact])[ yypact_ninf_ = ]b4_pact_ninf[;
790 
791   /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
792      positive, shift that token.  If negative, reduce the rule which
793      number is the opposite.  If YYTABLE_NINF_, syntax error.  */
794   private static immutable ]b4_int_type_for([b4_table])[ yytable_ninf_ = ]b4_table_ninf[;
795 
796   ]b4_parser_tables_define[
797 
798   /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
799      First, the terminals, then, starting at \a yyntokens_, nonterminals.  */
800   private static immutable string[] yytname_ =
801   @{
802   ]b4_tname[
803   @};
804 
805 ]b4_parse_trace_if([[
806   /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
807   private static immutable ]b4_int_type_for([b4_rline])[[] yyrline_ =
808   @{
809   ]b4_rline[
810   @};
811 
812   // Report on the debug stream that the rule yyrule is going to be reduced.
813   private final void yy_reduce_print (int yyrule, ref YYStack yystack)
814   {
815     if (yydebug == 0)
816       return;
817 
818     int yylno = yyrline_[yyrule];
819     int yynrhs = yyr2_[yyrule];
820     /* Print the symbols being reduced, and their result.  */
821     yycdebugln (format("Reducing stack by rule %d (line %d):",
822                 yyrule - 1, yylno));
823 
824     /* The symbols being reduced.  */
825     import std.conv : to;
826     for (int yyi = 0; yyi < yynrhs; yyi++)
827       yy_symbol_print (format("   $%d =", yyi + 1),
828                        to!SymbolKind (yystos_[yystack.stateAt(yynrhs - (yyi + 1))]),
829                        ]b4_rhs_value(yynrhs, yyi + 1)b4_locations_if([,
830                        b4_rhs_location(yynrhs, yyi + 1)])[);
831   }
832 ]])[
833 
834   private static SymbolKind yytranslate_ (int t)
835   {
836 ]b4_api_token_raw_if(
837 [[    import std.conv : to;
838     return to!SymbolKind (t);]],
839 [[    /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
840     immutable ]b4_int_type_for([b4_translate])[[] translate_table =
841     @{
842   ]b4_translate[
843     @};
844 
845     // Last valid token kind.
846     immutable int code_max = ]b4_code_max[;
847 
848     if (t <= 0)
849       return ]b4_symbol(0, kind)[;
850     else if (t <= code_max)
851       {
852         import std.conv : to;
853         return to!SymbolKind (translate_table[t]);
854       }
855     else
856       return ]b4_symbol(2, kind)[;]])[
857   }
858 
859   private static immutable int yylast_ = ]b4_last[;
860   private static immutable int yynnts_ = ]b4_nterms_number[;
861   private static immutable int yyfinal_ = ]b4_final_state_number[;
862   private static immutable int yyntokens_ = ]b4_tokens_number[;
863 
864   private final struct YYStackElement {
865     int state;
866     ]b4_yystype[ value;]b4_locations_if(
867     b4_location_type[[] location;])[
868   }
869 
870   private final struct YYStack {
871     private YYStackElement[] stack = [];
872 
873     public final @@property ulong height()
874     {
875       return stack.length;
876     }
877 
878     public final void push (int state, ]b4_yystype[ value]dnl
879   b4_locations_if([, ref ]b4_location_type[ loc])[)
880     {
881       stack ~= YYStackElement(state, value]b4_locations_if([, loc])[);
882     }
883 
884     public final void pop ()
885     {
886       pop (1);
887     }
888 
889     public final void pop (int num)
890     {
891       stack.length -= num;
892     }
893 
894     public final int stateAt (int i)
895     {
896       return stack[$-i-1].state;
897     }
898 
899 ]b4_locations_if([[
900     public final ref ]b4_location_type[ locationAt (int i)
901     {
902       return stack[$-i-1].location;
903     }]])[
904 
905     public final ref ]b4_yystype[ valueAt (int i)
906     {
907       return stack[$-i-1].value;
908     }
909 ]b4_parse_trace_if([[
910     // Print the state stack on the debug stream.
911     public final void print (File stream)
912     {
913       stream.write ("Stack now");
914       for (int i = 0; i < stack.length; i++)
915         stream.write (" ", stack[i].state);
916       stream.writeln ();
917     }]])[
918   }
919 ]b4_percent_code_get[
920 }
921 ]b4_percent_code_get([[epilogue]])[]dnl
922 b4_epilogue[]dnl
923 b4_output_end
924