gnulib: update
[bison.git] / data / skeletons / lalr1.d
blob97303772227dc16f4d83c1040d5531848af2be48
1 # D skeleton for Bison -*- autoconf -*-
3 # Copyright (C) 2007-2012, 2019-2021 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-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");
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 implements Lexer {
273 ]b4_percent_code_get([[lexer]])[
275 ]])[
276 /** The object doing lexical analysis for us. */
277 private Lexer yylexer;
279 ]b4_parse_param_vars[
281 ]b4_lexer_if([[
283 * Instantiate the Bison-generated parser.
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[));
291 ]])[
294 * Instantiate the Bison-generated parser.
295 * @@param yylexer The scanner that will supply tokens to the parser.
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[
302 ]b4_parse_trace_if([[
303 import std.stdio;
304 private File yyDebugStream;
307 * The <tt>File</tt> on which the debugging output is
308 * printed.
310 public File getDebugStream () { return yyDebugStream; }
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.
316 public final void setDebugStream(File s) { yyDebugStream = s; }
318 private int yydebug = 0;
321 * Answer the verbosity of the debugging output; 0 means that all kinds of
322 * output from the parser are suppressed.
324 public final int getDebugLevel() { return yydebug; }
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.
331 public final void setDebugLevel(int level) { yydebug = level; }
333 protected final void yycdebug (string s) {
334 if (0 < yydebug)
335 yyDebugStream.write (s);
338 protected final void yycdebugln (string s) {
339 if (0 < yydebug)
340 yyDebugStream.writeln (s);
342 ]])[
343 private final ]b4_parser_class[.Symbol yylex () {
344 return yylexer.yylex ();
347 protected final void yyerror (]b4_locations_if([[const Location loc, ]])[string s) {
348 yylexer.yyerror (]b4_locations_if([loc, ])[s);
352 * The number of syntax errors so far.
354 public int numberOfErrors() const { return yynerrs_; }
355 private int yynerrs_ = 0;
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;
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([
368 * Returned by a Bison action in order to request a new token.
370 public static immutable int YYPUSH_MORE = 4;])[
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;
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. */]])[
387 ]b4_locations_if([
388 private static immutable YYSemanticType yy_semantic_null;])[
389 private int yyerrstatus_ = 0;
391 private void yyerrok()
393 yyerrstatus_ = 0;
396 // Lookahead symbol kind.
397 SymbolKind yytoken = ]b4_symbol(empty, kind)[;
399 /* State. */
400 int yyn = 0;
401 int yylen = 0;
402 int yystate = 0;
404 YYStack yystack;
406 int label = YYNEWSTATE;
408 /* Error handling. */
409 ]b4_locations_if([[
410 /// The location where the error started.
411 Location yyerrloc;
413 /// Location of the lookahead.
414 Location yylloc;
416 /// @@$.
417 Location yyloc;]])[
419 /// Semantic value of the lookahead.
420 Value yylval;
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 ()
428 return yyerrstatus_ == 0;
431 /** Compute post-reduction state.
432 * @@param yystate the current state
433 * @@param yysym the nonterminal to push on the stack
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_];
443 private int yyaction (int yyn, ref YYStack yystack, int yylen)
445 Value yyval;]b4_locations_if([[
446 Location yyloc = yylloc_from_stack (yystack, yylen);]])[
448 /* If YYLEN is nonzero, implement the default value of the action:
449 `$$ = $1'. Otherwise, use the top of the stack.
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);
459 ]b4_parse_trace_if([[
460 yy_reduce_print (yyn, yystack);]])[
462 switch (yyn)
464 ]b4_user_actions[
465 default: break;
468 ]b4_parse_trace_if([[
469 yy_symbol_print ("-> $$ =", to!SymbolKind (yyr1_[yyn]), yyval]b4_locations_if([, yyloc])[);]])[
471 yystack.pop (yylen);
472 yylen = 0;
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;
480 ]b4_parse_trace_if([[
481 /*--------------------------------.
482 | Print this symbol on YYOUTPUT. |
483 `--------------------------------*/
485 private final void yy_symbol_print (string s, SymbolKind yykind,
486 ref Value yyval]b4_locations_if([, ref Location yyloc])[)
488 if (0 < yydebug)
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");
499 ]])[
500 ]b4_symbol_type_define[
501 ]b4_push_if([[
503 * Push Parse input from external lexer
505 * @@param yyla current Symbol
507 * @@return <tt>YYACCEPT, YYABORT, YYPUSH_MORE</tt>
509 public int pushParse(Symbol yyla)]], [[
511 * Parse input from the scanner that was specified at object construction
512 * time. Return whether the end of the input was reached successfully.
514 * @@return <tt>true</tt> if the parsing succeeds. Note that this does not
515 * imply that there were no syntax errors.
517 public bool parse()]])[
518 {]b4_push_if([[
519 if (!this.pushParseInitialized)
521 pushParseInitialize();
522 yyerrstatus_ = 0;
524 else
525 label = YYGETTOKEN;
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([[
533 yycdebugln ("Starting parse");]])[
534 yyerrstatus_ = 0;
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
544 [ /* Initialize the stack. */
545 yystack.push (yystate, yylval]b4_locations_if([, yylloc])[);
547 label = YYNEWSTATE;]])[
548 for (;;)
549 final switch (label)
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);]])[
558 /* Accept? */
559 if (yystate == yyfinal_)]b4_push_if([[
561 label = YYACCEPT;
562 break;
563 }]], [[
564 return true;]])[
566 /* Take a decision. First try without lookahead. */
567 yyn = yypact_[yystate];
568 if (yyPactValueIsDefault(yyn))
570 label = YYDEFAULT;
571 break;
572 }]b4_push_if([[
573 goto case;
575 case YYGETTOKEN:]])[
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();]])[]])[
593 /* Token already converted to internal form. */]b4_parse_trace_if([[
594 yy_symbol_print ("Next token is", yytoken, yylval]b4_locations_if([, yylloc])[);]])[
596 if (yytoken == ]b4_symbol(error, kind)[)
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;
606 else
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;
617 /* <= 0 means reduce or error. */
618 else if ((yyn = yytable_[yyn]) <= 0)
620 if (yyTableValueIsError(yyn))
621 label = YYERRLAB;]b4_lac_if([[
622 else if (!yylacEstablish(yystack, yytoken))
623 label = YYERRLAB;]])[
624 else
626 yyn = -yyn;
627 label = YYREDUCE;
630 else
632 /* Shift the lookahead token. */]b4_parse_trace_if([[
633 yy_symbol_print ("Shifting", yytoken, yylval]b4_locations_if([, yylloc])[);]])[
635 /* Discard the token being shifted. */
636 yytoken = ]b4_symbol(empty, kind)[;
638 /* Count tokens shifted since error; after three, turn off error
639 * status. */
640 if (yyerrstatus_ > 0)
641 --yyerrstatus_;
643 yystate = yyn;
644 yystack.push (yystate, yylval]b4_locations_if([, yylloc])[);]b4_lac_if([[
645 yylacDiscard("shift");]])[
646 label = YYNEWSTATE;
649 break;
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;
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;
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)
678 ++yynerrs_;
679 yyreportSyntaxError(new Context(]b4_lac_if([[this, ]])[yystack, yytoken]b4_locations_if([[, yylloc]])[));
681 ]b4_locations_if([
682 yyerrloc = yylloc;])[
683 if (yyerrstatus_ == 3)
685 /* If just tried and failed to reuse lookahead token after an
686 * error, discard it. */
688 /* Return failure if at end of input. */
689 if (yytoken == ]b4_symbol(eof, [kind])[)]b4_push_if([[
691 label = YYABORT;
692 break;
693 }]], [[
694 return false;]])[
695 else
696 yytoken = ]b4_symbol(empty, kind)[;
699 /* Else will try to reuse lookahead token after shifting the error
700 * token. */
701 label = YYERRLAB1;
702 break;
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;
717 /*-------------------------------------------------------------.
718 | yyerrlab1 -- common code for both syntax error and YYERROR. |
719 `-------------------------------------------------------------*/
720 case YYERRLAB1:
721 yyerrstatus_ = 3; /* Each real token shifted decrements this. */
723 // Pop stack until we find a state that shifts the error token.
724 for (;;)
726 yyn = yypact_[yystate];
727 if (!yyPactValueIsDefault(yyn))
729 yyn += ]b4_symbol(error, kind)[;
730 if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == ]b4_symbol(error, kind)[)
732 yyn = yytable_[yyn];
733 if (0 < yyn)
734 break;
738 /* Pop the current state because it cannot handle the error token. */
739 if (yystack.height == 1)]b4_push_if([[
741 label = YYABORT;
742 break;
743 }]],[[
744 return false;]])[
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);])[
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;
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;]])[
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;]])[
795 assert(0);
798 ]b4_push_if([[
799 bool pushParseInitialized = false;
802 * (Re-)Initialize the state of the push parser.
804 public void pushParseInitialize()
807 /* Lookahead and lookahead in internal form. */
808 this.yytoken = ]b4_symbol(empty, kind)[;
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;]])[
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());])[
827 /* Semantic value of the lookahead. */
828 //destroy(this.yylval);
830 /* Initialize the stack. */
831 yystack.push(this.yystate, this.yylval]b4_locations_if([, this.yylloc])[);
833 this.pushParseInitialized = true;
834 }]])[]b4_both_if([[
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.
840 * @@return <tt>true</tt> if the parsing succeeds. Note that this does not
841 * imply that there were no syntax errors.
843 bool parse()
845 int status = 0;
846 do {
847 status = this.pushParse(yylex());
848 } while (status == YYPUSH_MORE);
849 return status == YYACCEPT;
850 }]])[
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)[)
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)
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;
892 yyerror(]b4_locations_if([yyctx.getLocation(), ])[res);
893 }]],
894 [[simple]], [[
895 yyerror(]b4_locations_if([yyctx.getLocation(), ])[YY_("syntax error"));]])[
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.
927 int yycount = 0;
928 if (yyctx.getToken() != ]b4_symbol(empty, kind)[)
930 if (yyarg !is null)
931 yyarg[yycount] = yyctx.getToken();
932 yycount += 1;
933 yycount += yyctx.getExpectedTokens(yyarg, 1, yyargn);
935 return yycount;
937 ]])[
941 * Information needed to get the list of expected tokens and to forge
942 * a syntax error diagnostic.
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;]])[
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;]])[
959 final SymbolKind getToken() const
961 return yytoken;
962 }]b4_locations_if([[
964 final const(Location) getLocation() const
966 return yylocation;
967 }]])[
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).
974 int getExpectedTokens(SymbolKind[] yyarg, int yyargn)]b4_lac_if([[]], [[ const]])[
976 return getExpectedTokens(yyarg, 0, yyargn);
979 int getExpectedTokens(SymbolKind[] yyarg, int yyoffset, int yyargn)]b4_lac_if([[]], [[ const]])[
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.
985 if (!yyparser.yylacEstablished)
986 yyparser.yylacCheck(yystack, yytoken);
987 ]])[
988 for (int yyx = 0; yyx < yyntokens_; ++yyx)
990 SymbolKind yysym = SymbolKind(yyx);
991 if (yysym != ]b4_symbol(error, kind)[
992 && yysym != ]b4_symbol(undef, kind)[
993 && yyparser.yylacCheck(yystack, yysym))
995 if (yyarg == null)
996 yycount += 1;
997 else if (yycount == yyargn)
998 return 0;
999 else
1000 yyarg[yycount++] = yysym;
1002 }]], [[
1003 int yyn = yypact_[this.yystack.stateAt(0)];
1004 if (!yyPactValueIsDefault(yyn))
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]))
1018 if (yyarg is null)
1019 ++yycount;
1020 else if (yycount == yyargn)
1021 return 0;
1022 else
1023 yyarg[yycount++] = SymbolKind(yyx);
1025 }]])[
1026 if (yyarg !is null && yycount == yyoffset && yyoffset < yyargn)
1027 yyarg[yyoffset] = ]b4_symbol(empty, kind)[;
1028 return yycount - yyoffset;
1032 ]b4_lac_if([[
1033 /** Check the lookahead yytoken.
1034 * \returns true iff the token will be eventually shifted.
1036 bool yylacCheck(const YYStack yystack, SymbolKind yytoken)
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)
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)
1055 // Use the default action.
1056 yyrule = yydefact_[+topState];
1057 if (yyrule == 0)
1058 {]b4_parse_trace_if([[
1059 yycdebugln(" Err");]])[
1060 return false;
1063 else
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;
1072 if (0 < yyrule)
1073 {]b4_parse_trace_if([[
1074 yycdebugln(" S" ~ to!string(yyrule));]])[
1075 return true;
1077 yyrule = -yyrule;
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.
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)
1089 yylacStack.length -= yylen;
1090 yylen = 0;
1092 else if (lacSize != 0)
1094 destroy(yylacStack);
1095 yylen -= lacSize;
1097 // Only afterwards look at the main stack.
1098 // We simulate popping elements by incrementing lacTop.
1099 lacTop += yylen;
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;
1113 /** Establish the initial context if no initial context currently exists.
1114 * \returns true iff the token will be eventually shifted.
1116 bool yylacEstablish(YYStack yystack, SymbolKind yytoken)
1118 /* Establish the initial context for the current lookahead if no initial
1119 context is currently established.
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.
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).
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);
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)
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.
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;
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.
1179 int[] yylacStack;
1180 /** Whether an initial LAC context was established. */
1181 bool yylacEstablished;
1182 ]])[
1185 * Whether the given <code>yypact_</code> value indicates a defaulted state.
1186 * @@param yyvalue the value to check
1188 private static bool yyPactValueIsDefault(int yyvalue)
1190 return yyvalue == yypact_ninf_;
1194 * Whether the given <code>yytable_</code> value indicates a syntax error.
1195 * @@param yyvalue the value to check
1197 private static bool yyTableValueIsError(int yyvalue)
1199 return yyvalue == yytable_ninf_;
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[;
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[;
1211 ]b4_parser_tables_define[
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_ =
1217 ]b4_rline[
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)
1223 if (yydebug == 0)
1224 return;
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));
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)])[);
1239 ]])[
1241 private static auto yytranslate_ (int t)
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 =
1248 ]b4_translate[
1251 // Last valid token kind.
1252 immutable int code_max = ]b4_code_max[;
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)[;]])[
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[;
1267 private final struct YYStackElement {
1268 int state;
1269 Value value;]b4_locations_if(
1270 b4_location_type[[] location;])[
1273 private final struct YYStack {
1274 private YYStackElement[] stack = [];
1276 public final ulong height()
1278 return stack.length;
1281 public final void push (int state, Value value]dnl
1282 b4_locations_if([, ref Location loc])[)
1284 stack ~= YYStackElement(state, value]b4_locations_if([, loc])[);
1287 public final void pop ()
1289 pop (1);
1292 public final void pop (int num)
1294 stack.length -= num;
1297 public final int stateAt (int i) const
1299 return stack[$-i-1].state;
1302 ]b4_locations_if([[
1303 public final ref Location locationAt (int i)
1305 return stack[$-i-1].location;
1306 }]])[
1308 public final ref Value valueAt (int i)
1310 return stack[$-i-1].value;
1312 ]b4_parse_trace_if([[
1313 // Print the state stack on the debug stream.
1314 public final void print (File stream)
1316 stream.write ("Stack now");
1317 for (int i = 0; i < stack.length; i++)
1318 stream.write (" ", stack[i].state);
1319 stream.writeln ();
1320 }]])[
1322 ]b4_percent_code_get[
1324 ]b4_percent_code_get([[epilogue]])[]dnl
1325 b4_epilogue[]dnl
1326 b4_output_end