@@ -25,6 +25,38 @@ m4_define([b4_lac_flag],
25
25
[ m4_if ( b4_percent_define_get ( [ [ parse.lac] ] ) ,
26
26
[ none] , [ [ 0] ] , [ [ 1] ] ) ] )
27
27
28
+
29
+ # # --------------- ##
30
+ # # api.push-pull. ##
31
+ # # --------------- ##
32
+
33
+ b4_percent_define_default([ [ api.push-pull] ] , [ [ pull] ] )
34
+ b4_percent_define_check_values([ [ [ [ api.push-pull] ] ,
35
+ [ [ pull] ] , [ [ push] ] , [ [ both] ] ] ] )
36
+
37
+ # Define m4 conditional macros that encode the value
38
+ # of the api.push-pull flag.
39
+ b4_define_flag_if([ pull] ) m4_define ( [ b4_pull_flag] , [ [ 1] ] )
40
+ b4_define_flag_if([ push] ) m4_define ( [ b4_push_flag] , [ [ 1] ] )
41
+ m4_case ( b4_percent_define_get ( [ [ api.push-pull] ] ) ,
42
+ [ pull] , [ m4_define ( [ b4_push_flag] , [ [ 0] ] ) ] ,
43
+ [ push] , [ m4_define ( [ b4_pull_flag] , [ [ 0] ] ) ] )
44
+
45
+ # Define a macro to be true when api.push-pull has the value "both".
46
+ m4_define ( [ b4_both_if] ,[ b4_push_if([ b4_pull_if([ $1 ] ,[ $2 ] )] ,[ $2 ] )] )
47
+
48
+ # Handle BISON_USE_PUSH_FOR_PULL for the test suite. So that push parsing
49
+ # tests function as written, do not let BISON_USE_PUSH_FOR_PULL modify the
50
+ # behavior of Bison at all when push parsing is already requested.
51
+ b4_define_flag_if([ use_push_for_pull] )
52
+ b4_use_push_for_pull_if([
53
+ b4_push_if([ m4_define ( [ b4_use_push_for_pull_flag] , [ [ 0] ] ) ] ,
54
+ [ m4_define ( [ b4_push_flag] , [ [ 1] ] ) ] )] )
55
+
56
+
57
+ # Define a macro to encapsulate the parse state variables. This
58
+ # allows them to be defined either in parse() when doing pull parsing,
59
+ # or as class instance variable when doing push parsing.
28
60
b4_output_begin([ b4_parser_file_name] )
29
61
b4_copyright([ Skeleton implementation for Bison LALR(1) parsers in D] ,
30
62
[ 2007-2012, 2019-2021] )[
@@ -328,6 +360,11 @@ b4_user_union_members
328
360
* Returned by a Bison action in order to stop the parsing process and
329
361
* return failure (<tt>false</tt>). */
330
362
public static immutable int YYABORT = 1;
363
+ ] b4_push_if([
364
+ /**
365
+ * Returned by a Bison action in order to request a new token.
366
+ */
367
+ public static immutable int YYPUSH_MORE = 4;] )[
331
368
332
369
/**
333
370
* Returned by a Bison action in order to start error recovery without
@@ -342,6 +379,8 @@ b4_user_union_members
342
379
private static immutable int YYREDUCE = 6;
343
380
private static immutable int YYERRLAB1 = 7;
344
381
private static immutable int YYRETURN = 8;
382
+ ] b4_push_if([ [ private static immutable int YYGETTOKEN = 9; /* Signify that a new token is expected when doing push-parsing. */] ] )[
383
+
345
384
] b4_locations_if([
346
385
private static immutable YYSemanticType yy_semantic_null;] )[
347
386
private int yyerrstatus_ = 0;
@@ -351,6 +390,32 @@ b4_user_union_members
351
390
yyerrstatus_ = 0;
352
391
}
353
392
393
+ // Lookahead symbol kind.
394
+ SymbolKind yytoken = ] b4_symbol(empty, kind)[ ;
395
+
396
+ /* State. */
397
+ int yyn = 0;
398
+ int yylen = 0;
399
+ int yystate = 0;
400
+
401
+ YYStack yystack;
402
+
403
+ int label = YYNEWSTATE;
404
+
405
+ /* Error handling. */
406
+ ] b4_locations_if([ [
407
+ /// The location where the error started.
408
+ Location yyerrloc;
409
+
410
+ /// Location of the lookahead.
411
+ Location yylloc;
412
+
413
+ /// @@$.
414
+ Location yyloc;] ] )[
415
+
416
+ /// Semantic value of the lookahead.
417
+ Value yylval;
418
+
354
419
/**
355
420
* Whether error recovery is being done. In this state, the parser
356
421
* reads token until it reaches a known state, and then restarts normal
@@ -430,40 +495,34 @@ b4_user_union_members
430
495
}
431
496
] ] )[
432
497
] b4_symbol_type_define[
498
+ ] b4_push_if([ [
499
+ /**
500
+ * Push Parse input from external lexer
501
+ *
502
+ * @@param yyla current Symbol
503
+ *
504
+ * @@return <tt>YYACCEPT, YYABORT, YYPUSH_MORE</tt>
505
+ */
506
+ public int pushParse(Symbol yyla)] ] , [ [
433
507
/**
434
508
* Parse input from the scanner that was specified at object construction
435
509
* time. Return whether the end of the input was reached successfully.
436
510
*
437
511
* @@return <tt>true</tt> if the parsing succeeds. Note that this does not
438
512
* imply that there were no syntax errors.
439
513
*/
440
- public bool parse ()
441
- {
442
- // Lookahead symbol kind.
443
- SymbolKind yytoken = ] b4_symbol(empty, kind)[ ;
444
-
445
- /* State. */
446
- int yyn = 0;
447
- int yylen = 0;
448
- int yystate = 0;
449
-
450
- YYStack yystack;
451
-
452
- /* Error handling. */
453
- ] b4_locations_if([ [
454
- /// The location where the error started.
455
- Location yyerrloc;
456
-
457
- /// Location of the lookahead.
458
- Location yylloc;
459
-
460
- /// @@$.
461
- Location yyloc;] ] )[
462
-
463
- /// Semantic value of the lookahead.
464
- Value yylval;
514
+ public bool parse()] ] )[
515
+ {] b4_push_if([ [
516
+ if (!this.pushParseInitialized)
517
+ {
518
+ pushParseInitialize();
519
+ yyerrstatus_ = 0;
520
+ }
521
+ else
522
+ label = YYGETTOKEN;
465
523
466
- bool yyresult;] b4_lac_if([ [
524
+ bool push_token_consumed = true;
525
+ ] ] , [ [ bool yyresult;] b4_lac_if([ [
467
526
// Discard the LAC context in case there still is one left from a
468
527
// previous invocation.
469
528
yylacDiscard("init");] ] )[ ] b4_parse_trace_if([ [
@@ -482,7 +541,7 @@ m4_popdef([b4_at_dollar])])dnl
482
541
[ /* Initialize the stack. */
483
542
yystack.push (yystate, yylval] b4_locations_if([ , yylloc] )[ );
484
543
485
- int label = YYNEWSTATE;
544
+ label = YYNEWSTATE;] ] ) [
486
545
for (;;)
487
546
final switch (label)
488
547
{
@@ -494,25 +553,38 @@ m4_popdef([b4_at_dollar])])dnl
494
553
yystack.print (yyDebugStream);] ] )[
495
554
496
555
/* Accept? */
497
- if (yystate == yyfinal_)
498
- return true;
556
+ if (yystate == yyfinal_)] b4_push_if([ [
557
+ {
558
+ label = YYACCEPT;
559
+ break;
560
+ }] ] , [ [
561
+ return true;] ] )[
499
562
500
563
/* Take a decision. First try without lookahead. */
501
564
yyn = yypact_[ yystate] ;
502
565
if (yyPactValueIsDefault(yyn))
503
566
{
504
567
label = YYDEFAULT;
505
568
break;
506
- }
569
+ }] b4_push_if([ [
570
+ goto case;
571
+
572
+ case YYGETTOKEN:] ] )[
507
573
508
574
/* Read a lookahead token. */
509
575
if (yytoken == ] b4_symbol(empty, kind)[ )
510
- {] b4_parse_trace_if([ [
511
- yycdebugln ("Reading a token");] ] )[
576
+ {] b4_push_if([ [
577
+ if (!push_token_consumed)
578
+ return YYPUSH_MORE;] ] )[ ] b4_parse_trace_if([ [
579
+ yycdebugln ("Reading a token");] ] )[ ] b4_push_if([ [
580
+ yytoken = yyla.token;
581
+ yylval = yyla.value;] b4_locations_if([ [
582
+ yylloc = yyla.location;] ] )[
583
+ push_token_consumed = false;] ] , [ [
512
584
Symbol yysymbol = yylex();
513
585
yytoken = yysymbol.token();
514
586
yylval = yysymbol.value();] b4_locations_if([ [
515
- yylloc = yysymbol.location();] ] )[
587
+ yylloc = yysymbol.location();] ] )[ ] ] ) [
516
588
}
517
589
518
590
/* Token already converted to internal form. */] b4_parse_trace_if([ [
@@ -611,8 +683,12 @@ m4_popdef([b4_at_dollar])])dnl
611
683
* error, discard it. */
612
684
613
685
/* Return failure if at end of input. */
614
- if (yytoken == ] b4_symbol(eof, [ kind] )[ )
615
- return false;
686
+ if (yytoken == ] b4_symbol(eof, [ kind] )[ )] b4_push_if([ [
687
+ {
688
+ label = YYABORT;
689
+ break;
690
+ }] ] , [ [
691
+ return false;] ] )[
616
692
else
617
693
yytoken = ] b4_symbol(empty, kind)[ ;
618
694
}
@@ -657,16 +733,23 @@ m4_popdef([b4_at_dollar])])dnl
657
733
}
658
734
659
735
/* Pop the current state because it cannot handle the error token. */
660
- if (yystack.height == 1)
661
- return false;
736
+ if (yystack.height == 1)] b4_push_if([ [
737
+ {
738
+ label = YYABORT;
739
+ break;
740
+ }] ] ,[ [
741
+ return false;] ] )[
662
742
663
743
] b4_locations_if([ yyerrloc = yystack.locationAt (0);] )[
664
744
yystack.pop ();
665
745
yystate = yystack.stateAt (0);] b4_parse_trace_if([ [
666
746
if (0 < yydebug)
667
747
yystack.print (yyDebugStream);] ] )[
668
- }
669
-
748
+ }] b4_push_if([ [
749
+ if (label == YYABORT)
750
+ /* Leave the switch. */
751
+ break;
752
+ ] ] )[
670
753
] b4_locations_if([
671
754
/* Muck with the stack to setup for yylloc. */
672
755
yystack.push (0, yy_semantic_null, yylloc);
@@ -683,24 +766,86 @@ m4_popdef([b4_at_dollar])])dnl
683
766
break;
684
767
685
768
/* Accept. */
686
- case YYACCEPT:
769
+ case YYACCEPT:] b4_push_if([ [
770
+ this.pushParseInitialized = false;] b4_parse_trace_if([ [
771
+ if (0 < yydebug)
772
+ yystack.print (yyDebugStream);] ] )[
773
+ return YYACCEPT;] ] , [ [
687
774
yyresult = true;
688
775
label = YYRETURN;
689
- break;
776
+ break;] ] ) [
690
777
691
778
/* Abort. */
692
- case YYABORT:
779
+ case YYABORT:] b4_push_if([ [
780
+ this.pushParseInitialized = false;] b4_parse_trace_if([ [
781
+ if (0 < yydebug)
782
+ yystack.print (yyDebugStream);] ] )[
783
+ return YYABORT;] ] , [ [
693
784
yyresult = false;
694
785
label = YYRETURN;
695
- break;
696
-
697
- case YYRETURN:] b4_parse_trace_if([ [
786
+ break;] ] )[
787
+ ] b4_push_if([ [ ] ] , [ [ ] [ case YYRETURN:] b4_parse_trace_if([ [
698
788
if (0 < yydebug)
699
789
yystack.print (yyDebugStream);] ] )[
700
- return yyresult;
790
+ return yyresult;] ] ) [
701
791
}
792
+ assert(0);
702
793
}
703
794
795
+ ] b4_push_if([ [
796
+ bool pushParseInitialized = false;
797
+
798
+ /**
799
+ * (Re-)Initialize the state of the push parser.
800
+ */
801
+ public void pushParseInitialize()
802
+ {
803
+
804
+ /* Lookahead and lookahead in internal form. */
805
+ this.yytoken = ] b4_symbol(empty, kind)[ ;
806
+
807
+ /* State. */
808
+ this.yyn = 0;
809
+ this.yylen = 0;
810
+ this.yystate = 0;
811
+ destroy(this.yystack);
812
+ this.label = YYNEWSTATE;
813
+ ] b4_lac_if([ [
814
+ destroy(this.yylacStack);
815
+ this.yylacEstablished = false;] ] )[
816
+
817
+ /* Error handling. */
818
+ this.yynerrs_ = 0;
819
+ ] b4_locations_if([
820
+ /* The location where the error started. */
821
+ this.yyerrloc = Location(Position(), Position());
822
+ this.yylloc = Location(Position(), Position());] )[
823
+
824
+ /* Semantic value of the lookahead. */
825
+ //destroy(this.yylval);
826
+
827
+ /* Initialize the stack. */
828
+ yystack.push(this.yystate, this.yylval] b4_locations_if([ , this.yylloc] )[ );
829
+
830
+ this.pushParseInitialized = true;
831
+ }] ] )[ ] b4_both_if([ [
832
+ /**
833
+ * Parse input from the scanner that was specified at object construction
834
+ * time. Return whether the end of the input was reached successfully.
835
+ * This version of parse() is defined only when api.push-push=both.
836
+ *
837
+ * @@return <tt>true</tt> if the parsing succeeds. Note that this does not
838
+ * imply that there were no syntax errors.
839
+ */
840
+ bool parse()
841
+ {
842
+ int status = 0;
843
+ do {
844
+ status = this.pushParse(yylex());
845
+ } while (status == YYPUSH_MORE);
846
+ return status == YYACCEPT;
847
+ }] ] )[
848
+
704
849
// Generate an error message.
705
850
private final void yyreportSyntaxError(Context yyctx)
706
851
{] b4_parse_error_bmatch(
0 commit comments