"Fossies" - the Fresh Open Source Software Archive

Member "dmd2/src/druntime/benchmark/gcbench/vdparser.extra/vdc/parser/mod.d" (20 Nov 2020, 24796 Bytes) of package /linux/misc/dmd.2.094.2.linux.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) D source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 // This file is part of Visual D
    2 //
    3 // Visual D integrates the D programming language into Visual Studio
    4 // Copyright (c) 2010-2011 by Rainer Schuetze, All Rights Reserved
    5 //
    6 // Distributed under the Boost Software License, Version 1.0.
    7 // See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt
    8 
    9 module vdc.parser.mod;
   10 
   11 import vdc.util;
   12 import vdc.lexer;
   13 import vdc.parser.engine;
   14 import vdc.parser.decl;
   15 import vdc.parser.expr;
   16 import vdc.parser.misc;
   17 import vdc.parser.aggr;
   18 import vdc.parser.tmpl;
   19 import vdc.parser.stmt;
   20 
   21 import ast = vdc.ast.mod;
   22 
   23 import std.conv;
   24 
   25 ////////////////////////////////////////////////////////////////
   26 
   27 //-- GRAMMAR_BEGIN --
   28 //Module:
   29 //    ModuleDeclaration DeclDefs_opt
   30 //    DeclDefs_opt
   31 //
   32 class Module
   33 {
   34     static Action enter(Parser p)
   35     {
   36         p.pushNode(new ast.Module(p.tok));
   37 
   38         if(p.tok.id == TOK_module)
   39         {
   40             p.pushRecoverState(&recoverModuleDeclaration);
   41 
   42             p.pushState(&shiftModuleDeclaration);
   43             return ModuleDeclaration.enter(p);
   44         }
   45 
   46         if(p.tok.id == TOK_EOF)
   47             return Accept;
   48 
   49         p.pushState(&shiftModuleDeclDefs);
   50         return DeclDefs.enter(p);
   51     }
   52 
   53     static Action shiftModuleDeclaration(Parser p)
   54     {
   55         p.popAppendTopNode!(ast.Module)();
   56         if(p.tok.id == TOK_EOF)
   57             return Accept;
   58 
   59         p.pushState(&shiftModuleDeclDefs);
   60         return DeclDefs.enter(p);
   61     }
   62 
   63     static Action shiftModuleDeclDefs(Parser p)
   64     {
   65         if(p.tok.id != TOK_EOF)
   66         {
   67             // recover by assuming the mismatched braces, trying to add more declarations to the module
   68             p.pushRecoverState(&recoverModuleDeclaration);
   69 
   70             return p.parseError("EOF expected");
   71         }
   72         return Accept;
   73     }
   74 
   75     static Action recoverModuleDeclaration(Parser p)
   76     {
   77         p.pushState(&afterRecover);
   78         return Parser.recoverSemiCurly(p);
   79     }
   80 
   81     static Action recoverDeclDef(Parser p)
   82     {
   83         p.pushState(&afterRecover);
   84             return Parser.recoverSemiCurly(p);
   85     }
   86 
   87     static Action afterRecover(Parser p)
   88     {
   89         if(p.tok.id == TOK_EOF)
   90             return Accept;
   91 
   92         if(p.tok.id == TOK_rcurly)
   93         {
   94             // eat pending '}'
   95             p.pushState(&afterRecover);
   96             return Accept;
   97         }
   98         p.pushState(&shiftModuleDeclDefs);
   99         return DeclDefs.enter(p);
  100     }
  101 }
  102 
  103 //-- GRAMMAR_BEGIN --
  104 //ModuleDeclaration:
  105 //    module ModuleFullyQualifiedName ;
  106 class ModuleDeclaration
  107 {
  108     static Action enter(Parser p)
  109     {
  110         if(p.tok.id != TOK_module)
  111             return p.parseError("module expected");
  112 
  113         p.pushNode(new ast.ModuleDeclaration(p.tok));
  114 
  115         p.pushState(&shiftName);
  116         p.pushState(&ModuleFullyQualifiedName.enter);
  117         return Accept;
  118     }
  119 
  120     static Action shiftName(Parser p)
  121     {
  122         if(p.tok.id != TOK_semicolon)
  123             return p.parseError("semicolon expected");
  124         p.popAppendTopNode!(ast.ModuleDeclaration)();
  125         return Accept;
  126     }
  127 }
  128 
  129 //-- GRAMMAR_BEGIN --
  130 //ModuleFullyQualifiedName:
  131 //    ModuleName
  132 //    Packages . ModuleName
  133 //
  134 //ModuleName:
  135 //    Identifier
  136 //
  137 //Packages:
  138 //    PackageName
  139 //    Packages . PackageName
  140 //
  141 //PackageName:
  142 //    Identifier
  143 class ModuleFullyQualifiedName
  144 {
  145     mixin ListNode!(ast.ModuleFullyQualifiedName, Identifier, TOK_dot);
  146 }
  147 
  148 /* might also be empty, but the grammar reflects this by the _opt suffix where used */
  149 //-- GRAMMAR_BEGIN --
  150 //DeclDefs:
  151 //    DeclDef
  152 //    DeclDef DeclDefs
  153 class DeclDefs
  154 {
  155     enum doNotPopNode = true;
  156 
  157     // does not create new Node, but inserts DeclDef into module or block
  158     static Action enter(Parser p)
  159     {
  160         if(p.tok.id == TOK_rcurly || p.tok.id == TOK_EOF)
  161             return Forward;
  162 
  163         p.pushRecoverState(&recover);
  164         p.pushState(&Parser.keepRecover);   // add a "guard" state to avoid popping recover
  165 
  166         p.pushState(&shiftDeclDef);
  167         return DeclDef.enter(p);
  168     }
  169 
  170     static Action next(Parser p)
  171     {
  172         if(p.tok.id == TOK_rcurly || p.tok.id == TOK_EOF || p.tok.id == TOK_RECOVER)
  173             return Forward;
  174 
  175         p.pushState(&shiftDeclDef);
  176         return DeclDef.enter(p);
  177     }
  178 
  179     static Action shiftDeclDef(Parser p)
  180     {
  181         p.popAppendTopNode();
  182         return next(p);
  183     }
  184 
  185     static Action recover(Parser p)
  186     {
  187         auto node = new ast.ParseRecoverNode(p.tok);
  188         if(p.nodeStack.depth)
  189             node.fulspan.start = p.topNode().fulspan.end; // record span of removed text
  190         p.pushNode(node);
  191         p.pushState(&afterRecover);
  192         return Parser.recoverSemiCurly(p);
  193     }
  194 
  195     static Action afterRecover(Parser p)
  196     {
  197         p.popAppendTopNode!(ast.Node, ast.ParseRecoverNode)();
  198 
  199         p.pushRecoverState(&recover);
  200         p.pushState(&Parser.keepRecover);   // add a "guard" state to avoid popping recover
  201 
  202         return next(p);
  203     }
  204 }
  205 
  206 //-- GRAMMAR_BEGIN --
  207 //DeclDef:
  208 //    AttributeSpecifier
  209 //    PragmaSpecifier
  210 //    ImportDeclaration
  211 //    EnumDeclaration
  212 //    ClassDeclaration
  213 //    InterfaceDeclaration
  214 //    AggregateDeclaration
  215 //    Declaration
  216 //    Constructor
  217 //    Destructor
  218 //    Invariant
  219 //    UnitTest
  220 //    StaticConstructor
  221 //    StaticDestructor
  222 //    SharedStaticConstructor
  223 //    SharedStaticDestructor
  224 //    DebugSpecification
  225 //    VersionSpecification
  226 //    ConditionalDeclaration
  227 //    StaticAssert
  228 //    TemplateDeclaration
  229 //    TemplateMixinDeclaration
  230 //    TemplateMixin
  231 //    MixinDeclaration
  232 //    ClassAllocator
  233 //    ClassDeallocator
  234 //    ;
  235 class DeclDef
  236 {
  237     // does not create new Node, but inserts DeclDef into module or block
  238     static Action enter(Parser p)
  239     {
  240         switch(p.tok.id)
  241         {
  242             case TOK_pragma:
  243                 return Pragma.enter(p);
  244             case TOK_mixin:
  245                 p.pushState(&shiftMixin);
  246                 return Accept;
  247             case TOK_import:
  248                 return ImportDeclaration.enter(p);
  249             case TOK_enum:
  250                 return EnumDeclaration.enter(p);
  251 
  252             case TOK_struct:
  253             case TOK_union:
  254             case TOK_class:
  255             case TOK_interface:
  256                 return AggregateDeclaration.enter(p);
  257 
  258             case TOK_this:
  259                 return Constructor.enter(p);
  260             case TOK_tilde:
  261                 return Destructor.enter(p);
  262             case TOK_invariant:
  263                 return Invariant.enter(p);
  264             case TOK_unittest:
  265                 return Unittest.enter(p);
  266             case TOK_debug:
  267                 return DebugCondOrSpec.enter(p);
  268             case TOK_version:
  269                 return VersionCondOrSpec.enter(p);
  270             case TOK_template:
  271                 return TemplateDeclaration.enter(p);
  272             case TOK_new:
  273                 return ClassAllocator.enter(p);
  274             case TOK_delete:
  275                 return ClassDeallocator.enter(p);
  276 
  277             case TOK_semicolon:
  278                 p.pushNode(new ast.EmptyDeclDef(p.tok));
  279                 return Accept;
  280 
  281             case TOK_static:
  282                 p.pushToken(p.tok);
  283                 p.pushState(&shiftStatic);
  284                 return Accept;
  285 
  286             default:
  287                 if(AttributeSpecifier.tryenter(p) == Accept)
  288                     return Accept;
  289                 return Declaration.enter(p);
  290         }
  291     }
  292 
  293     static Action shiftStatic(Parser p)
  294     {
  295         switch(p.tok.id)
  296         {
  297             case TOK_if: // only after static
  298                 p.popToken();
  299                 return ConditionalDeclaration.enterAfterStatic(p);
  300             case TOK_assert: // only after static
  301                 p.popToken();
  302                 return StaticAssert.enterAfterStatic(p);
  303             default:
  304                 return AttributeSpecifier.enterAfterStatic(p);
  305         }
  306     }
  307 
  308     static Action shiftMixin(Parser p)
  309     {
  310         switch(p.tok.id)
  311         {
  312             case TOK_template:
  313                 return TemplateMixinDeclaration.enterAfterMixin(p);
  314             case TOK_lparen:
  315                 return MixinDeclaration.enterAfterMixin(p);
  316             default:
  317                 return TemplateMixin.enterAfterMixin(p);
  318         }
  319     }
  320 }
  321 
  322 //-- GRAMMAR_BEGIN --
  323 //AttributeSpecifier:
  324 //    Attribute :
  325 //    Attribute DeclarationBlock
  326 //
  327 //Attribute:
  328 //    LinkageAttribute
  329 //    AlignAttribute
  330 //    AttributeOrStorageClass
  331 //    ProtectionAttribute
  332 //    @disable
  333 //    @property
  334 //    @safe
  335 //    @system
  336 //    @trusted
  337 class AttributeSpecifier
  338 {
  339     // no members means "Attribute:"
  340 
  341     static Action enter(Parser p)
  342     {
  343         if(tryenter(p) != Accept)
  344             return p.parseError("attribute specifier expected");
  345         return Accept;
  346     }
  347 
  348     static Action tryenter(Parser p)
  349     {
  350         switch(p.tok.id)
  351         {
  352             case TOK_align:
  353                 p.pushState(&shiftAttribute);
  354                 return AlignAttribute.enter(p);
  355             case TOK_extern:
  356                 p.pushState(&shiftAttribute);
  357                 return LinkageAttribute.enter(p);
  358             case TOK_Identifier:
  359                 if(p.tok.txt[0] != '@')
  360                     return Forward;
  361                 return UserAttributeSpecifier.enter(p);
  362             case TOK_deprecated:
  363                 return UserAttributeSpecifier.enter(p);
  364 
  365             default:
  366                 if(tokenToAnnotation(p.tok.id) == 0 &&
  367                    tokenToProtection(p.tok.id) == 0 &&
  368                    tokenToAttribute(p.tok.id) == 0)
  369                     return Forward;
  370 
  371                 p.pushToken(p.tok);
  372                 p.pushState(&shiftColonOrLcurly);
  373                 return Accept;
  374         }
  375     }
  376 
  377     // assumes attribute on the token stack
  378     static Action enterAfterStatic(Parser p)
  379     {
  380         return shiftColonOrLcurly(p);
  381     }
  382 
  383     static ast.AttributeSpecifier createFromToken(Token tok)
  384     {
  385         TokenId id = tok.id;
  386         ast.AttributeSpecifier n;
  387         Annotation annot = tokenToAnnotation(id);
  388         if(annot == 0)
  389             annot = tokenToProtection(id);
  390         if(annot != 0)
  391         {
  392             n = new ast.AttributeSpecifier(tok);
  393             n.annotation = annot;
  394         }
  395         else
  396         {
  397             Attribute attr = tokenToAttribute(id);
  398             if(attr != 0)
  399             {
  400                 n = new ast.AttributeSpecifier(tok);
  401                 n.attr = attr;
  402             }
  403         }
  404         assert(n);
  405         return n;
  406     }
  407 
  408     static Action shiftColonOrLcurly(Parser p)
  409     {
  410         switch(p.tok.id)
  411         {
  412             case TOK_lparen:
  413                 if(isTypeModifier(p.topToken().id))
  414                     // running into a type instead of an attribute, so switch to Declaration
  415                     return Decl!true.enterAttributeSpecifier(p);
  416                 goto default;
  417             default:
  418                 Token tok = p.popToken();
  419                 auto attr = createFromToken(tok);
  420                 p.pushNode(attr);
  421                 return shiftAttribute(p);
  422         }
  423     }
  424 
  425     static Action shiftAttribute(Parser p)
  426     {
  427         auto attr = p.topNode!(ast.AttributeSpecifier);
  428         switch(p.tok.id)
  429         {
  430             case TOK_colon:
  431                 attr.id = TOK_colon;
  432                 return Accept;
  433 
  434             case TOK_lcurly:
  435                 attr.id = TOK_lcurly;
  436                 p.pushState(&shiftRcurly);
  437                 p.pushState(&DeclDefs.enter);
  438                 p.pushNode(new ast.DeclarationBlock(p.tok));
  439                 return Accept;
  440 
  441             case TOK_Identifier:
  442                 // identifier can be basic type or identifier of an AutoDeclaration
  443                 p.pushToken(p.tok);
  444                 p.pushState(&shiftIdentifier);
  445                 return Accept;
  446 
  447             case TOK_alias:
  448             case TOK_typedef:
  449                 p.pushState(&shiftDeclDef);
  450                 return Declaration.enter(p);
  451 
  452             case TOK_align:
  453                 p.pushState(&shiftDeclDef);
  454                 p.pushState(&shiftAttribute);
  455                 return AlignAttribute.enter(p);
  456             case TOK_extern:
  457                 p.pushState(&shiftDeclDef);
  458                 p.pushState(&shiftAttribute);
  459                 return LinkageAttribute.enter(p);
  460 
  461             case TOK_pragma:
  462             case TOK_mixin:
  463             case TOK_import:
  464             case TOK_enum:
  465             case TOK_struct:
  466             case TOK_union:
  467             case TOK_class:
  468             case TOK_interface:
  469             case TOK_this:
  470             case TOK_tilde:
  471             case TOK_invariant:
  472             case TOK_unittest:
  473             case TOK_debug:
  474             case TOK_version:
  475             case TOK_template:
  476             case TOK_semicolon:
  477             case TOK_static:
  478                 p.pushState(&shiftDeclDef);
  479                 return DeclDef.enter(p);
  480             default:
  481                 if(isTypeModifier(p.tok.id))
  482                 {
  483                     p.pushState(&shiftDeclDef);
  484                     p.pushToken(p.tok);
  485                     p.pushState(&shiftColonOrLcurly);
  486                     return Accept;
  487                 }
  488                 int annot = tokenToAnnotation(p.tok.id) | tokenToProtection(p.tok.id);
  489                 int attrib = tokenToAttribute(p.tok.id);
  490                 if(annot || attrib)
  491                 {
  492                     p.combineAnnotations(attr.annotation, annot);
  493                     p.combineAttributes(attr.attr, attrib);
  494                     p.pushState(&shiftAttribute);
  495                     return Accept;
  496                 }
  497                 p.pushState(&shiftDeclDef);
  498                 return Decl!true.enter(p);
  499         }
  500     }
  501 
  502     static Action shiftRcurly(Parser p)
  503     {
  504         if(p.tok.id != TOK_rcurly)
  505             return p.parseError("closing brace expected for declaration block");
  506 
  507         p.popAppendTopNode!(ast.AttributeSpecifier)();
  508         return Accept;
  509     }
  510 
  511     static Action shiftDeclDef(Parser p)
  512     {
  513         p.popAppendTopNode!(ast.AttributeSpecifier)();
  514         return Forward;
  515     }
  516 
  517     static Action shiftIdentifier(Parser p)
  518     {
  519         switch(p.tok.id)
  520         {
  521             case TOK_assign:
  522                 p.pushState(&shiftDeclDef);
  523                 return Decl!true.enterIdentifier(p);
  524             case TOK_lparen:
  525                 p.pushState(&shiftDeclDef);
  526                 return Decl!true.enterAutoReturn(p);
  527             default:
  528                 p.pushState(&shiftDeclDef);
  529                 return Decl!true.enterTypeIdentifier(p);
  530         }
  531     }
  532 }
  533 
  534 //-- GRAMMAR_BEGIN --
  535 //UserAttributeSpecifier:
  536 //    deprectated
  537 //    @identifier
  538 //    deprecated ( ArgumentList )
  539 //    @identifier ( ArgumentList )
  540 class UserAttributeSpecifier
  541 {
  542     static Action enter(Parser p)
  543     {
  544         switch(p.tok.id)
  545         {
  546             case TOK_deprecated:
  547             case TOK_Identifier:
  548                 auto attr = new ast.UserAttributeSpecifier(p.tok);
  549                 attr.ident = p.tok.txt;
  550                 p.pushNode(attr);
  551                 p.pushState(&shiftIdentifier);
  552                 return Accept;
  553             default:
  554                 return p.parseError("@identifier expected in user attribute");
  555         }
  556     }
  557 
  558     static Action shiftIdentifier(Parser p)
  559     {
  560         switch(p.tok.id)
  561         {
  562             case TOK_lparen:
  563                 p.pushState(&shiftArgumentList);
  564                 return Arguments.enter(p);
  565             default:
  566                 return Forward;
  567         }
  568     }
  569 
  570     static Action shiftArgumentList(Parser p)
  571     {
  572         p.popAppendTopNode!(ast.UserAttributeSpecifier, ast.ArgumentList)();
  573         return Forward;
  574     }
  575 }
  576 
  577 //-- GRAMMAR_BEGIN --
  578 //DeclarationBlock:
  579 //    DeclDef
  580 //    { DeclDefs_opt }
  581 class DeclarationBlock
  582 {
  583     static Action enter(Parser p)
  584     {
  585         switch(p.tok.id)
  586         {
  587             case TOK_lcurly:
  588                 auto decl = new ast.DeclarationBlock(p.tok);
  589                 p.pushNode(decl);
  590                 p.pushState(&shiftLcurly);
  591                 return Accept;
  592             default:
  593                 return DeclDef.enter(p);
  594         }
  595     }
  596     static Action shiftLcurly(Parser p)
  597     {
  598         switch(p.tok.id)
  599         {
  600             case TOK_rcurly:
  601                 return Accept;
  602             default:
  603                 p.pushState(&shiftDeclDefs);
  604                 return DeclDefs.enter(p);
  605         }
  606     }
  607 
  608     static Action shiftDeclDefs(Parser p)
  609     {
  610         switch(p.tok.id)
  611         {
  612             case TOK_rcurly:
  613                 return Accept;
  614             default:
  615                 return p.parseError("'}' expected");
  616         }
  617     }
  618 }
  619 
  620 
  621 //-- GRAMMAR_BEGIN --
  622 //LinkageAttribute:
  623 //    extern ( LinkageType )
  624 //
  625 //LinkageType:
  626 //    "C"
  627 //    "C" ++
  628 //    "D"
  629 //    "Windows"
  630 //    "Pascal"
  631 //    "System"
  632 class LinkageAttribute
  633 {
  634     static Action enter(Parser p)
  635     {
  636         if(p.tok.id != TOK_extern)
  637             return p.parseError("extern expected");
  638         p.pushState(&shiftLparen);
  639         return Accept;
  640     }
  641 
  642     static Action shiftLparen(Parser p)
  643     {
  644         switch(p.tok.id)
  645         {
  646             case TOK_lparen:
  647                 p.pushNode(new ast.LinkageAttribute(p.tok));
  648                 p.pushState(&shiftLinkageType);
  649                 return Accept;
  650             default:
  651                 auto attr = new ast.AttributeSpecifier(p.tok);
  652                 attr.attr = Attr_Extern;
  653                 p.pushNode(attr);
  654                 return Forward;
  655         }
  656     }
  657 
  658     static Action shiftLinkageType(Parser p)
  659     {
  660         Attribute attr = tokenToLinkageType(p.tok);
  661         if(attr == 0)
  662             return p.parseError("linkage type expected in extern");
  663         p.topNode!(ast.LinkageAttribute)().attr = attr;
  664 
  665         p.pushState(&shiftRParen);
  666         return Accept;
  667     }
  668 
  669     static Action shiftRParen(Parser p)
  670     {
  671         assert(cast(ast.LinkageAttribute)p.topNode());
  672         if(p.tok.id == TOK_rparen)
  673             return Accept;
  674 
  675         if(p.topNode().attr != Attr_ExternC || p.tok.id != TOK_plusplus)
  676             return p.parseError("closing parenthesis expected after linkage type");
  677 
  678         p.topNode().attr = Attr_ExternCPP;
  679         p.pushState(&shiftRParen);
  680         return Accept;
  681     }
  682 }
  683 
  684 Attribute tokenToLinkageType(Token tok)
  685 {
  686     if(tok.id != TOK_Identifier)
  687         return 0;
  688 
  689     switch(tok.txt)
  690     {
  691         case "C":       return Attr_ExternC;
  692         case "D":       return Attr_ExternD;
  693         case "Windows": return Attr_ExternWindows;
  694         case "Pascal":  return Attr_ExternPascal;
  695         case "System":  return Attr_ExternSystem;
  696         default:        return 0;
  697     }
  698 }
  699 
  700 //-- GRAMMAR_BEGIN --
  701 //AlignAttribute:
  702 //    align
  703 //    align ( Integer )
  704 class AlignAttribute
  705 {
  706     static Action enter(Parser p)
  707     {
  708         if(p.tok.id != TOK_align)
  709             return p.parseError("align expected");
  710 
  711         p.pushNode(new ast.AlignAttribute(p.tok));
  712         p.pushState(&shiftLparen);
  713         return Accept;
  714     }
  715 
  716     static Action shiftLparen(Parser p)
  717     {
  718         if(p.tok.id != TOK_lparen)
  719             return Forward;
  720 
  721         p.pushState(&shiftInteger);
  722         return Accept;
  723     }
  724 
  725     static Action shiftInteger(Parser p)
  726     {
  727         if(p.tok.id != TOK_IntegerLiteral)
  728             return p.parseError("integer expected in align");
  729         int algn = parse!int(p.tok.txt);
  730         Attribute attr = alignmentToAttribute(algn);
  731         if(attr == 0)
  732             return p.parseError("alignment not supported: " ~ p.tok.txt);
  733 
  734         p.topNode!(ast.AlignAttribute)().attr = attr;
  735         p.pushState(&shiftRParen);
  736         return Accept;
  737     }
  738 
  739     static Action shiftRParen(Parser p)
  740     {
  741         assert(cast(ast.AlignAttribute)p.topNode());
  742         if(p.tok.id != TOK_rparen)
  743             return p.parseError("closing parenthesis expected after align");
  744         return Accept;
  745     }
  746 }
  747 
  748 Attribute alignmentToAttribute(int algn)
  749 {
  750     switch(algn)
  751     {
  752         case 1:  return Attr_Align1;
  753         case 2:  return Attr_Align2;
  754         case 4:  return Attr_Align4;
  755         case 8:  return Attr_Align8;
  756         case 16: return Attr_Align16;
  757         default: return 0;
  758     }
  759 }
  760 
  761 //-- GRAMMAR_BEGIN --
  762 //ProtectionAttribute:
  763 //    private
  764 //    package
  765 //    protected
  766 //    public
  767 //    export
  768 
  769 //PragmaSpecifier:
  770 //    Pragma DeclDef
  771 //Pragma:
  772 //    pragma ( Identifier )
  773 //    pragma ( Identifier , TemplateArgumentList )
  774 class Pragma
  775 {
  776     static Action enter(Parser p)
  777     {
  778         if(p.tok.id != TOK_pragma)
  779             return p.parseError("pragma expected");
  780 
  781         p.pushNode(new ast.Pragma(p.tok));
  782         p.pushState(&shiftLparen);
  783         return Accept;
  784     }
  785 
  786     static Action shiftLparen(Parser p)
  787     {
  788         if(p.tok.id != TOK_lparen)
  789             return Forward;
  790 
  791         p.pushState(&shiftIdentifier);
  792         return Accept;
  793     }
  794 
  795     static Action shiftIdentifier(Parser p)
  796     {
  797         if(p.tok.id != TOK_Identifier)
  798             return p.parseError("integer expected in align");
  799 
  800         p.topNode!(ast.Pragma)().ident = p.tok.txt;
  801 
  802         p.pushState(&shiftCommaOrRParen);
  803         return Accept;
  804     }
  805 
  806     static Action shiftCommaOrRParen(Parser p)
  807     {
  808         if(p.tok.id == TOK_comma)
  809         {
  810             p.pushState(&shiftArgumentList);
  811             p.pushState(&TemplateArgumentList.enter);
  812             return Accept;
  813         }
  814         return shiftRParen(p);
  815     }
  816 
  817     static Action shiftRParen(Parser p)
  818     {
  819         assert(cast(ast.Pragma)p.topNode());
  820         if(p.tok.id != TOK_rparen)
  821             return p.parseError("closing parenthesis expected for pragma");
  822         return Accept;
  823     }
  824 
  825     static Action shiftArgumentList(Parser p)
  826     {
  827         p.popAppendTopNode!(ast.Pragma)();
  828         return shiftRParen(p);
  829     }
  830 }
  831 
  832 
  833 //-- GRAMMAR_BEGIN --
  834 //ImportDeclaration:
  835 //    import ImportList ;
  836 class ImportDeclaration
  837 {
  838     mixin SequenceNode!(ast.ImportDeclaration, TOK_import, ImportList, TOK_semicolon);
  839 }
  840 
  841 //-- GRAMMAR_BEGIN --
  842 //ImportList:
  843 //    Import
  844 //    ImportBindings
  845 //    Import , ImportList
  846 //
  847 //ImportBindings:
  848 //    Import : ImportBindList
  849 
  850 class ImportList
  851 {
  852     static Action enter(Parser p)
  853     {
  854         p.pushNode(new ast.ImportList(p.tok));
  855         p.pushState(&shiftImport);
  856         return Import.enter(p);
  857     }
  858 
  859     static Action shiftImport(Parser p)
  860     {
  861         if(p.tok.id == TOK_colon)
  862         {
  863             p.pushState(&shiftImportBindList);
  864             p.pushState(&ImportBindList.enter);
  865             return Accept;
  866         }
  867         p.popAppendTopNode!(ast.ImportList)();
  868 
  869         if(p.tok.id == TOK_comma)
  870         {
  871             p.pushState(&shiftImport);
  872             p.pushState(&Import.enter);
  873             return Accept;
  874         }
  875         return Forward;
  876     }
  877 
  878     static Action shiftImportBindList(Parser p)
  879     {
  880         p.popAppendTopNode!(ast.Import)();
  881         p.popAppendTopNode!(ast.ImportList)();
  882         return Forward;
  883     }
  884 }
  885 
  886 //-- GRAMMAR_BEGIN --
  887 //Import:
  888 //    ModuleFullyQualifiedName
  889 //    ModuleAliasIdentifier = ModuleFullyQualifiedName
  890 //
  891 //ModuleAliasIdentifier:
  892 //    Identifier
  893 class Import
  894 {
  895     static Action enter(Parser p)
  896     {
  897         if(p.tok.id != TOK_Identifier)
  898             return p.parseError("identifier expected in import");
  899 
  900         p.pushToken(p.tok);
  901         p.pushNode(new ast.Import(p.tok));
  902         p.pushState(&shiftIdentifier);
  903         return Accept;
  904     }
  905 
  906     static Action shiftIdentifier(Parser p)
  907     {
  908         p.pushState(&shiftFullyQualifiedName);
  909 
  910         if(p.tok.id == TOK_assign)
  911         {
  912             p.topNode!(ast.Import)().aliasIdent = p.popToken().txt;
  913             p.pushState(&ModuleFullyQualifiedName.enter);
  914             return Accept;
  915         }
  916 
  917         // delegate into ModuleFullyQualifiedName
  918         p.pushNode(new ast.ModuleFullyQualifiedName(p.tok));
  919         auto id = new ast.Identifier(p.popToken());
  920         p.pushNode(id);
  921         return ModuleFullyQualifiedName.shift(p);
  922     }
  923 
  924     static Action shiftFullyQualifiedName(Parser p)
  925     {
  926         p.popAppendTopNode!(ast.Import)();
  927         return Forward;
  928     }
  929 }
  930 
  931 //-- GRAMMAR_BEGIN --
  932 //ImportBindList:
  933 //    ImportBind
  934 //    ImportBind , ImportBindList
  935 class ImportBindList
  936 {
  937     mixin ListNode!(ast.ImportBindList, ImportBind, TOK_comma);
  938 }
  939 
  940 
  941 //-- GRAMMAR_BEGIN --
  942 //ImportBind:
  943 //    Identifier
  944 //    Identifier = Identifier
  945 class ImportBind
  946 {
  947     mixin OptionalNode!(ast.ImportBind, Identifier, TOK_assign, Identifier);
  948 }
  949 
  950 //-- GRAMMAR_BEGIN --
  951 //MixinDeclaration:
  952 //    mixin ( AssignExpression ) ;
  953 class MixinDeclaration
  954 {
  955     mixin SequenceNode!(ast.MixinDeclaration, TOK_mixin, TOK_lparen, AssignExpression, TOK_rparen, TOK_semicolon);
  956 
  957     static Action enterAfterMixin(Parser p)
  958     {
  959         p.pushNode(new ast.MixinDeclaration(p.tok));
  960         return shift1.shift(p);
  961     }
  962 }
  963 
  964 //-- GRAMMAR_BEGIN --
  965 //Unittest:
  966 //    unittest BlockStatement
  967 class Unittest
  968 {
  969     mixin SequenceNode!(ast.Unittest, TOK_unittest, BlockStatement);
  970 }