maint: remove unnecessary casts before using gnulib functions
[bison.git] / data / skeletons / lalr1.d
blob01175325095e0dcc68e262f6aaf9a5d0bf9ac5cd
1 # D skeleton for Bison -*- autoconf -*-
3 # Copyright (C) 2007-2012, 2019-2022 Free Software Foundation, Inc.
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.
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.
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/>.
18 m4_include(b4_skeletonsdir/[d.m4])
20 b4_header_if([b4_complain([%header/%defines does not make sense in D])])
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]])])
31 ## --------------- ##
32 ## api.push-pull. ##
33 ## --------------- ##
35 b4_percent_define_default([[api.push-pull]], [[pull]])
36 b4_percent_define_check_values([[[[api.push-pull]],
37 [[pull]], [[push]], [[both]]]])
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]])])
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])])
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]])])])
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-2022])[
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");
73 ]b4_user_pre_prologue[
74 ]b4_user_post_prologue[
75 ]b4_percent_code_get([[imports]])[
76 import std.format;
77 import std.conv;
79 /**
80 * Handle error message internationalisation.
82 static if (!is(typeof(YY_))) {
83 version(YYENABLE_NLS)
85 version(ENABLE_NLS)
87 extern(C) char* dgettext(const char*, const char*);
88 string YY_(const char* s)
90 return to!string(dgettext("bison-runtime", s));
94 static if (!is(typeof(YY_)))
96 pragma(inline, true)
97 string YY_(string msg) { return msg; }
102 * A Bison parser, automatically generated from <tt>]m4_bpatsubst(b4_file_name, [^"\(.*\)"$], [\1])[</tt>.
104 * @@author LALR (1) parser skeleton written by Paolo Bonzini.
105 * Port to D language was done by Oliver Mangold.
109 * Communication interface between the scanner and the Bison-generated
110 * parser <tt>]b4_parser_class[</tt>.
112 public interface Lexer
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 ();
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], [[
131 * Build and emit a "syntax error" message in a user-defined way.
133 * @@param ctx The context of the error.
135 void reportSyntaxError(]b4_parser_class[.Context ctx);
136 ]])[
139 ]b4_public_types_declare[
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 ]], [[
150 * A struct denoting a point in the input.*/
151 public struct ]b4_position_type[ {
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;
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);
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.");
183 private immutable bool yy_location_is_class = !__traits(compiles, *(new Location((new Position[1])[0])));]], [[
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[
191 /** The first, inclusive, position in the range. */
192 public Position begin;
194 /** The first position beyond the range. */
195 public Position end;
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)
203 this.begin = this.end = loc;
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)
212 this.begin = begin;
213 this.end = end;
217 * Reset initial location to final location.
219 public void step()
221 this.begin = this.end;
225 * A representation of the location.
227 public string toString() const
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;
241 private immutable bool yy_location_is_class = false;
243 ]])])[]b4_value_type_setup[]m4_ifdef([b4_user_union_members], [private union YYSemanticType
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[
252 ]b4_identification[
254 ]b4_declare_symbol_enum[
256 ]b4_locations_if([[
257 private final Location yylloc_from_stack (ref YYStack rhs, int n)
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);
270 }]])[
272 ]b4_lexer_if([[private class YYLexer: Lexer
274 ]b4_percent_code_get([[lexer]])[
276 ]])[
277 /** The object doing lexical analysis for us. */
278 private Lexer yylexer;
280 ]b4_parse_param_vars[
282 ]b4_lexer_if([[
284 * Instantiate the Bison-generated parser.
286 public this] (b4_parse_param_decl([b4_lex_param_decl])[) {
287 ]b4_percent_code_get([[init]])[]b4_lac_if([[
288 this.yylacStack = new int[];
289 this.yylacEstablished = false;]])[
290 this (new YYLexer(]b4_lex_param_call[));
292 ]])[
295 * Instantiate the Bison-generated parser.
296 * @@param yylexer The scanner that will supply tokens to the parser.
298 ]b4_lexer_if([[protected]], [[public]]) [this (]b4_parse_param_decl([[Lexer yylexer]])[) {
299 this.yylexer = yylexer;]b4_parse_trace_if([[
300 this.yyDebugStream = stderr;]])[
301 ]b4_parse_param_cons[
303 ]b4_parse_trace_if([[
304 import std.stdio;
305 private File yyDebugStream;
308 * The <tt>File</tt> on which the debugging output is
309 * printed.
311 public File getDebugStream () { return yyDebugStream; }
314 * Set the <tt>std.File</tt> on which the debug output is printed.
315 * @@param s The stream that is used for debugging output.
317 public final void setDebugStream(File s) { yyDebugStream = s; }
319 private int yydebug = 0;
322 * Answer the verbosity of the debugging output; 0 means that all kinds of
323 * output from the parser are suppressed.
325 public final int getDebugLevel() { return yydebug; }
328 * Set the verbosity of the debugging output; 0 means that all kinds of
329 * output from the parser are suppressed.
330 * @@param level The verbosity level for debugging output.
332 public final void setDebugLevel(int level) { yydebug = level; }
334 protected final void yycdebug (string s) {
335 if (0 < yydebug)
336 yyDebugStream.write (s);
339 protected final void yycdebugln (string s) {
340 if (0 < yydebug)
341 yyDebugStream.writeln (s);
343 ]])[
344 private final ]b4_parser_class[.Symbol yylex () {
345 return yylexer.yylex ();
348 protected final void yyerror (]b4_locations_if([[const Location loc, ]])[string s) {
349 yylexer.yyerror (]b4_locations_if([loc, ])[s);
353 * The number of syntax errors so far.
355 public int numberOfErrors() const { return yynerrs_; }
356 private int yynerrs_ = 0;
359 * Returned by a Bison action in order to stop the parsing process and
360 * return success (<tt>true</tt>). */
361 public static immutable int YYACCEPT = 0;
364 * Returned by a Bison action in order to stop the parsing process and
365 * return failure (<tt>false</tt>). */
366 public static immutable int YYABORT = 1;
367 ]b4_push_if([
369 * Returned by a Bison action in order to request a new token.
371 public static immutable int YYPUSH_MORE = 4;])[
374 * Returned by a Bison action in order to start error recovery without
375 * printing an error message. */
376 public static immutable int YYERROR = 2;
378 // Internal return codes that are not supported for user semantic
379 // actions.
380 private static immutable int YYERRLAB = 3;
381 private static immutable int YYNEWSTATE = 4;
382 private static immutable int YYDEFAULT = 5;
383 private static immutable int YYREDUCE = 6;
384 private static immutable int YYERRLAB1 = 7;
385 private static immutable int YYRETURN = 8;
386 ]b4_push_if([[ private static immutable int YYGETTOKEN = 9; /* Signify that a new token is expected when doing push-parsing. */]])[
388 ]b4_locations_if([
389 private static immutable YYSemanticType yy_semantic_null;])[
390 private int yyerrstatus_ = 0;
392 private void yyerrok()
394 yyerrstatus_ = 0;
397 // Lookahead symbol kind.
398 SymbolKind yytoken = ]b4_symbol(empty, kind)[;
400 /* State. */
401 int yyn = 0;
402 int yylen = 0;
403 int yystate = 0;
405 YYStack yystack;
407 int label = YYNEWSTATE;
409 /* Error handling. */
410 ]b4_locations_if([[
411 /// The location where the error started.
412 Location yyerrloc;
414 /// Location of the lookahead.
415 Location yylloc;
417 /// @@$.
418 Location yyloc;]])[
420 /// Semantic value of the lookahead.
421 Value yylval;
424 * Whether error recovery is being done. In this state, the parser
425 * reads token until it reaches a known state, and then restarts normal
426 * operation. */
427 public final bool recovering ()
429 return yyerrstatus_ == 0;
432 /** Compute post-reduction state.
433 * @@param yystate the current state
434 * @@param yysym the nonterminal to push on the stack
436 private int yyLRGotoState(int yystate, int yysym) {
437 int yyr = yypgoto_[yysym - yyntokens_] + yystate;
438 if (0 <= yyr && yyr <= yylast_ && yycheck_[yyr] == yystate)
439 return yytable_[yyr];
440 else
441 return yydefgoto_[yysym - yyntokens_];
444 private int yyaction (int yyn, ref YYStack yystack, int yylen)
446 Value yyval;]b4_locations_if([[
447 Location yyloc = yylloc_from_stack (yystack, yylen);]])[
449 /* If YYLEN is nonzero, implement the default value of the action:
450 `$$ = $1'. Otherwise, use the top of the stack.
452 Otherwise, the following line sets YYVAL to garbage.
453 This behavior is undocumented and Bison
454 users should not rely upon it. */
455 if (yylen > 0)
456 yyval = yystack.valueAt (yylen - 1);
457 else
458 yyval = yystack.valueAt (0);
460 ]b4_parse_trace_if([[
461 yy_reduce_print (yyn, yystack);]])[
463 switch (yyn)
465 ]b4_user_actions[
466 default: break;
469 ]b4_parse_trace_if([[
470 yy_symbol_print ("-> $$ =", to!SymbolKind (yyr1_[yyn]), yyval]b4_locations_if([, yyloc])[);]])[
472 yystack.pop (yylen);
473 yylen = 0;
475 /* Shift the result of the reduction. */
476 int yystate = yyLRGotoState(yystack.stateAt(0), yyr1_[yyn]);
477 yystack.push (yystate, yyval]b4_locations_if([, yyloc])[);
478 return YYNEWSTATE;
481 ]b4_parse_trace_if([[
482 /*--------------------------------.
483 | Print this symbol on YYOUTPUT. |
484 `--------------------------------*/
486 private final void yy_symbol_print (string s, SymbolKind yykind,
487 ref Value yyval]b4_locations_if([, ref Location yyloc])[)
489 if (0 < yydebug)
491 File yyo = yyDebugStream;
492 yyo.write(s);
493 yyo.write(yykind < yyntokens_ ? " token " : " nterm ");
494 yyo.write(format("%s", yykind));
495 yyo.write(" ("]b4_locations_if([ ~ yyloc.toString() ~ ": "])[);
496 ]b4_symbol_actions([printer])[
497 yyo.write(")\n");
500 ]])[
501 ]b4_symbol_type_define[
502 ]b4_push_if([[
504 * Push Parse input from external lexer
506 * @@param yyla current Symbol
508 * @@return <tt>YYACCEPT, YYABORT, YYPUSH_MORE</tt>
510 public int pushParse(Symbol yyla)]], [[
512 * Parse input from the scanner that was specified at object construction
513 * time. Return whether the end of the input was reached successfully.
515 * @@return <tt>true</tt> if the parsing succeeds. Note that this does not
516 * imply that there were no syntax errors.
518 public bool parse()]])[
519 {]b4_push_if([[
520 if (!this.pushParseInitialized)
522 pushParseInitialize();
523 yyerrstatus_ = 0;
525 else
526 label = YYGETTOKEN;
528 bool push_token_consumed = true;
529 ]], [[ bool yyresult;]b4_lac_if([[
530 // Discard the LAC context in case there still is one left from a
531 // previous invocation.
532 yylacDiscard("init");]])[]b4_parse_trace_if([[
534 yycdebugln ("Starting parse");]])[
535 yyerrstatus_ = 0;
537 ]m4_ifdef([b4_initial_action], [
538 m4_pushdef([b4_at_dollar], [yylloc])dnl
539 m4_pushdef([b4_dollar_dollar], [yylval])dnl
540 /* User initialization code. */
541 b4_user_initial_action
542 m4_popdef([b4_dollar_dollar])dnl
543 m4_popdef([b4_at_dollar])])dnl
545 [ /* Initialize the stack. */
546 yystack.push (yystate, yylval]b4_locations_if([, yylloc])[);
548 label = YYNEWSTATE;]])[
549 for (;;)
550 final switch (label)
552 /* New state. Unlike in the C/C++ skeletons, the state is already
553 pushed when we come here. */
554 case YYNEWSTATE:]b4_parse_trace_if([[
555 yycdebugln (format("Entering state %d", yystate));
556 if (0 < yydebug)
557 yystack.print (yyDebugStream);]])[
559 /* Accept? */
560 if (yystate == yyfinal_)]b4_push_if([[
562 label = YYACCEPT;
563 break;
564 }]], [[
565 return true;]])[
567 /* Take a decision. First try without lookahead. */
568 yyn = yypact_[yystate];
569 if (yyPactValueIsDefault(yyn))
571 label = YYDEFAULT;
572 break;
573 }]b4_push_if([[
574 goto case;
576 case YYGETTOKEN:]])[
578 /* Read a lookahead token. */
579 if (yytoken == ]b4_symbol(empty, kind)[)
580 {]b4_push_if([[
581 if (!push_token_consumed)
582 return YYPUSH_MORE;]])[]b4_parse_trace_if([[
583 yycdebugln ("Reading a token");]])[]b4_push_if([[
584 yytoken = yyla.token;
585 yylval = yyla.value;]b4_locations_if([[
586 yylloc = yyla.location;]])[
587 push_token_consumed = false;]], [[
588 Symbol yysymbol = yylex();
589 yytoken = yysymbol.token();
590 yylval = yysymbol.value();]b4_locations_if([[
591 yylloc = yysymbol.location();]])[]])[
594 /* Token already converted to internal form. */]b4_parse_trace_if([[
595 yy_symbol_print ("Next token is", yytoken, yylval]b4_locations_if([, yylloc])[);]])[
597 if (yytoken == ]b4_symbol(error, kind)[)
599 // The scanner already issued an error message, process directly
600 // to error recovery. But do not keep the error token as
601 // lookahead, it is too special and may lead us to an endless
602 // loop in error recovery. */
603 yytoken = ]b4_symbol(undef, kind)[;]b4_locations_if([[
604 yyerrloc = yylloc;]])[
605 label = YYERRLAB1;
607 else
609 /* If the proper action on seeing token YYTOKEN is to reduce or to
610 detect an error, take that action. */
611 yyn += yytoken;
612 if (yyn < 0 || yylast_ < yyn || yycheck_[yyn] != yytoken) {]b4_lac_if([[
613 if (!yylacEstablish(yystack, yytoken))
614 label = YYERRLAB;
615 else]])[
616 label = YYDEFAULT;
618 /* <= 0 means reduce or error. */
619 else if ((yyn = yytable_[yyn]) <= 0)
621 if (yyTableValueIsError(yyn))
622 label = YYERRLAB;]b4_lac_if([[
623 else if (!yylacEstablish(yystack, yytoken))
624 label = YYERRLAB;]])[
625 else
627 yyn = -yyn;
628 label = YYREDUCE;
631 else
633 /* Shift the lookahead token. */]b4_parse_trace_if([[
634 yy_symbol_print ("Shifting", yytoken, yylval]b4_locations_if([, yylloc])[);]])[
636 /* Discard the token being shifted. */
637 yytoken = ]b4_symbol(empty, kind)[;
639 /* Count tokens shifted since error; after three, turn off error
640 * status. */
641 if (yyerrstatus_ > 0)
642 --yyerrstatus_;
644 yystate = yyn;
645 yystack.push (yystate, yylval]b4_locations_if([, yylloc])[);]b4_lac_if([[
646 yylacDiscard("shift");]])[
647 label = YYNEWSTATE;
650 break;
652 /*-----------------------------------------------------------.
653 | yydefault -- do the default action for the current state. |
654 `-----------------------------------------------------------*/
655 case YYDEFAULT:
656 yyn = yydefact_[yystate];
657 if (yyn == 0)
658 label = YYERRLAB;
659 else
660 label = YYREDUCE;
661 break;
663 /*-----------------------------.
664 | yyreduce -- Do a reduction. |
665 `-----------------------------*/
666 case YYREDUCE:
667 yylen = yyr2_[yyn];
668 label = yyaction (yyn, yystack, yylen);
669 yystate = yystack.stateAt (0);
670 break;
672 /*--------------------------------------.
673 | yyerrlab -- here on detecting error. |
674 `--------------------------------------*/
675 case YYERRLAB:
676 /* If not already recovering from an error, report this error. */
677 if (yyerrstatus_ == 0)
679 ++yynerrs_;
680 yyreportSyntaxError(new Context(]b4_lac_if([[this, ]])[yystack, yytoken]b4_locations_if([[, yylloc]])[));
682 ]b4_locations_if([
683 yyerrloc = yylloc;])[
684 if (yyerrstatus_ == 3)
686 /* If just tried and failed to reuse lookahead token after an
687 * error, discard it. */
689 /* Return failure if at end of input. */
690 if (yytoken == ]b4_symbol(eof, [kind])[)]b4_push_if([[
692 label = YYABORT;
693 break;
694 }]], [[
695 return false;]])[
696 else
697 yytoken = ]b4_symbol(empty, kind)[;
700 /* Else will try to reuse lookahead token after shifting the error
701 * token. */
702 label = YYERRLAB1;
703 break;
705 /*-------------------------------------------------.
706 | errorlab -- error raised explicitly by YYERROR. |
707 `-------------------------------------------------*/
708 case YYERROR:]b4_locations_if([
709 yyerrloc = yystack.locationAt (yylen - 1);])[
710 /* Do not reclaim the symbols of the rule which action triggered
711 this YYERROR. */
712 yystack.pop (yylen);
713 yylen = 0;
714 yystate = yystack.stateAt (0);
715 label = YYERRLAB1;
716 break;
718 /*-------------------------------------------------------------.
719 | yyerrlab1 -- common code for both syntax error and YYERROR. |
720 `-------------------------------------------------------------*/
721 case YYERRLAB1:
722 yyerrstatus_ = 3; /* Each real token shifted decrements this. */
724 // Pop stack until we find a state that shifts the error token.
725 for (;;)
727 yyn = yypact_[yystate];
728 if (!yyPactValueIsDefault(yyn))
730 yyn += ]b4_symbol(error, kind)[;
731 if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == ]b4_symbol(error, kind)[)
733 yyn = yytable_[yyn];
734 if (0 < yyn)
735 break;
739 /* Pop the current state because it cannot handle the error token. */
740 if (yystack.height == 1)]b4_push_if([[
742 label = YYABORT;
743 break;
744 }]],[[
745 return false;]])[
747 ]b4_locations_if([ yyerrloc = yystack.locationAt (0);])[
748 yystack.pop ();
749 yystate = yystack.stateAt (0);]b4_parse_trace_if([[
750 if (0 < yydebug)
751 yystack.print (yyDebugStream);]])[
752 }]b4_push_if([[
753 if (label == YYABORT)
754 /* Leave the switch. */
755 break;
756 ]])[
757 ]b4_locations_if([
758 /* Muck with the stack to setup for yylloc. */
759 yystack.push (0, yy_semantic_null, yylloc);
760 yystack.push (0, yy_semantic_null, yyerrloc);
761 yyloc = yylloc_from_stack (yystack, 2);
762 yystack.pop (2);])[
764 /* Shift the error token. */]b4_lac_if([[
765 yylacDiscard("error recovery");]])[]b4_parse_trace_if([[
766 yy_symbol_print ("Shifting", to!SymbolKind (yystos_[yyn]), yylval]b4_locations_if([, yyloc])[);]])[
767 yystate = yyn;
768 yystack.push (yyn, yylval]b4_locations_if([, yyloc])[);
769 label = YYNEWSTATE;
770 break;
772 /* Accept. */
773 case YYACCEPT:]b4_push_if([[
774 this.pushParseInitialized = false;]b4_parse_trace_if([[
775 if (0 < yydebug)
776 yystack.print (yyDebugStream);]])[
777 return YYACCEPT;]], [[
778 yyresult = true;
779 label = YYRETURN;
780 break;]])[
782 /* Abort. */
783 case YYABORT:]b4_push_if([[
784 this.pushParseInitialized = false;]b4_parse_trace_if([[
785 if (0 < yydebug)
786 yystack.print (yyDebugStream);]])[
787 return YYABORT;]], [[
788 yyresult = false;
789 label = YYRETURN;
790 break;]])[
791 ]b4_push_if([[]], [[ ][case YYRETURN:]b4_parse_trace_if([[
792 if (0 < yydebug)
793 yystack.print (yyDebugStream);]])[
794 return yyresult;]])[
796 assert(0);
799 ]b4_push_if([[
800 bool pushParseInitialized = false;
803 * (Re-)Initialize the state of the push parser.
805 public void pushParseInitialize()
808 /* Lookahead and lookahead in internal form. */
809 this.yytoken = ]b4_symbol(empty, kind)[;
811 /* State. */
812 this.yyn = 0;
813 this.yylen = 0;
814 this.yystate = 0;
815 destroy(this.yystack);
816 this.label = YYNEWSTATE;
817 ]b4_lac_if([[
818 destroy(this.yylacStack);
819 this.yylacEstablished = false;]])[
821 /* Error handling. */
822 this.yynerrs_ = 0;
823 ]b4_locations_if([
824 /* The location where the error started. */
825 this.yyerrloc = Location(Position(), Position());
826 this.yylloc = Location(Position(), Position());])[
828 /* Semantic value of the lookahead. */
829 //destroy(this.yylval);
831 /* Initialize the stack. */
832 yystack.push(this.yystate, this.yylval]b4_locations_if([, this.yylloc])[);
834 this.pushParseInitialized = true;
835 }]])[]b4_both_if([[
837 * Parse input from the scanner that was specified at object construction
838 * time. Return whether the end of the input was reached successfully.
839 * This version of parse() is defined only when api.push-push=both.
841 * @@return <tt>true</tt> if the parsing succeeds. Note that this does not
842 * imply that there were no syntax errors.
844 bool parse()
846 int status = 0;
847 do {
848 status = this.pushParse(yylex());
849 } while (status == YYPUSH_MORE);
850 return status == YYACCEPT;
851 }]])[
853 // Generate an error message.
854 private final void yyreportSyntaxError(Context yyctx)
855 {]b4_parse_error_bmatch(
856 [custom], [[
857 yylexer.reportSyntaxError(yyctx);]],
858 [detailed], [[
859 if (yyctx.getToken() != ]b4_symbol(empty, kind)[)
861 // FIXME: This method of building the message is not compatible
862 // with internationalization.
863 immutable int argmax = 5;
864 SymbolKind[] yyarg = new SymbolKind[argmax];
865 int yycount = yysyntaxErrorArguments(yyctx, yyarg, argmax);
866 string res, yyformat;
867 switch (yycount)
869 case 1:
870 yyformat = YY_("syntax error, unexpected %s");
871 res = format(yyformat, yyarg[0]);
872 break;
873 case 2:
874 yyformat = YY_("syntax error, unexpected %s, expecting %s");
875 res = format(yyformat, yyarg[0], yyarg[1]);
876 break;
877 case 3:
878 yyformat = YY_("syntax error, unexpected %s, expecting %s or %s");
879 res = format(yyformat, yyarg[0], yyarg[1], yyarg[2]);
880 break;
881 case 4:
882 yyformat = YY_("syntax error, unexpected %s, expecting %s or %s or %s");
883 res = format(yyformat, yyarg[0], yyarg[1], yyarg[2], yyarg[3]);
884 break;
885 case 5:
886 yyformat = YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
887 res = format(yyformat, yyarg[0], yyarg[1], yyarg[2], yyarg[3], yyarg[4]);
888 break;
889 default:
890 res = YY_("syntax error");
891 break;
893 yyerror(]b4_locations_if([yyctx.getLocation(), ])[res);
894 }]],
895 [[simple]], [[
896 yyerror(]b4_locations_if([yyctx.getLocation(), ])[YY_("syntax error"));]])[
899 ]b4_parse_error_bmatch(
900 [detailed], [[
901 private int yysyntaxErrorArguments(Context yyctx, SymbolKind[] yyarg, int yyargn) {
902 /* There are many possibilities here to consider:
903 - If this state is a consistent state with a default action,
904 then the only way this function was invoked is if the
905 default action is an error action. In that case, don't
906 check for expected tokens because there are none.
907 - The only way there can be no lookahead present (in tok) is
908 if this state is a consistent state with a default action.
909 Thus, detecting the absence of a lookahead is sufficient to
910 determine that there is no unexpected or expected token to
911 report. In that case, just report a simple "syntax error".
912 - Don't assume there isn't a lookahead just because this
913 state is a consistent state with a default action. There
914 might have been a previous inconsistent state, consistent
915 state with a non-default action, or user semantic action
916 that manipulated yychar. (However, yychar is currently out
917 of scope during semantic actions.)
918 - Of course, the expected token list depends on states to
919 have correct lookahead information, and it depends on the
920 parser not to perform extra reductions after fetching a
921 lookahead from the scanner and before detecting a syntax
922 error. Thus, state merging (from LALR or IELR) and default
923 reductions corrupt the expected token list. However, the
924 list is correct for canonical LR with one exception: it
925 will still contain any token that will not be accepted due
926 to an error action in a later state.
928 int yycount = 0;
929 if (yyctx.getToken() != ]b4_symbol(empty, kind)[)
931 if (yyarg !is null)
932 yyarg[yycount] = yyctx.getToken();
933 yycount += 1;
934 yycount += yyctx.getExpectedTokens(yyarg, 1, yyargn);
936 return yycount;
938 ]])[
942 * Information needed to get the list of expected tokens and to forge
943 * a syntax error diagnostic.
945 public static final class Context
946 {]b4_lac_if([[
947 private ]b4_parser_class[ yyparser;]])[
948 private const(YYStack) yystack;
949 private SymbolKind yytoken;]b4_locations_if([[
950 private const(Location) yylocation;]])[
952 this(]b4_lac_if([[]b4_parser_class[ parser, ]])[YYStack stack, SymbolKind kind]b4_locations_if([[, Location loc]])[)
953 {]b4_lac_if([[
954 yyparser = parser;]])[
955 yystack = stack;
956 yytoken = kind;]b4_locations_if([[
957 yylocation = loc;]])[
960 final SymbolKind getToken() const
962 return yytoken;
963 }]b4_locations_if([[
965 final const(Location) getLocation() const
967 return yylocation;
968 }]])[
970 * Put in YYARG at most YYARGN of the expected tokens given the
971 * current YYCTX, and return the number of tokens stored in YYARG. If
972 * YYARG is null, return the number of expected tokens (guaranteed to
973 * be less than YYNTOKENS).
975 int getExpectedTokens(SymbolKind[] yyarg, int yyargn)]b4_lac_if([[]], [[ const]])[
977 return getExpectedTokens(yyarg, 0, yyargn);
980 int getExpectedTokens(SymbolKind[] yyarg, int yyoffset, int yyargn)]b4_lac_if([[]], [[ const]])[
982 int yycount = yyoffset;]b4_lac_if([b4_parse_trace_if([[
983 // Execute LAC once. We don't care if it is successful, we
984 // only do it for the sake of debugging output.
986 if (!yyparser.yylacEstablished)
987 yyparser.yylacCheck(yystack, yytoken);
988 ]])[
989 for (int yyx = 0; yyx < yyntokens_; ++yyx)
991 SymbolKind yysym = SymbolKind(yyx);
992 if (yysym != ]b4_symbol(error, kind)[
993 && yysym != ]b4_symbol(undef, kind)[
994 && yyparser.yylacCheck(yystack, yysym))
996 if (yyarg == null)
997 yycount += 1;
998 else if (yycount == yyargn)
999 return 0;
1000 else
1001 yyarg[yycount++] = yysym;
1003 }]], [[
1004 int yyn = yypact_[this.yystack.stateAt(0)];
1005 if (!yyPactValueIsDefault(yyn))
1007 /* Start YYX at -YYN if negative to avoid negative
1008 indexes in YYCHECK. In other words, skip the first
1009 -YYN actions for this state because they are default
1010 actions. */
1011 int yyxbegin = yyn < 0 ? -yyn : 0;
1012 /* Stay within bounds of both yycheck and yytname. */
1013 int yychecklim = yylast_ - yyn + 1;
1014 int yyxend = yychecklim < yyntokens_ ? yychecklim : yyntokens_;
1015 for (int yyx = yyxbegin; yyx < yyxend; ++yyx)
1016 if (yycheck_[yyx + yyn] == yyx && yyx != ]b4_symbol(error, kind)[
1017 && !yyTableValueIsError(yytable_[yyx + yyn]))
1019 if (yyarg is null)
1020 ++yycount;
1021 else if (yycount == yyargn)
1022 return 0;
1023 else
1024 yyarg[yycount++] = SymbolKind(yyx);
1026 }]])[
1027 if (yyarg !is null && yycount == yyoffset && yyoffset < yyargn)
1028 yyarg[yyoffset] = ]b4_symbol(empty, kind)[;
1029 return yycount - yyoffset;
1033 ]b4_lac_if([[
1034 /** Check the lookahead yytoken.
1035 * \returns true iff the token will be eventually shifted.
1037 bool yylacCheck(const YYStack yystack, SymbolKind yytoken)
1039 // Logically, the yylacStack's lifetime is confined to this function.
1040 // Clear it, to get rid of potential left-overs from previous call.
1041 destroy(yylacStack);
1042 // Reduce until we encounter a shift and thereby accept the token.
1043 ]b4_parse_trace_if([[
1044 yycdebug("LAC: checking lookahead " ~ format("%s", yytoken) ~ ":");]])[
1045 int lacTop = 0;
1046 while (true)
1048 int topState = (yylacStack.length == 0
1049 ? yystack.stateAt(lacTop)
1050 : yylacStack[$ - 1]);
1051 int yyrule = yypact_[topState];
1052 if (yyPactValueIsDefault(yyrule)
1053 || (yyrule += yytoken) < 0 || yylast_ < yyrule
1054 || yycheck_[yyrule] != yytoken)
1056 // Use the default action.
1057 yyrule = yydefact_[+topState];
1058 if (yyrule == 0)
1059 {]b4_parse_trace_if([[
1060 yycdebugln(" Err");]])[
1061 return false;
1064 else
1066 // Use the action from yytable.
1067 yyrule = yytable_[yyrule];
1068 if (yyTableValueIsError(yyrule))
1069 {]b4_parse_trace_if([[
1070 yycdebugln(" Err");]])[
1071 return false;
1073 if (0 < yyrule)
1074 {]b4_parse_trace_if([[
1075 yycdebugln(" S" ~ to!string(yyrule));]])[
1076 return true;
1078 yyrule = -yyrule;
1080 // By now we know we have to simulate a reduce.
1081 ]b4_parse_trace_if([[
1082 yycdebug(" R" ~ to!string(yyrule - 1));]])[
1083 // Pop the corresponding number of values from the stack.
1085 int yylen = yyr2_[yyrule];
1086 // First pop from the LAC stack as many tokens as possible.
1087 int lacSize = cast (int) yylacStack.length;
1088 if (yylen < lacSize)
1090 yylacStack.length -= yylen;
1091 yylen = 0;
1093 else if (lacSize != 0)
1095 destroy(yylacStack);
1096 yylen -= lacSize;
1098 // Only afterwards look at the main stack.
1099 // We simulate popping elements by incrementing lacTop.
1100 lacTop += yylen;
1102 // Keep topState in sync with the updated stack.
1103 topState = (yylacStack.length == 0
1104 ? yystack.stateAt(lacTop)
1105 : yylacStack[$ - 1]);
1106 // Push the resulting state of the reduction.
1107 int state = yyLRGotoState(topState, yyr1_[yyrule]);]b4_parse_trace_if([[
1108 yycdebug(" G" ~ to!string(state));]])[
1109 yylacStack.length++;
1110 yylacStack[$ - 1] = state;
1114 /** Establish the initial context if no initial context currently exists.
1115 * \returns true iff the token will be eventually shifted.
1117 bool yylacEstablish(YYStack yystack, SymbolKind yytoken)
1119 /* Establish the initial context for the current lookahead if no initial
1120 context is currently established.
1122 We define a context as a snapshot of the parser stacks. We define
1123 the initial context for a lookahead as the context in which the
1124 parser initially examines that lookahead in order to select a
1125 syntactic action. Thus, if the lookahead eventually proves
1126 syntactically unacceptable (possibly in a later context reached via a
1127 series of reductions), the initial context can be used to determine
1128 the exact set of tokens that would be syntactically acceptable in the
1129 lookahead's place. Moreover, it is the context after which any
1130 further semantic actions would be erroneous because they would be
1131 determined by a syntactically unacceptable token.
1133 yylacEstablish should be invoked when a reduction is about to be
1134 performed in an inconsistent state (which, for the purposes of LAC,
1135 includes consistent states that don't know they're consistent because
1136 their default reductions have been disabled).
1138 For parse.lac=full, the implementation of yylacEstablish is as
1139 follows. If no initial context is currently established for the
1140 current lookahead, then check if that lookahead can eventually be
1141 shifted if syntactic actions continue from the current context. */
1142 if (yylacEstablished)
1143 return true;
1144 else
1145 {]b4_parse_trace_if([[
1146 yycdebugln("LAC: initial context established for " ~ format("%s", yytoken));]])[
1147 yylacEstablished = true;
1148 return yylacCheck(yystack, yytoken);
1152 /** Discard any previous initial lookahead context because of event.
1153 * \param event the event which caused the lookahead to be discarded.
1154 * Only used for debbuging output. */
1155 void yylacDiscard(string event)
1157 /* Discard any previous initial lookahead context because of Event,
1158 which may be a lookahead change or an invalidation of the currently
1159 established initial context for the current lookahead.
1161 The most common example of a lookahead change is a shift. An example
1162 of both cases is syntax error recovery. That is, a syntax error
1163 occurs when the lookahead is syntactically erroneous for the
1164 currently established initial context, so error recovery manipulates
1165 the parser stacks to try to find a new initial context in which the
1166 current lookahead is syntactically acceptable. If it fails to find
1167 such a context, it discards the lookahead. */
1168 if (yylacEstablished)
1169 {]b4_parse_trace_if([[
1170 yycdebugln("LAC: initial context discarded due to " ~ event);]])[
1171 yylacEstablished = false;
1175 /** The stack for LAC.
1176 * Logically, the yylacStack's lifetime is confined to the function
1177 * yylacCheck. We just store it as a member of this class to hold
1178 * on to the memory and to avoid frequent reallocations.
1180 int[] yylacStack;
1181 /** Whether an initial LAC context was established. */
1182 bool yylacEstablished;
1183 ]])[
1186 * Whether the given <code>yypact_</code> value indicates a defaulted state.
1187 * @@param yyvalue the value to check
1189 private static bool yyPactValueIsDefault(int yyvalue)
1191 return yyvalue == yypact_ninf_;
1195 * Whether the given <code>yytable_</code> value indicates a syntax error.
1196 * @@param yyvalue the value to check
1198 private static bool yyTableValueIsError(int yyvalue)
1200 return yyvalue == yytable_ninf_;
1203 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
1204 STATE-NUM. */
1205 private static immutable ]b4_int_type_for([b4_pact])[ yypact_ninf_ = ]b4_pact_ninf[;
1207 /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
1208 positive, shift that token. If negative, reduce the rule which
1209 number is the opposite. If YYTABLE_NINF_, syntax error. */
1210 private static immutable ]b4_int_type_for([b4_table])[ yytable_ninf_ = ]b4_table_ninf[;
1212 ]b4_parser_tables_define[
1214 ]b4_parse_trace_if([[
1215 /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
1216 private static immutable ]b4_int_type_for([b4_rline])[[] yyrline_ =
1218 ]b4_rline[
1221 // Report on the debug stream that the rule yyrule is going to be reduced.
1222 private final void yy_reduce_print (int yyrule, ref YYStack yystack)
1224 if (yydebug == 0)
1225 return;
1227 int yylno = yyrline_[yyrule];
1228 int yynrhs = yyr2_[yyrule];
1229 /* Print the symbols being reduced, and their result. */
1230 yycdebugln (format("Reducing stack by rule %d (line %d):",
1231 yyrule - 1, yylno));
1233 /* The symbols being reduced. */
1234 for (int yyi = 0; yyi < yynrhs; yyi++)
1235 yy_symbol_print (format(" $%d =", yyi + 1),
1236 to!SymbolKind (yystos_[yystack.stateAt(yynrhs - (yyi + 1))]),
1237 ]b4_rhs_value(yynrhs, yyi + 1)b4_locations_if([,
1238 b4_rhs_location(yynrhs, yyi + 1)])[);
1240 ]])[
1242 private static auto yytranslate_ (int t)
1244 ]b4_api_token_raw_if(
1245 [[ return SymbolKind(t);]],
1246 [[ /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
1247 immutable ]b4_int_type_for([b4_translate])[[] translate_table =
1249 ]b4_translate[
1252 // Last valid token kind.
1253 immutable int code_max = ]b4_code_max[;
1255 if (t <= 0)
1256 return ]b4_symbol(eof, kind)[;
1257 else if (t <= code_max)
1258 return SymbolKind(translate_table[t]);
1259 else
1260 return ]b4_symbol(undef, kind)[;]])[
1263 private static immutable int yylast_ = ]b4_last[;
1264 private static immutable int yynnts_ = ]b4_nterms_number[;
1265 private static immutable int yyfinal_ = ]b4_final_state_number[;
1266 private static immutable int yyntokens_ = ]b4_tokens_number[;
1268 private final struct YYStackElement {
1269 int state;
1270 Value value;]b4_locations_if(
1271 b4_location_type[[] location;])[
1274 private final struct YYStack {
1275 private YYStackElement[] stack = [];
1277 public final ulong height()
1279 return stack.length;
1282 public final void push (int state, Value value]dnl
1283 b4_locations_if([, ref Location loc])[)
1285 stack ~= YYStackElement(state, value]b4_locations_if([, loc])[);
1288 public final void pop ()
1290 pop (1);
1293 public final void pop (int num)
1295 stack.length -= num;
1298 public final int stateAt (int i) const
1300 return stack[$-i-1].state;
1303 ]b4_locations_if([[
1304 public final ref Location locationAt (int i)
1306 return stack[$-i-1].location;
1307 }]])[
1309 public final ref Value valueAt (int i)
1311 return stack[$-i-1].value;
1313 ]b4_parse_trace_if([[
1314 // Print the state stack on the debug stream.
1315 public final void print (File stream)
1317 stream.write ("Stack now");
1318 for (int i = 0; i < stack.length; i++)
1319 stream.write (" ", stack[i].state);
1320 stream.writeln ();
1321 }]])[
1323 ]b4_percent_code_get[
1325 ]b4_percent_code_get([[epilogue]])[]dnl
1326 b4_epilogue[]dnl
1327 b4_output_end