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
<http
://www.gnu.org/licenses/>.
18 m4_include(b4_skeletonsdir
/[d
.m4
])
21 b4_percent_define_default([[parse
.lac
]], [[none
]])
22 b4_percent_define_check_values([[[[parse
.lac
]], [[full
]], [[none
]]]])
23 b4_define_flag_if([lac
])
24 m4_define([b4_lac_flag
],
25 [m4_if(b4_percent_define_get([[parse
.lac
]]),
26 [none
], [[0]], [[1]])])
28 b4_output_begin([b4_parser_file_name
])
29 b4_copyright([Skeleton implementation
for Bison
LALR(1) parsers
in D
],
30 [2007-2012, 2019-2021])[
32 ]b4_percent_define_ifdef([package], [module b4_percent_define_get([package]);
36 static assert(false, "need compiler for D Version 2");
39 ]b4_user_pre_prologue
[
40 ]b4_user_post_prologue
[
41 ]b4_percent_code_get([[imports
]])[
46 * Handle error message internationalisation.
48 static if (!is(typeof(YY_
))) {
53 extern(C
) char* dgettext(const char*, const char*);
54 string
YY_(const char* s
)
56 return to
!string(dgettext("bison-runtime", s
));
60 static if (!is(typeof(YY_
)))
63 string
YY_(string msg
) { return msg
; }
68 * A Bison parser, automatically generated from <tt>]m4_bpatsubst(b4_file_name, [^"\(.*\)"$], [\1])[</tt>.
70 * @@author LALR (1) parser skeleton written by Paolo Bonzini.
71 * Port to D language was done by Oliver Mangold.
75 * Communication interface between the scanner and the Bison-generated
76 * parser <tt>]b4_parser_class[</tt>.
78 public interface Lexer
81 * Entry point for the scanner. Returns the token identifier corresponding
82 * to the next token and prepares to return the semantic value
83 * ]b4_locations_if([and beginning/ending positions ])[of the token.
84 * @@return the token identifier corresponding to the next token. */
88 * Entry point for error reporting. Emits an error
89 * ]b4_locations_if([referring to the given location ])[in a user-defined way.
91 * @@param loc The location of the element to which the
92 * error message is related]])[
93 * @@param s The string for the error message. */
94 void yyerror (]b4_locations_if([[const Location loc
, ]])[string s
);
95 ]b4_parse_error_bmatch([custom
], [[
97 * Build and emit a "syntax error" message in a user-defined way.
99 * @@param ctx The context of the error.
101 void reportSyntaxError(]b4_parser_class
[.Context ctx
);
105 ]b4_public_types_declare
[
107 ]b4_locations_if([b4_position_type_if([[
108 static assert(__traits(compiles
,
109 (new Position
[1])[0]=(new Position
[1])[0]),
110 "struct/class Position must be default-constructible "
112 static assert(__traits(compiles
, (new string
[1])[0]=(new Position
).toString()),
113 "error: struct/class Position must have toString method");
116 * A struct denoting a point in the input.*/
117 public struct ]b4_position_type
[ {
119 /** The column index within the line of input. */
120 public int column
= 1;
121 /** The line number within an input file. */
123 /** The name of the input file. */
124 public string filename
= null;
127 * A string representation of the position. */
128 public string
toString() const {
130 return format("%s:%d.%d", filename
, line
, column
);
132 return format("%d.%d", line
, column
);
135 ]])b4_location_type_if([[
136 static assert(__traits(compiles
, (new Location((new Position
[1])[0]))) &&
137 __traits(compiles
, (new Location((new Position
[1])[0], (new Position
[1])[0]))),
138 "error: struct/class Location must have "
139 "default constructor and constructors this(Position) and this(Position, Position).");
140 static assert(__traits(compiles
, (new Location
[1])[0].begin
=(new Location
[1])[0].begin
) &&
141 __traits(compiles
, (new Location
[1])[0].begin
=(new Location
[1])[0].end
) &&
142 __traits(compiles
, (new Location
[1])[0].end
=(new Location
[1])[0].begin
) &&
143 __traits(compiles
, (new Location
[1])[0].end
=(new Location
[1])[0].end
),
144 "error: struct/class Location must have assignment-compatible "
145 "members/properties 'begin' and 'end'.");
146 static assert(__traits(compiles
, (new string
[1])[0]=(new Location
[1])[0].toString()),
147 "error: struct/class Location must have toString method.");
149 private immutable bool yy_location_is_class
= !__traits(compiles
, *(new Location((new Position
[1])[0])));]], [[
151 * A struct defining a pair of positions. Positions, defined by the
152 * <code>Position</code> struct, denote a point in the input.
153 * Locations represent a part of the input through the beginning
154 * and ending positions. */
155 public struct ]b4_location_type
[
157 /** The first, inclusive, position in the range. */
158 public Position begin
;
160 /** The first position beyond the range. */
164 * Create a <code>Location</code> denoting an empty range located at
166 * @@param loc The position at which the range is anchored. */
167 public this(Position loc
)
169 this.begin
= this.end
= loc
;
173 * Create a <code>Location</code> from the endpoints of the range.
174 * @@param begin The first position included in the range.
175 * @@param end The first position beyond the range. */
176 public this(Position begin
, Position end
)
183 * Reset initial location to final location.
187 this.begin
= this.end
;
191 * A representation of the location.
193 public string
toString() const
195 auto end_col
= 0 < end
.column ? end
.column
- 1 : 0;
196 auto res
= begin
.toString ();
197 if (end
.filename
&& begin
.filename
!= end
.filename
)
198 res
~= "-" ~ format("%s:%d.%d", end
.filename
, end
.line
, end_col
);
199 else if (begin
.line
< end
.line
)
200 res
~= "-" ~ format("%d.%d", end
.line
, end_col
);
201 else if (begin
.column
< end_col
)
202 res
~= "-" ~ format("%d", end_col
);
207 private immutable bool yy_location_is_class
= false;
209 ]])])m4_ifdef([b4_user_union_members
], [private union YYSemanticType
211 b4_user_union_members
213 [m4_if(b4_tag_seen_flag
, 0,
214 [[private alias int YYSemanticType
;]])])[
216 ]b4_parser_class_declaration
[
220 ]b4_declare_symbol_enum
[
223 private final Location
yylloc_from_stack (ref YYStack rhs
, int n
)
225 static if (yy_location_is_class
) {
227 return new Location (rhs
.locationAt (n
-1).begin
, rhs
.locationAt (0).end
);
229 return new Location (rhs
.locationAt (0).end
);
232 return Location (rhs
.locationAt (n
-1).begin
, rhs
.locationAt (0).end
);
234 return Location (rhs
.locationAt (0).end
);
238 ]b4_lexer_if([[ private class YYLexer implements Lexer
{
239 ]b4_percent_code_get([[lexer
]])[
242 /** The object doing lexical analysis for us. */
243 private Lexer yylexer
;
245 ]b4_parse_param_vars
[
249 * Instantiate the Bison-generated parser.
251 public this] (b4_parse_param_decl([b4_lex_param_decl
])[) {
252 ]b4_percent_code_get([[init
]])[]b4_lac_if([[
253 this.yylacStack
= new int[];
254 this.yylacEstablished
= false;]])[
255 this (new YYLexer(]b4_lex_param_call
[));
260 * Instantiate the Bison-generated parser.
261 * @@param yylexer The scanner that will supply tokens to the parser.
263 ]b4_lexer_if([[protected]], [[public]]) [this (]b4_parse_param_decl([[Lexer yylexer
]])[) {
264 this.yylexer
= yylexer
;]b4_parse_trace_if([[
265 this.yyDebugStream
= stderr
;]])[
266 ]b4_parse_param_cons
[
268 ]b4_parse_trace_if([[
269 private File yyDebugStream
;
272 * The <tt>File</tt> on which the debugging output is
275 public File
getDebugStream () { return yyDebugStream
; }
278 * Set the <tt>std.File</tt> on which the debug output is printed.
279 * @@param s The stream that is used for debugging output.
281 public final void setDebugStream(File s
) { yyDebugStream
= s
; }
283 private int yydebug
= 0;
286 * Answer the verbosity of the debugging output; 0 means that all kinds of
287 * output from the parser are suppressed.
289 public final int getDebugLevel() { return yydebug
; }
292 * Set the verbosity of the debugging output; 0 means that all kinds of
293 * output from the parser are suppressed.
294 * @@param level The verbosity level for debugging output.
296 public final void setDebugLevel(int level
) { yydebug
= level
; }
298 protected final void yycdebug (string s
) {
300 yyDebugStream
.write (s
);
303 protected final void yycdebugln (string s
) {
305 yyDebugStream
.writeln (s
);
308 private final ]b4_parser_class
[.Symbol
yylex () {
309 return yylexer
.yylex ();
312 protected final void yyerror (]b4_locations_if([[const Location loc
, ]])[string s
) {
313 yylexer
.yyerror (]b4_locations_if([loc
, ])[s
);
317 * The number of syntax errors so far.
319 public int numberOfErrors() const { return yynerrs_
; }
320 private int yynerrs_
= 0;
323 * Returned by a Bison action in order to stop the parsing process and
324 * return success (<tt>true</tt>). */
325 public static immutable int YYACCEPT
= 0;
328 * Returned by a Bison action in order to stop the parsing process and
329 * return failure (<tt>false</tt>). */
330 public static immutable int YYABORT
= 1;
333 * Returned by a Bison action in order to start error recovery without
334 * printing an error message. */
335 public static immutable int YYERROR
= 2;
337 // Internal return codes that are not supported for user semantic
339 private static immutable int YYERRLAB
= 3;
340 private static immutable int YYNEWSTATE
= 4;
341 private static immutable int YYDEFAULT
= 5;
342 private static immutable int YYREDUCE
= 6;
343 private static immutable int YYERRLAB1
= 7;
344 private static immutable int YYRETURN
= 8;
346 private static immutable YYSemanticType yy_semantic_null
;])[
347 private int yyerrstatus_
= 0;
349 private void yyerrok()
355 * Whether error recovery is being done. In this state, the parser
356 * reads token until it reaches a known state, and then restarts normal
358 public final bool recovering ()
360 return yyerrstatus_
== 0;
363 /** Compute post-reduction state.
364 * @@param yystate the current state
365 * @@param yysym the nonterminal to push on the stack
367 private int yyLRGotoState(int yystate
, int yysym
) {
368 int yyr
= yypgoto_
[yysym
- yyntokens_
] + yystate
;
369 if (0 <= yyr
&& yyr
<= yylast_
&& yycheck_
[yyr
] == yystate
)
370 return yytable_
[yyr
];
372 return yydefgoto_
[yysym
- yyntokens_
];
375 private int yyaction (int yyn
, ref YYStack yystack
, int yylen
)
377 Value yyval
;]b4_locations_if([[
378 Location yyloc
= yylloc_from_stack (yystack
, yylen
);]])[
380 /* If YYLEN is nonzero, implement the default value of the action:
381 `$$ = $1'. Otherwise, use the top of the stack.
383 Otherwise, the following line sets YYVAL to garbage.
384 This behavior is undocumented and Bison
385 users should not rely upon it. */
387 yyval
= yystack
.valueAt (yylen
- 1);
389 yyval
= yystack
.valueAt (0);
391 ]b4_parse_trace_if([[
392 yy_reduce_print (yyn
, yystack
);]])[
400 ]b4_parse_trace_if([[
401 yy_symbol_print ("-> $$ =", to
!SymbolKind (yyr1_
[yyn
]), yyval
]b4_locations_if([, yyloc
])[);]])[
406 /* Shift the result of the reduction. */
407 int yystate
= yyLRGotoState(yystack
.stateAt(0), yyr1_
[yyn
]);
408 yystack
.push (yystate
, yyval
]b4_locations_if([, yyloc
])[);
412 ]b4_parse_trace_if([[
413 /*--------------------------------.
414 | Print this symbol on YYOUTPUT. |
415 `--------------------------------*/
417 private final void yy_symbol_print (string s
, SymbolKind yykind
,
418 ref Value yyval
]b4_locations_if([, ref Location yyloc
])[)
422 File yyo
= yyDebugStream
;
424 yyo
.write(yykind
< yyntokens_ ?
" token " : " nterm ");
425 yyo
.write(format("%s", yykind
));
426 yyo
.write(" ("]b4_locations_if([ ~ yyloc
.toString() ~ ": "])[);
427 ]b4_symbol_actions([printer
])[
432 ]b4_symbol_type_define
[
434 * Parse input from the scanner that was specified at object construction
435 * time. Return whether the end of the input was reached successfully.
437 * @@return <tt>true</tt> if the parsing succeeds. Note that this does not
438 * imply that there were no syntax errors.
442 // Lookahead symbol kind.
443 SymbolKind yytoken
= ]b4_symbol(empty
, kind
)[;
452 /* Error handling. */
454 /// The location where the error started.
457 /// Location of the lookahead.
463 /// Semantic value of the lookahead.
466 bool yyresult
;]b4_lac_if([[
467 // Discard the LAC context in case there still is one left from a
468 // previous invocation.
469 yylacDiscard("init");]])[]b4_parse_trace_if([[
471 yycdebugln ("Starting parse");]])[
474 ]m4_ifdef([b4_initial_action
], [
475 m4_pushdef([b4_at_dollar
], [yylloc
])dnl
476 m4_pushdef([b4_dollar_dollar
], [yylval
])dnl
477 /* User initialization code. */
478 b4_user_initial_action
479 m4_popdef([b4_dollar_dollar
])dnl
480 m4_popdef([b4_at_dollar
])])dnl
482 [ /* Initialize the stack. */
483 yystack
.push (yystate
, yylval
]b4_locations_if([, yylloc
])[);
485 int label
= YYNEWSTATE
;
489 /* New state. Unlike in the C/C++ skeletons, the state is already
490 pushed when we come here. */
491 case YYNEWSTATE
:]b4_parse_trace_if([[
492 yycdebugln (format("Entering state %d", yystate
));
494 yystack
.print (yyDebugStream
);]])[
497 if (yystate
== yyfinal_
)
500 /* Take a decision. First try without lookahead. */
501 yyn
= yypact_
[yystate
];
502 if (yyPactValueIsDefault(yyn
))
508 /* Read a lookahead token. */
509 if (yytoken
== ]b4_symbol(empty
, kind
)[)
510 {]b4_parse_trace_if([[
511 yycdebugln ("Reading a token");]])[
512 Symbol yysymbol
= yylex();
513 yytoken
= yysymbol
.token();
514 yylval
= yysymbol
.value();]b4_locations_if([[
515 yylloc
= yysymbol
.location();]])[
518 /* Token already converted to internal form. */]b4_parse_trace_if([[
519 yy_symbol_print ("Next token is", yytoken
, yylval
]b4_locations_if([, yylloc
])[);]])[
521 if (yytoken
== ]b4_symbol(error
, kind
)[)
523 // The scanner already issued an error message, process directly
524 // to error recovery. But do not keep the error token as
525 // lookahead, it is too special and may lead us to an endless
526 // loop in error recovery. */
527 yytoken
= ]b4_symbol(undef
, kind
)[;]b4_locations_if([[
528 yyerrloc
= yylloc
;]])[
533 /* If the proper action on seeing token YYTOKEN is to reduce or to
534 detect an error, take that action. */
536 if (yyn
< 0 || yylast_
< yyn || yycheck_
[yyn
] != yytoken
) {]b4_lac_if([[
537 if (!yylacEstablish(yystack
, yytoken
))
542 /* <= 0 means reduce or error. */
543 else if ((yyn
= yytable_
[yyn
]) <= 0)
545 if (yyTableValueIsError(yyn
))
546 label
= YYERRLAB
;]b4_lac_if([[
547 else if (!yylacEstablish(yystack
, yytoken
))
548 label
= YYERRLAB
;]])[
557 /* Shift the lookahead token. */]b4_parse_trace_if([[
558 yy_symbol_print ("Shifting", yytoken
, yylval
]b4_locations_if([, yylloc
])[);]])[
560 /* Discard the token being shifted. */
561 yytoken
= ]b4_symbol(empty
, kind
)[;
563 /* Count tokens shifted since error; after three, turn off error
565 if (yyerrstatus_
> 0)
569 yystack
.push (yystate
, yylval
]b4_locations_if([, yylloc
])[);]b4_lac_if([[
570 yylacDiscard("shift");]])[
576 /*-----------------------------------------------------------.
577 | yydefault -- do the default action for the current state. |
578 `-----------------------------------------------------------*/
580 yyn
= yydefact_
[yystate
];
587 /*-----------------------------.
588 | yyreduce -- Do a reduction. |
589 `-----------------------------*/
592 label
= yyaction (yyn
, yystack
, yylen
);
593 yystate
= yystack
.stateAt (0);
596 /*--------------------------------------.
597 | yyerrlab -- here on detecting error. |
598 `--------------------------------------*/
600 /* If not already recovering from an error, report this error. */
601 if (yyerrstatus_
== 0)
604 yyreportSyntaxError(new Context(]b4_lac_if([[this, ]])[yystack
, yytoken
]b4_locations_if([[, yylloc
]])[));
607 yyerrloc
= yylloc
;])[
608 if (yyerrstatus_
== 3)
610 /* If just tried and failed to reuse lookahead token after an
611 * error, discard it. */
613 /* Return failure if at end of input. */
614 if (yytoken
== ]b4_symbol(eof
, [kind
])[)
617 yytoken
= ]b4_symbol(empty
, kind
)[;
620 /* Else will try to reuse lookahead token after shifting the error
625 /*-------------------------------------------------.
626 | errorlab -- error raised explicitly by YYERROR. |
627 `-------------------------------------------------*/
628 case YYERROR
:]b4_locations_if([
629 yyerrloc
= yystack
.locationAt (yylen
- 1);])[
630 /* Do not reclaim the symbols of the rule which action triggered
634 yystate
= yystack
.stateAt (0);
638 /*-------------------------------------------------------------.
639 | yyerrlab1 -- common code for both syntax error and YYERROR. |
640 `-------------------------------------------------------------*/
642 yyerrstatus_
= 3; /* Each real token shifted decrements this. */
644 // Pop stack until we find a state that shifts the error token.
647 yyn
= yypact_
[yystate
];
648 if (!yyPactValueIsDefault(yyn
))
650 yyn
+= ]b4_symbol(error
, kind
)[;
651 if (0 <= yyn
&& yyn
<= yylast_
&& yycheck_
[yyn
] == ]b4_symbol(error
, kind
)[)
659 /* Pop the current state because it cannot handle the error token. */
660 if (yystack
.height
== 1)
663 ]b4_locations_if([ yyerrloc
= yystack
.locationAt (0);])[
665 yystate
= yystack
.stateAt (0);]b4_parse_trace_if([[
667 yystack
.print (yyDebugStream
);]])[
671 /* Muck with the stack to setup for yylloc. */
672 yystack
.push (0, yy_semantic_null
, yylloc
);
673 yystack
.push (0, yy_semantic_null
, yyerrloc
);
674 yyloc
= yylloc_from_stack (yystack
, 2);
677 /* Shift the error token. */]b4_lac_if([[
678 yylacDiscard("error recovery");]])[]b4_parse_trace_if([[
679 yy_symbol_print ("Shifting", to
!SymbolKind (yystos_
[yyn
]), yylval
]b4_locations_if([, yyloc
])[);]])[
681 yystack
.push (yyn
, yylval
]b4_locations_if([, yyloc
])[);
697 case YYRETURN
:]b4_parse_trace_if([[
699 yystack
.print (yyDebugStream
);]])[
704 // Generate an error message.
705 private final void yyreportSyntaxError(Context yyctx
)
706 {]b4_parse_error_bmatch(
708 yylexer
.reportSyntaxError(yyctx
);]],
710 if (yyctx
.getToken() != ]b4_symbol(empty
, kind
)[)
712 // FIXME: This method of building the message is not compatible
713 // with internationalization.
714 immutable int argmax
= 5;
715 SymbolKind
[] yyarg
= new SymbolKind
[argmax
];
716 int yycount
= yysyntaxErrorArguments(yyctx
, yyarg
, argmax
);
717 string res
, yyformat
;
721 yyformat
= YY_("syntax error, unexpected %s");
722 res
= format(yyformat
, yyarg
[0]);
725 yyformat
= YY_("syntax error, unexpected %s, expecting %s");
726 res
= format(yyformat
, yyarg
[0], yyarg
[1]);
729 yyformat
= YY_("syntax error, unexpected %s, expecting %s or %s");
730 res
= format(yyformat
, yyarg
[0], yyarg
[1], yyarg
[2]);
733 yyformat
= YY_("syntax error, unexpected %s, expecting %s or %s or %s");
734 res
= format(yyformat
, yyarg
[0], yyarg
[1], yyarg
[2], yyarg
[3]);
737 yyformat
= YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
738 res
= format(yyformat
, yyarg
[0], yyarg
[1], yyarg
[2], yyarg
[3], yyarg
[4]);
741 res
= YY_("syntax error");
744 yyerror(]b4_locations_if([yyctx
.getLocation(), ])[res
);
747 yyerror(]b4_locations_if([yyctx
.getLocation(), ])[YY_("syntax error"));]])[
750 ]b4_parse_error_bmatch(
752 private int yysyntaxErrorArguments(Context yyctx
, SymbolKind
[] yyarg
, int yyargn
) {
753 /* There are many possibilities here to consider:
754 - If this state is a consistent state with a default action,
755 then the only way this function was invoked is if the
756 default action is an error action. In that case, don't
757 check for expected tokens because there are none.
758 - The only way there can be no lookahead present (in tok) is
759 if this state is a consistent state with a default action.
760 Thus, detecting the absence of a lookahead is sufficient to
761 determine that there is no unexpected or expected token to
762 report. In that case, just report a simple "syntax error".
763 - Don't assume there isn't a lookahead just because this
764 state is a consistent state with a default action. There
765 might have been a previous inconsistent state, consistent
766 state with a non-default action, or user semantic action
767 that manipulated yychar. (However, yychar is currently out
768 of scope during semantic actions.)
769 - Of course, the expected token list depends on states to
770 have correct lookahead information, and it depends on the
771 parser not to perform extra reductions after fetching a
772 lookahead from the scanner and before detecting a syntax
773 error. Thus, state merging (from LALR or IELR) and default
774 reductions corrupt the expected token list. However, the
775 list is correct for canonical LR with one exception: it
776 will still contain any token that will not be accepted due
777 to an error action in a later state.
780 if (yyctx
.getToken() != ]b4_symbol(empty
, kind
)[)
783 yyarg
[yycount
] = yyctx
.getToken();
785 yycount
+= yyctx
.getExpectedTokens(yyarg
, 1, yyargn
);
793 * Information needed to get the list of expected tokens and to forge
794 * a syntax error diagnostic.
796 public static final class Context
798 private ]b4_parser_class
[ yyparser
;]])[
799 private const(YYStack
) yystack
;
800 private SymbolKind yytoken
;]b4_locations_if([[
801 private const(Location
) yylocation
;]])[
803 this(]b4_lac_if([[]b4_parser_class
[ parser
, ]])[YYStack stack
, SymbolKind kind
]b4_locations_if([[, Location loc
]])[)
805 yyparser
= parser
;]])[
807 yytoken
= kind
;]b4_locations_if([[
808 yylocation
= loc
;]])[
811 final SymbolKind
getToken() const
816 final const(Location
) getLocation() const
821 * Put in YYARG at most YYARGN of the expected tokens given the
822 * current YYCTX, and return the number of tokens stored in YYARG. If
823 * YYARG is null, return the number of expected tokens (guaranteed to
824 * be less than YYNTOKENS).
826 int getExpectedTokens(SymbolKind
[] yyarg
, int yyargn
)]b4_lac_if([[]], [[ const]])[
828 return getExpectedTokens(yyarg
, 0, yyargn
);
831 int getExpectedTokens(SymbolKind
[] yyarg
, int yyoffset
, int yyargn
)]b4_lac_if([[]], [[ const]])[
833 int yycount
= yyoffset
;]b4_lac_if([b4_parse_trace_if([[
834 // Execute LAC once. We don't care if it is successful, we
835 // only do it for the sake of debugging output.
837 if (!yyparser
.yylacEstablished
)
838 yyparser
.yylacCheck(yystack
, yytoken
);
840 for (int yyx
= 0; yyx
< yyntokens_
; ++yyx
)
842 SymbolKind yysym
= SymbolKind(yyx
);
843 if (yysym
!= ]b4_symbol(error
, kind
)[
844 && yysym
!= ]b4_symbol(undef
, kind
)[
845 && yyparser
.yylacCheck(yystack
, yysym
))
849 else if (yycount
== yyargn
)
852 yyarg
[yycount
++] = yysym
;
855 int yyn
= yypact_
[this.yystack
.stateAt(0)];
856 if (!yyPactValueIsDefault(yyn
))
858 /* Start YYX at -YYN if negative to avoid negative
859 indexes in YYCHECK. In other words, skip the first
860 -YYN actions for this state because they are default
862 int yyxbegin
= yyn
< 0 ?
-yyn
: 0;
863 /* Stay within bounds of both yycheck and yytname. */
864 int yychecklim
= yylast_
- yyn
+ 1;
865 int yyxend
= yychecklim
< yyntokens_ ? yychecklim
: yyntokens_
;
866 for (int yyx
= yyxbegin
; yyx
< yyxend
; ++yyx
)
867 if (yycheck_
[yyx
+ yyn
] == yyx
&& yyx
!= ]b4_symbol(error
, kind
)[
868 && !yyTableValueIsError(yytable_
[yyx
+ yyn
]))
872 else if (yycount
== yyargn
)
875 yyarg
[yycount
++] = SymbolKind(yyx
);
878 if (yyarg
!is null && yycount
== yyoffset
&& yyoffset
< yyargn
)
879 yyarg
[yyoffset
] = ]b4_symbol(empty
, kind
)[;
880 return yycount
- yyoffset
;
885 /** Check the lookahead yytoken.
886 * \returns true iff the token will be eventually shifted.
888 bool yylacCheck(const YYStack yystack
, SymbolKind yytoken
)
890 // Logically, the yylacStack's lifetime is confined to this function.
891 // Clear it, to get rid of potential left-overs from previous call.
893 // Reduce until we encounter a shift and thereby accept the token.
894 ]b4_parse_trace_if([[
895 yycdebug("LAC: checking lookahead " ~ format("%s", yytoken
) ~ ":");]])[
899 int topState
= (yylacStack
.length
== 0
900 ? yystack
.stateAt(lacTop
)
901 : yylacStack
[$ - 1]);
902 int yyrule
= yypact_
[topState
];
903 if (yyPactValueIsDefault(yyrule
)
904 ||
(yyrule
+= yytoken
) < 0 || yylast_
< yyrule
905 || yycheck_
[yyrule
] != yytoken
)
907 // Use the default action.
908 yyrule
= yydefact_
[+topState
];
910 {]b4_parse_trace_if([[
911 yycdebugln(" Err");]])[
917 // Use the action from yytable.
918 yyrule
= yytable_
[yyrule
];
919 if (yyTableValueIsError(yyrule
))
920 {]b4_parse_trace_if([[
921 yycdebugln(" Err");]])[
925 {]b4_parse_trace_if([[
926 yycdebugln(" S" ~ to
!string(yyrule
));]])[
931 // By now we know we have to simulate a reduce.
932 ]b4_parse_trace_if([[
933 yycdebug(" R" ~ to
!string(yyrule
- 1));]])[
934 // Pop the corresponding number of values from the stack.
936 int yylen
= yyr2_
[yyrule
];
937 // First pop from the LAC stack as many tokens as possible.
938 int lacSize
= cast (int) yylacStack
.length
;
941 yylacStack
.length
-= yylen
;
944 else if (lacSize
!= 0)
949 // Only afterwards look at the main stack.
950 // We simulate popping elements by incrementing lacTop.
953 // Keep topState in sync with the updated stack.
954 topState
= (yylacStack
.length
== 0
955 ? yystack
.stateAt(lacTop
)
956 : yylacStack
[$ - 1]);
957 // Push the resulting state of the reduction.
958 int state
= yyLRGotoState(topState
, yyr1_
[yyrule
]);]b4_parse_trace_if([[
959 yycdebug(" G" ~ to
!string(state
));]])[
961 yylacStack
[$ - 1] = state
;
965 /** Establish the initial context if no initial context currently exists.
966 * \returns true iff the token will be eventually shifted.
968 bool yylacEstablish(YYStack yystack
, SymbolKind yytoken
)
970 /* Establish the initial context for the current lookahead if no initial
971 context is currently established.
973 We define a context as a snapshot of the parser stacks. We define
974 the initial context for a lookahead as the context in which the
975 parser initially examines that lookahead in order to select a
976 syntactic action. Thus, if the lookahead eventually proves
977 syntactically unacceptable (possibly in a later context reached via a
978 series of reductions), the initial context can be used to determine
979 the exact set of tokens that would be syntactically acceptable in the
980 lookahead's place. Moreover, it is the context after which any
981 further semantic actions would be erroneous because they would be
982 determined by a syntactically unacceptable token.
984 yylacEstablish should be invoked when a reduction is about to be
985 performed in an inconsistent state (which, for the purposes of LAC,
986 includes consistent states that don't know they're consistent because
987 their default reductions have been disabled).
989 For parse.lac=full, the implementation of yylacEstablish is as
990 follows. If no initial context is currently established for the
991 current lookahead, then check if that lookahead can eventually be
992 shifted if syntactic actions continue from the current context. */
993 if (yylacEstablished
)
996 {]b4_parse_trace_if([[
997 yycdebugln("LAC: initial context established for " ~ format("%s", yytoken
));]])[
998 yylacEstablished
= true;
999 return yylacCheck(yystack
, yytoken
);
1003 /** Discard any previous initial lookahead context because of event.
1004 * \param event the event which caused the lookahead to be discarded.
1005 * Only used for debbuging output. */
1006 void yylacDiscard(string event
)
1008 /* Discard any previous initial lookahead context because of Event,
1009 which may be a lookahead change or an invalidation of the currently
1010 established initial context for the current lookahead.
1012 The most common example of a lookahead change is a shift. An example
1013 of both cases is syntax error recovery. That is, a syntax error
1014 occurs when the lookahead is syntactically erroneous for the
1015 currently established initial context, so error recovery manipulates
1016 the parser stacks to try to find a new initial context in which the
1017 current lookahead is syntactically acceptable. If it fails to find
1018 such a context, it discards the lookahead. */
1019 if (yylacEstablished
)
1020 {]b4_parse_trace_if([[
1021 yycdebugln("LAC: initial context discarded due to " ~ event
);]])[
1022 yylacEstablished
= false;
1026 /** The stack for LAC.
1027 * Logically, the yylacStack's lifetime is confined to the function
1028 * yylacCheck. We just store it as a member of this class to hold
1029 * on to the memory and to avoid frequent reallocations.
1032 /** Whether an initial LAC context was established. */
1033 bool yylacEstablished
;
1037 * Whether the given <code>yypact_</code> value indicates a defaulted state.
1038 * @@param yyvalue the value to check
1040 private static bool yyPactValueIsDefault(int yyvalue
)
1042 return yyvalue
== yypact_ninf_
;
1046 * Whether the given <code>yytable_</code> value indicates a syntax error.
1047 * @@param yyvalue the value to check
1049 private static bool yyTableValueIsError(int yyvalue
)
1051 return yyvalue
== yytable_ninf_
;
1054 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
1056 private static immutable ]b4_int_type_for([b4_pact
])[ yypact_ninf_
= ]b4_pact_ninf
[;
1058 /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
1059 positive, shift that token. If negative, reduce the rule which
1060 number is the opposite. If YYTABLE_NINF_, syntax error. */
1061 private static immutable ]b4_int_type_for([b4_table
])[ yytable_ninf_
= ]b4_table_ninf
[;
1063 ]b4_parser_tables_define
[
1065 ]b4_parse_trace_if([[
1066 /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
1067 private static immutable ]b4_int_type_for([b4_rline
])[[] yyrline_
=
1072 // Report on the debug stream that the rule yyrule is going to be reduced.
1073 private final void yy_reduce_print (int yyrule
, ref YYStack yystack
)
1078 int yylno
= yyrline_
[yyrule
];
1079 int yynrhs
= yyr2_
[yyrule
];
1080 /* Print the symbols being reduced, and their result. */
1081 yycdebugln (format("Reducing stack by rule %d (line %d):",
1082 yyrule
- 1, yylno
));
1084 /* The symbols being reduced. */
1085 for (int yyi
= 0; yyi
< yynrhs
; yyi
++)
1086 yy_symbol_print (format(" $%d =", yyi
+ 1),
1087 to
!SymbolKind (yystos_
[yystack
.stateAt(yynrhs
- (yyi
+ 1))]),
1088 ]b4_rhs_value(yynrhs
, yyi
+ 1)b4_locations_if([,
1089 b4_rhs_location(yynrhs
, yyi
+ 1)])[);
1093 private static auto yytranslate_ (int t
)
1095 ]b4_api_token_raw_if(
1096 [[ return SymbolKind(t
);]],
1097 [[ /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
1098 immutable ]b4_int_type_for([b4_translate
])[[] translate_table
=
1103 // Last valid token kind.
1104 immutable int code_max
= ]b4_code_max
[;
1107 return ]b4_symbol(eof
, kind
)[;
1108 else if (t
<= code_max
)
1109 return SymbolKind(translate_table
[t
]);
1111 return ]b4_symbol(undef
, kind
)[;]])[
1114 private static immutable int yylast_
= ]b4_last
[;
1115 private static immutable int yynnts_
= ]b4_nterms_number
[;
1116 private static immutable int yyfinal_
= ]b4_final_state_number
[;
1117 private static immutable int yyntokens_
= ]b4_tokens_number
[;
1119 private final struct YYStackElement
{
1121 Value value
;]b4_locations_if(
1122 b4_location_type
[[] location
;])[
1125 private final struct YYStack
{
1126 private YYStackElement
[] stack
= [];
1128 public final ulong height()
1130 return stack
.length
;
1133 public final void push (int state
, Value value
]dnl
1134 b4_locations_if([, ref Location loc
])[)
1136 stack
~= YYStackElement(state
, value
]b4_locations_if([, loc
])[);
1139 public final void pop ()
1144 public final void pop (int num
)
1146 stack
.length
-= num
;
1149 public final int stateAt (int i
) const
1151 return stack
[$-i
-1].state
;
1155 public final ref Location
locationAt (int i
)
1157 return stack
[$-i
-1].location
;
1160 public final ref Value
valueAt (int i
)
1162 return stack
[$-i
-1].value
;
1164 ]b4_parse_trace_if([[
1165 // Print the state stack on the debug stream.
1166 public final void print (File stream
)
1168 stream
.write ("Stack now");
1169 for (int i
= 0; i
< stack
.length
; i
++)
1170 stream
.write (" ", stack
[i
].state
);
1174 ]b4_percent_code_get
[
1176 ]b4_percent_code_get([[epilogue
]])[]dnl