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