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