@@ -422,6 +422,152 @@ string treeToString(Location, alias LocationRangeImpl = LocationRangeStartLength
422
422
return app.data;
423
423
}
424
424
425
+ enum PossibleNonterminalTypes
426
+ {
427
+ none = 0 ,
428
+ tree = 1 ,
429
+ string = 2 ,
430
+ array = 4 ,
431
+ all = tree | string | array
432
+ }
433
+
434
+ template NonterminalUnionImpl (alias CreatorInstance)
435
+ {
436
+ struct Union (PossibleNonterminalTypes possibleNonterminalTypes)
437
+ {
438
+ alias Location = CreatorInstance.Location;
439
+ alias LocationRangeImpl = CreatorInstance.LocationRangeImpl;
440
+
441
+ template NonterminalType (SymbolID nonterminalID)
442
+ if ((nonterminalID >= CreatorInstance.startNonterminalID
443
+ && nonterminalID < CreatorInstance.endNonterminalID)
444
+ || nonterminalID == SymbolID.max)
445
+ {
446
+ alias NonterminalType = CreatorInstance.NonterminalType! nonterminalID;
447
+ }
448
+
449
+ union
450
+ {
451
+ static if (possibleNonterminalTypes & PossibleNonterminalTypes.array)
452
+ CreatorInstance.NonterminalArray valueArray;
453
+ static if (possibleNonterminalTypes & PossibleNonterminalTypes.string )
454
+ string valueString;
455
+ static if (possibleNonterminalTypes & PossibleNonterminalTypes.tree)
456
+ CreatorInstance.NonterminalTree valueTree;
457
+ }
458
+
459
+ SymbolID nonterminalID = SymbolID.max;
460
+
461
+ inout (NonterminalType! nonterminalID2) get (SymbolID nonterminalID2)() inout
462
+ in
463
+ {
464
+ assert (nonterminalID2 == nonterminalID, text(nonterminalID2, " " , nonterminalID));
465
+ }
466
+ do
467
+ {
468
+ static if (CreatorInstance.allNonterminals[nonterminalID2 - CreatorInstance.startNonterminalID].flags & NonterminalFlags.array)
469
+ return valueArray;
470
+ else static if (CreatorInstance.allNonterminals[nonterminalID2 - CreatorInstance.startNonterminalID].flags & NonterminalFlags.string )
471
+ return valueString;
472
+ else
473
+ return valueTree;
474
+ }
475
+
476
+ auto get (nonterminalID2s... )() inout if (nonterminalID2s.length >= 2 )
477
+ {
478
+ foreach (nonterminalID2; nonterminalID2s)
479
+ {
480
+ if (nonterminalID2 == nonterminalID)
481
+ return get ! nonterminalID2();
482
+ }
483
+ assert (false );
484
+ }
485
+
486
+ static if (possibleNonterminalTypes & PossibleNonterminalTypes.tree)
487
+ static Union create (SymbolID nonterminalID, CreatorInstance.NonterminalTree tree)
488
+ in (CreatorInstance.isNonterminalTree(nonterminalID))
489
+ {
490
+ Union r;
491
+ r.valueTree = tree;
492
+ r.nonterminalID = nonterminalID;
493
+ return r;
494
+ }
495
+
496
+ static if (possibleNonterminalTypes & PossibleNonterminalTypes.string )
497
+ static Union create (SymbolID nonterminalID, string tree)
498
+ in (CreatorInstance.isNonterminalString(nonterminalID))
499
+ {
500
+ Union r;
501
+ r.valueString = tree;
502
+ r.nonterminalID = nonterminalID;
503
+ return r;
504
+ }
505
+
506
+ static if (possibleNonterminalTypes & PossibleNonterminalTypes.array)
507
+ static Union create (SymbolID nonterminalID, CreatorInstance.NonterminalArray tree)
508
+ in (CreatorInstance.isNonterminalArray(nonterminalID))
509
+ {
510
+ Union r;
511
+ r.valueArray = tree;
512
+ r.nonterminalID = nonterminalID;
513
+ return r;
514
+ }
515
+
516
+ static Union create ()(SymbolID nonterminalID)
517
+ in (nonterminalID >= CreatorInstance.startNonterminalID && nonterminalID < CreatorInstance.endNonterminalID)
518
+ {
519
+ Union r;
520
+ r.nonterminalID = nonterminalID;
521
+ return r;
522
+ }
523
+
524
+ void opAssign (PossibleNonterminalTypes possibleNonterminalTypes2)(
525
+ Union! (possibleNonterminalTypes2) rhs)
526
+ if (possibleNonterminalTypes2 != possibleNonterminalTypes)
527
+ {
528
+ static if ((possibleNonterminalTypes & PossibleNonterminalTypes.tree) && (possibleNonterminalTypes2 & PossibleNonterminalTypes.tree))
529
+ if (CreatorInstance.isNonterminalTree(rhs.nonterminalID))
530
+ {
531
+ valueTree = rhs.valueTree;
532
+ nonterminalID = rhs.nonterminalID;
533
+ return ;
534
+ }
535
+ static if ((possibleNonterminalTypes & PossibleNonterminalTypes.string ) && (possibleNonterminalTypes2 & PossibleNonterminalTypes.string ))
536
+ if (CreatorInstance.isNonterminalString(rhs.nonterminalID))
537
+ {
538
+ valueString = rhs.valueString;
539
+ nonterminalID = rhs.nonterminalID;
540
+ return ;
541
+ }
542
+ static if ((possibleNonterminalTypes & PossibleNonterminalTypes.array) && (possibleNonterminalTypes2 & PossibleNonterminalTypes.array))
543
+ if (CreatorInstance.isNonterminalArray(rhs.nonterminalID))
544
+ {
545
+ valueArray = rhs.valueArray;
546
+ nonterminalID = rhs.nonterminalID;
547
+ return ;
548
+ }
549
+ assert (0 );
550
+ }
551
+ }
552
+
553
+ template Union (alias nonterminalIDs)
554
+ {
555
+ alias Union = Union! (() {
556
+ PossibleNonterminalTypes possibleNonterminalTypes;
557
+ static foreach (n; nonterminalIDs)
558
+ {
559
+ static if (CreatorInstance.allNonterminals[n - CreatorInstance.startNonterminalID].flags & NonterminalFlags.array)
560
+ possibleNonterminalTypes |= PossibleNonterminalTypes.array;
561
+ else static if (CreatorInstance.allNonterminals[n - CreatorInstance.startNonterminalID].flags & NonterminalFlags.string )
562
+ possibleNonterminalTypes |= PossibleNonterminalTypes.string ;
563
+ else
564
+ possibleNonterminalTypes |= PossibleNonterminalTypes.tree;
565
+ }
566
+ return possibleNonterminalTypes;
567
+ }());
568
+ }
569
+ }
570
+
425
571
/**
426
572
Class for creating trees during parsing.
427
573
@@ -432,16 +578,19 @@ Params:
432
578
stored (start + length, start + end, ...).
433
579
*/
434
580
class DynamicParseTreeCreator (alias GrammarModule, Location_,
435
- alias LocationRangeImpl = LocationRangeStartLength)
581
+ alias LocationRangeImpl_ = LocationRangeStartLength)
436
582
{
437
583
alias Location = Location_;
584
+ alias LocationRangeImpl = LocationRangeImpl_;
438
585
alias LocationDiff = typeof (Location.init - Location.init);
439
586
alias allTokens = GrammarModule.allTokens;
440
587
alias allNonterminals = GrammarModule.allNonterminals;
441
588
alias allProductions = GrammarModule.allProductions;
442
589
alias Type = DynamicParseTree! (Location, LocationRangeImpl);
443
590
alias NonterminalArray = DynamicParseTreeTmpArray! (Location,
444
591
LocationRangeImpl);
592
+ alias NonterminalTree = DynamicParseTree! (Location,
593
+ LocationRangeImpl);
445
594
enum startNonterminalID = GrammarModule.startNonterminalID;
446
595
enum endNonterminalID = GrammarModule.endNonterminalID;
447
596
enum startProductionID = GrammarModule.startProductionID;
@@ -454,16 +603,39 @@ class DynamicParseTreeCreator(alias GrammarModule, Location_,
454
603
{
455
604
static if (
456
605
allNonterminals[nonterminalID - startNonterminalID].flags & NonterminalFlags.array)
457
- alias NonterminalType = DynamicParseTreeTmpArray! (Location,
458
- LocationRangeImpl);
606
+ alias NonterminalType = NonterminalArray;
459
607
else static if (
460
608
allNonterminals[nonterminalID - startNonterminalID].flags & NonterminalFlags.string )
461
609
alias NonterminalType = string ;
462
610
/* else static if (allNonterminals[nonterminalID - startNonterminalID].flags == NonterminalFlags.none
463
611
|| allNonterminals[nonterminalID - startNonterminalID].flags == NonterminalFlags.empty)
464
612
alias NonterminalType = typeof(null);*/
465
613
else
466
- alias NonterminalType = DynamicParseTree! (Location, LocationRangeImpl);
614
+ alias NonterminalType = NonterminalTree;
615
+ }
616
+
617
+ static bool isNonterminalTree (SymbolID nonterminalID)
618
+ {
619
+ if (nonterminalID < startNonterminalID || nonterminalID >= endNonterminalID)
620
+ return false ;
621
+ auto flags = allNonterminals[nonterminalID - startNonterminalID].flags;
622
+ return (flags & (NonterminalFlags.array | NonterminalFlags.string )) == 0 ;
623
+ }
624
+
625
+ static bool isNonterminalArray (SymbolID nonterminalID)
626
+ {
627
+ if (nonterminalID < startNonterminalID || nonterminalID >= endNonterminalID)
628
+ return false ;
629
+ auto flags = allNonterminals[nonterminalID - startNonterminalID].flags;
630
+ return (flags & NonterminalFlags.array) != 0 ;
631
+ }
632
+
633
+ static bool isNonterminalString (SymbolID nonterminalID)
634
+ {
635
+ if (nonterminalID < startNonterminalID || nonterminalID >= endNonterminalID)
636
+ return false ;
637
+ auto flags = allNonterminals[nonterminalID - startNonterminalID].flags;
638
+ return (flags & (NonterminalFlags.array | NonterminalFlags.string )) == NonterminalFlags.string ;
467
639
}
468
640
469
641
/**
@@ -484,14 +656,13 @@ class DynamicParseTreeCreator(alias GrammarModule, Location_,
484
656
the parser. The union can allow more nonterminals than necessary,
485
657
which can reduce template bloat.
486
658
*/
487
- alias NonterminalUnion = GenericNonterminalUnion ! (DynamicParseTreeCreator).Union;
659
+ alias NonterminalUnion = NonterminalUnionImpl ! (DynamicParseTreeCreator).Union;
488
660
489
661
/**
490
662
Tagged union of all possible nonterminals, which is used internally by
491
663
the parser.
492
664
*/
493
- alias NonterminalUnionAny = GenericNonterminalUnion! (DynamicParseTreeCreator).Union! (
494
- SymbolID.max, size_t .max);
665
+ alias NonterminalUnionAny = NonterminalUnionImpl! (DynamicParseTreeCreator).Union! (PossibleNonterminalTypes.all);
495
666
496
667
/**
497
668
Create a tree node for one production.
0 commit comments