diff --git a/std/d/ast.d b/std/d/ast.d index 111fbaf..775801f 100755 --- a/std/d/ast.d +++ b/std/d/ast.d @@ -251,9 +251,9 @@ class AddExpression : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */TokenType operator; - /** */AddExpression left; - /** */MulExpression right; + /** */ TokenType operator; + /** */ AddExpression left; + /** */ MulExpression right; } /// @@ -261,9 +261,9 @@ class AliasDeclaration : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */Type type; - /** */Declarator declarator; - /** */AliasInitializer[] initializations; + /** */ Type type; + /** */ Declarator declarator; + /** */ AliasInitializer[] initializations; } /// @@ -271,8 +271,8 @@ class AliasInitializer : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */Token identifier; - /** */Type type; + /** */ Token identifier; + /** */ Type type; } /// @@ -280,7 +280,7 @@ class AliasThisDeclaration : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */Token identifier; + /** */ Token identifier; } /// @@ -288,7 +288,7 @@ class AlignAttribute : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */Token intLiteral; + /** */ Token intLiteral; } /// @@ -296,8 +296,8 @@ class AndAndExpression : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */AndAndExpression left; - /** */OrExpression right; + /** */ AndAndExpression left; + /** */ OrExpression right; } /// @@ -305,8 +305,8 @@ class AndExpression : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */AndExpression andExpression; - /** */ShiftExpression shiftExpression; + /** */ AndExpression left; + /** */ CmpExpression right; } /// @@ -314,7 +314,7 @@ class ArgumentList : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */AssignExpression[] arguments; + /** */ AssignExpression[] arguments; } /// @@ -322,7 +322,7 @@ class Arguments : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */ArgumentList argumentList; + /** */ ArgumentList argumentList; } /// @@ -330,7 +330,7 @@ class ArrayInitializer : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */ArrayMemberInitialization[] arrayMemberInitializations; + /** */ ArrayMemberInitialization[] arrayMemberInitializations; } /// @@ -338,7 +338,7 @@ class ArrayLiteral : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */ArgumentList argumentList; + /** */ ArgumentList argumentList; } /// @@ -346,8 +346,8 @@ class ArrayMemberInitialization : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */AssignExpression assignExpression; - /** */NonVoidInitializer nonVoidInitializer; + /** */ AssignExpression assignExpression; + /** */ NonVoidInitializer nonVoidInitializer; } /// @@ -355,9 +355,9 @@ class AsmAddExp : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */Token operator; - /** */AsmMulExp left; - /** */AsmMulExp right; + /** */ TokenType operator; + /** */ AsmAddExp left; + /** */ AsmMulExp right; } /// @@ -365,8 +365,8 @@ class AsmAndExp : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */AsmEqualExp left; - /** */AsmEqualExp right; + /** */ AsmEqualExp left; + /** */ AsmEqualExp right; } /// @@ -374,9 +374,9 @@ class AsmBrExp : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */AsmBrExp asmBrExp; - /** */AsmEqualExp asmEqualExp; - /** */AsmUnaExp asmUnaExp; + /** */ AsmBrExp asmBrExp; + /** */ AsmEqualExp asmEqualExp; + /** */ AsmUnaExp asmUnaExp; } /// @@ -384,9 +384,9 @@ class AsmEqualExp : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */AsmRelExp left; - /** */AsmRelExp right; - /** */Token operator; + /** */ AsmRelExp left; + /** */ AsmRelExp right; + /** */ Token operator; } /// @@ -394,9 +394,9 @@ class AsmExp : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */AsmLogOrExp left; - /** */AsmExp middle; - /** */AsmExp right; + /** */ AsmLogOrExp left; + /** */ AsmExp middle; + /** */ AsmExp right; } /// @@ -404,10 +404,10 @@ class AsmInstruction : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */Token identifierOrIntegerOrOpcode; - /** */bool hasAlign; - /** */AsmExp asmExp; - /** */Operands operands; + /** */ Token identifierOrIntegerOrOpcode; + /** */ bool hasAlign; + /** */ AsmExp asmExp; + /** */ Operands operands; } /// @@ -415,8 +415,8 @@ class AsmLogAndExp : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */AsmOrExp left; - /** */AsmOrExp right; + /** */ AsmOrExp left; + /** */ AsmOrExp right; } /// @@ -424,8 +424,8 @@ class AsmLogOrExp : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */AsmLogAndExp left; - /** */AsmLogAndExp right; + /** */ AsmLogAndExp left; + /** */ AsmLogAndExp right; } /// @@ -433,9 +433,10 @@ class AsmMulExp : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */AsmBrExp left; - /** */AsmBrExp right; - /** */Token operator; + /** */ TokenType operator; + /** */ AsmMulExp left; + /** */ AsmBrExp right; + } /// @@ -443,8 +444,8 @@ class AsmOrExp : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */AsmXorExp left; - /** */AsmXorExp right; + /** */ AsmXorExp left; + /** */ AsmXorExp right; } /// @@ -452,9 +453,9 @@ class AsmPrimaryExp : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */IdentifierChain identifierChain; - /** */Register register; - /** */Token token; + /** */ IdentifierChain identifierChain; + /** */ Register register; + /** */ Token token; } /// @@ -462,9 +463,9 @@ class AsmRelExp : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */AsmShiftExp left; - /** */AsmShiftExp right; - /** */Token operator; + /** */ AsmShiftExp left; + /** */ AsmShiftExp right; + /** */ Token operator; } /// @@ -472,9 +473,9 @@ class AsmShiftExp : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */AsmAddExp left; - /** */AsmAddExp right; - /** */Token operator; + /** */ AsmAddExp left; + /** */ AsmAddExp right; + /** */ Token operator; } /// @@ -482,7 +483,7 @@ class AsmStatement : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */AsmInstruction[] asmInstructions; + /** */ AsmInstruction[] asmInstructions; } /// @@ -490,8 +491,8 @@ class AsmTypePrefix : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */Token left; - /** */Token right; + /** */ Token left; + /** */ Token right; } /// @@ -499,11 +500,11 @@ class AsmUnaExp : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */AsmTypePrefix asmTypePrefix; - /** */AsmExp asmExp; - /** */Token prefix; - /** */AsmPrimaryExp asmPrimaryExp; - /** */AsmUnaExp asmUnaExp; + /** */ AsmTypePrefix asmTypePrefix; + /** */ AsmExp asmExp; + /** */ Token prefix; + /** */ AsmPrimaryExp asmPrimaryExp; + /** */ AsmUnaExp asmUnaExp; } /// @@ -511,8 +512,8 @@ class AsmXorExp : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */AsmAndExp left; - /** */AsmAndExp right; + /** */ AsmAndExp left; + /** */ AsmAndExp right; } /// @@ -520,8 +521,8 @@ class AssertExpression : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */AssignExpression assertion; - /** */AssignExpression message; + /** */ AssignExpression assertion; + /** */ AssignExpression message; } /// @@ -529,7 +530,7 @@ class AssertStatement : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */AssertExpression assertExpression; + /** */ AssertExpression assertExpression; } /// @@ -537,9 +538,9 @@ class AssignExpression : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */TernaryExpression ternaryExpression; - /** */AssignExpression assignExpression; - /** */TokenType operator; + /** */ TernaryExpression ternaryExpression; + /** */ AssignExpression assignExpression; + /** */ TokenType operator; } /// @@ -547,11 +548,11 @@ class AssignStatement : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */PreIncDecExpression preIncDecExpression; - /** */PostIncDecExpression postIncDecExpression; - /** */UnaryExpression[] unaryExpressions; - /** */AssignExpression[] assignExpressions; - /** */TokenType[] assignOperators; + /** */ PreIncDecExpression preIncDecExpression; + /** */ PostIncDecExpression postIncDecExpression; + /** */ UnaryExpression[] unaryExpressions; + /** */ AssignExpression[] assignExpressions; + /** */ TokenType[] assignOperators; } /// @@ -559,7 +560,7 @@ class AssocArrayLiteral : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */KeyValuePairs keyValuePairs; + /** */ KeyValuePairs keyValuePairs; } /// @@ -567,9 +568,9 @@ class AtAttribute : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */FunctionCallExpression functionCallExpression; - /** */ArgumentList argumentList; - /** */Token identifier; + /** */ FunctionCallExpression functionCallExpression; + /** */ ArgumentList argumentList; + /** */ Token identifier; } /// @@ -586,8 +587,8 @@ public: visitor.visit(dec); } } - /** */Attribute attribute; - /** */Declaration[] declarations; + /** */ Attribute attribute; + /** */ Declaration[] declarations; } /// @@ -595,12 +596,12 @@ class Attribute : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */LinkageAttribute linkageAttribute; - /** */AlignAttribute alignAttribute; - /** */PragmaExpression pragmaExpression; - /** */Deprecated deprecated_; - /** */AtAttribute atAttribute; - /** */TokenType attribute; + /** */ LinkageAttribute linkageAttribute; + /** */ AlignAttribute alignAttribute; + /** */ PragmaExpression pragmaExpression; + /** */ Deprecated deprecated_; + /** */ AtAttribute atAttribute; + /** */ TokenType attribute; } /// @@ -608,9 +609,9 @@ class AutoDeclaration : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */StorageClass storageClass; - /** */Token[] identifiers; - /** */Initializer[] initializers; + /** */ StorageClass storageClass; + /** */ Token[] identifiers; + /** */ Initializer[] initializers; } /// @@ -618,7 +619,7 @@ class BlockStatement : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */DeclarationsAndStatements declarationsAndStatements; + /** */ DeclarationsAndStatements declarationsAndStatements; } /// @@ -626,7 +627,7 @@ class BodyStatement : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */BlockStatement blockStatement; + /** */ BlockStatement blockStatement; } /// @@ -660,7 +661,7 @@ class BasicType : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */TokenType type; + /** */ TokenType type; } /// @@ -668,9 +669,9 @@ class CaseRangeStatement : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */AssignExpression low; - /** */AssignExpression high; - /** */DeclarationsAndStatements declarationsAndStatements; + /** */ AssignExpression low; + /** */ AssignExpression high; + /** */ DeclarationsAndStatements declarationsAndStatements; } /// @@ -678,8 +679,8 @@ class CaseStatement: ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */ArgumentList argumentList; - /** */DeclarationsAndStatements declarationsAndStatements; + /** */ ArgumentList argumentList; + /** */ DeclarationsAndStatements declarationsAndStatements; } /// @@ -687,9 +688,9 @@ class CastExpression: ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */Type type; - /** */CastQualifier castQualifier; - /** */UnaryExpression unaryExpression; + /** */ Type type; + /** */ CastQualifier castQualifier; + /** */ UnaryExpression unaryExpression; } /// @@ -697,9 +698,9 @@ class CastQualifier: ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */TokenType first; - /** */TokenType second; - /** */bool hasSecond; + /** */ TokenType first; + /** */ TokenType second; + /** */ bool hasSecond; } /// @@ -758,9 +759,9 @@ class CompileCondition : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */VersionCondition versionCondition; - /** */DebugCondition debugCondition; - /** */StaticIfCondition staticIfCondition; + /** */ VersionCondition versionCondition; + /** */ DebugCondition debugCondition; + /** */ StaticIfCondition staticIfCondition; } /// @@ -768,9 +769,9 @@ class ConditionalDeclaration : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */CompileCondition compileCondition; - /** */Declaration[] trueDeclarations; - /** */Declaration[] falseDeclarations; + /** */ CompileCondition compileCondition; + /** */ Declaration[] trueDeclarations; + /** */ Declaration[] falseDeclarations; } /// @@ -778,9 +779,9 @@ class ConditionalStatement : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */CompileCondition compileCondition; - /** */StatementNoCaseNoDefault trueStatement; - /** */StatementNoCaseNoDefault falseStatement; + /** */ CompileCondition compileCondition; + /** */ StatementNoCaseNoDefault trueStatement; + /** */ StatementNoCaseNoDefault falseStatement; } /// @@ -788,7 +789,7 @@ class Constraint : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */Expression expression; + /** */ Expression expression; } /// @@ -796,8 +797,8 @@ class Constructor : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */Parameters parameters; - /** */FunctionBody functionBody; + /** */ Parameters parameters; + /** */ FunctionBody functionBody; } /// @@ -991,7 +992,9 @@ class EqualExpression : ASTNode { public: mixin(DEFAULT_ACCEPT); - mixin(SHIFT_SHIFT_BODY); + /** */ TokenType operator; + /** */ ShiftExpression left; + /** */ ShiftExpression right; } /// @@ -999,7 +1002,7 @@ class Expression : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */ AssignExpression[] assignExpressions; + /** */ AssignExpression[] items; } /// @@ -1140,8 +1143,7 @@ class GotoStatement : ASTNode public: mixin(DEFAULT_ACCEPT); /** */ Expression expression; - /** */ Token identifier; - /** */ bool isDefault; + /** */ Token token; } /// @@ -1182,7 +1184,9 @@ class IdentityExpression : ASTNode { public: mixin(DEFAULT_ACCEPT); - mixin(SHIFT_SHIFT_BODY); + /** */ bool negated; + /** */ ShiftExpression left; + /** */ ShiftExpression right; } /// @@ -1320,7 +1324,8 @@ class KeyValuePair : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */ KeyValuePair[] keyValuePairs; + /** */ AssignExpression key; + /** */ AssignExpression value; } /// @@ -1328,8 +1333,7 @@ class KeyValuePairs : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */ AssignExpression key; - /** */ AssignExpression value; + /** */ KeyValuePair[] keyValuePairs; } /// @@ -1433,8 +1437,8 @@ class MulExpression : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */ Token operator; - /** */ UnaryExpression left; + /** */ TokenType operator; + /** */ MulExpression left; /** */ UnaryExpression right; } @@ -1445,10 +1449,8 @@ public: mixin(DEFAULT_ACCEPT); /** */ Arguments allocatorArguments; /** */ Arguments constructorArguments; - /** */ IdentifierList identifierList; - /** */ ClassBody /// -classBody; - + /** */ BaseClassList baseClassList; + /** */ ClassBody classBody; } /// @@ -1541,8 +1543,8 @@ class OrExpression : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */ XorExpression xorExpression; - /** */ OrExpression orExpression; + /** */ OrExpression left; + /** */ XorExpression right; } /// @@ -1550,8 +1552,8 @@ class OrOrExpression : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */ OrOrExpression orOrExpression; - /** */ AndAndExpression andAndExpression; + /** */ OrOrExpression left; + /** */ AndAndExpression right; } /// @@ -1614,8 +1616,8 @@ class PowExpression : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */ UnaryExpression unaryExpression; - /** */ PowExpression powExpression; + /** */ PowExpression left; + /** */ UnaryExpression right; } /// @@ -1650,20 +1652,19 @@ class PrimaryExpression : ASTNode public: mixin(DEFAULT_ACCEPT); /** */ Token primary; - /** */ bool hasDot; - IdentifierOrTemplateInstance identifierOrTemplateInstance; - Type type; - TypeofExpression typeofExpression; - TypeidExpression typeidExpression; - ArrayLiteral arrayLiteral; - AssocArrayLiteral assocArrayLiteral; - Expression expression; - IsExpression isExpression; - LambdaExpression lambdaExpression; - FunctionLiteralExpression functionLiteralExpression; - TraitsExpression traitsExpression; - MixinExpression mixinExpression; - ImportExpression importExpression; + /** */ IdentifierOrTemplateInstance identifierOrTemplateInstance; + /** */ Type type; + /** */ TypeofExpression typeofExpression; + /** */ TypeidExpression typeidExpression; + /** */ ArrayLiteral arrayLiteral; + /** */ AssocArrayLiteral assocArrayLiteral; + /** */ Expression expression; + /** */ IsExpression isExpression; + /** */ LambdaExpression lambdaExpression; + /** */ FunctionLiteralExpression functionLiteralExpression; + /** */ TraitsExpression traitsExpression; + /** */ MixinExpression mixinExpression; + /** */ ImportExpression importExpression; } /// @@ -1681,7 +1682,9 @@ class RelExpression : ASTNode { public: mixin(DEFAULT_ACCEPT); - mixin(SHIFT_SHIFT_BODY); + /** */ TokenType operator; + /** */ RelExpression left; + /** */ ShiftExpression right; } /// @@ -1722,9 +1725,9 @@ class ShiftExpression : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */ AddExpression addExpression; - /** */ ShiftExpression shiftExpression; - /** */ Token operator; + /** */ TokenType operator; + /** */ ShiftExpression left; + /** */ AddExpression right; } /// diff --git a/std/d/lexer.d b/std/d/lexer.d index 3a187ef..d12faad 100755 --- a/std/d/lexer.d +++ b/std/d/lexer.d @@ -2220,7 +2220,7 @@ private: // For now a private helper that is tailored to the way lexer works // hides away forwardness of range by buffering -// RA-version is strightforward thin wrapping +// random-access version is a strightforward thin wrapping // ATM it is byte-oriented private struct LexSource(R) if(isForwardRange!R && !isRandomAccessRange!R) @@ -3038,21 +3038,20 @@ struct StringCache index = new Slot*[startSize]; } - string get(R)(R range) - if(isRandomAccessRange!R - && is(Unqual!(ElementType!R) : const(ubyte))) + string get(R)(R range) if (isRandomAccessRange!R + && is(Unqual!(ElementType!R) : const(ubyte))) { uint h = hash(range); uint bucket = h & (index.length-1); Slot *s = index[bucket]; - if(s == null) + if (s == null) { string str = putIntoCache(range); index[bucket] = allocateSlot(str, h); uniqueSlots++; return str; } - for(;;) + while (true) { if(s.hash == h && s.value.equal(range)) return s.value; @@ -3064,7 +3063,7 @@ struct StringCache uniqueSlots++; // had at least 1 item in this bucket // and inserted another one - check load factor - if(uniqueSlots*loadDenom > index.length*loadQuot) + if (uniqueSlots * loadDenom > index.length * loadQuot) rehash(); return str; } diff --git a/std/d/parser.d b/std/d/parser.d index 956ba5b..466ca65 100755 --- a/std/d/parser.d +++ b/std/d/parser.d @@ -72,11 +72,13 @@ version (unittest) import std.stdio; version = development; version(development) import std.stdio; +// TODO: any place that says *expect(...) needs to be fixed + /** -* Params: -* tokens = the tokens parsed by std.d.lexer -* Returns: the parsed module -*/ + * Params: + * tokens = the tokens parsed by std.d.lexer + * Returns: the parsed module + */ Module parseModule(const(Token)[] tokens) { auto parser = new Parser(); @@ -99,17 +101,8 @@ struct Parser */ AddExpression parseAddExpression() { - auto node = new AddExpression; - node.right = parseMulExpression(); - while (currentIsOneOf(TokenType.plus, TokenType.minus, TokenType.tilde)) - { - node.operator = advance().type; - auto newNode = new AddExpression; - newNode.left = node; - newNode.right = parseMulExpression(); - node = newNode; - } - return node; + return parseLeftAssocBinaryExpression!(AddExpression, MulExpression, + TokenType.plus, TokenType.minus, TokenType.tilde)(); } /** @@ -189,17 +182,8 @@ struct Parser */ AndAndExpression parseAndAndExpression() { - auto node = new AndAndExpression; - node.right = parseOrExpression(); - while (currentIs(TokenType.logicAnd)) - { - advance(); - auto node2 = new AndAndExpression; - node2.left = node; - node2.right = parseOrExpression(); - node = node2; - } - return node; + return parseLeftAssocBinaryExpression!(AndAndExpression, OrExpression, + TokenType.logicAnd)(); } /** @@ -212,9 +196,8 @@ struct Parser */ AndExpression parseAndExpression() { - auto node = new AndExpression; - // TODO - return node; + return parseLeftAssocBinaryExpression!(AndExpression, CmpExpression, + TokenType.bitAnd)(); } /** @@ -325,9 +308,8 @@ struct Parser */ AsmAddExp parseAsmAddExp() { - auto node = new AsmAddExp; - // TODO - return node; + return parseLeftAssocBinaryExpression!(AsmAddExp, AsmMulExp, + TokenType.plus, TokenType.minus)(); } /** @@ -598,21 +580,6 @@ struct Parser return node; } - /** - * Parses an AssertStatement - * - * $(GRAMMAR $(RULEDEF assertStatement): - * $(RULE assertExpression) $(LITERAL ';') - * ;) - */ - AssertStatement parseAssertStatement() - { - auto node = new AssertStatement; - node.assertExpression = parseAssertExpression(); - expect(TokenType.semicolon); - return node; - } - /** * Parses an AssignExpression * @@ -658,8 +625,6 @@ struct Parser * * $(GRAMMAR $(RULEDEF assignStatement): * $(RULE unaryExpression) $(RULE assignOperator) $(RULE assignExpression) ($(LITERAL ',') $(RULE unaryExpression) $(RULE assignOperator) $(RULE assignExpression))* $(LITERAL ';') - * | $(RULE preIncDecExpression) $(LITERAL ';') - * | $(RULE postIncDecExpression) $(LITERAL ';') * ;) */ AssignStatement parseAssignStatement() @@ -695,7 +660,20 @@ struct Parser AtAttribute parseAtAttribute() { auto node = new AtAttribute; - // TODO + expect(TokenType.at); + with (TokenType) switch (current().type) + { + case identifier: + if (peekIsOneOf(lParen, dot, not)) + node.functionCallExpression = parseFunctionCallExpression(); + else + node.identifier = advance(); + break; + case lParen: + node.argumentlist = parseArgumentList(); + expect(rParen); + break; + } return node; } @@ -883,8 +861,7 @@ struct Parser * Parses a BaseClass * * $(GRAMMAR $(RULEDEF baseClass): - * $(RULE typeofExpression) ($(LITERAL '.') $(RULE identifierOrTemplateChain))? - * | $(RULE identifierOrTemplateChain) + * ($(RULE typeofExpression) $(LITERAL '.'))? $(RULE identifierOrTemplateChain) * ;) */ BaseClass parseBaseClass() @@ -908,11 +885,7 @@ struct Parser */ BaseClassList parseBaseClassList() { - auto node = new BaseClassList; - do - node.baseClasses ~= parseBaseClass(); - while(currentIs(TokenType.comma)); - return node; + return parseCommaSeparatedRule!(BaseClassList, BaseClass)(); } /** @@ -1300,7 +1273,43 @@ class ClassFour(A, B) if (someTest()) : Super {}}; CmpExpression parseCmpExpression() { auto node = new CmpExpression; - // TODO + auto shift = parseShiftExpression(); + with (TokenType) switch (current().type) + { + case is_: + node.identityExpression = parseIdentityExpression(shift); + break; + case in_: + node.inExpression = parseInExpression(shift); + break; + case not: + if (peekIs(is_)) + node.identityExpression = parseIdentityExpression(shift); + else if (peekIs(in_)) + node.inExpression = parseInExpression(shift); + break; + case less: + case lessEqual: + case greater: + case greaterEqual: + case unordered: + case notLessEqualGreater: + case lessOrGreater: + case lessEqualGreater: + case notGreater: + case notGreaterEqual: + case notLess: + case notLessEqual: + node.relExpression = parseRelExpression(shift); + break; + case equal: + case notEqual: + node.equalExpression = parseEqualExpression(shift); + break; + default: + node.shiftExpression = shift; + break; + } return node; } @@ -1352,18 +1361,24 @@ class ClassFour(A, B) if (someTest()) : Super {}}; * Parses an ConditionalStatement * * $(GRAMMAR $(RULEDEF conditionalStatement): - * $(RULE compileCondition) $(RULE nonEmptyStatementNoCaseNoDefault) ($(LITERAL 'else') $(RULE nonEmptyStatementNoCaseNoDefault))? + * $(RULE compileCondition) $(RULE statementNoCaseNoDefault) ($(LITERAL 'else') $(RULE nonEmptyStatementNoCaseNoDefault))? * ;) */ ConditionalStatement parseConditionalStatement() { auto node = new ConditionalStatement; - // TODO + node.compileCondition = parseCompileCondition(); + node.trueStatement = parseStatementNoCaseNoDefault(); + if (currentIs(TokenType.else)) + { + advance(); + node.falseStatement = parseStatementNoCaseNoDefault(); + } return node; } /** - * Parses an Constraint + * Parses a Constraint * * $(GRAMMAR $(RULEDEF constraint): * $(LITERAL 'if') $(LITERAL '$(LPAREN)') $(RULE expression) $(LITERAL '$(RPAREN)') @@ -1635,11 +1650,11 @@ class ClassFour(A, B) if (someTest()) : Super {}}; } /** - * Parses an DeclarationsAndStatements + * Parses DeclarationsAndStatements * - * $(GRAMMAR $(RULEDEF declarationsAndStatements): - * ($(RULE declaration) | $(RULE statementNoCaseNoDefault))+ - * ;) + * $(GRAMMAR $(RULEDEF declarationsAndStatements): + * ($(RULE declaration) | $(RULE statementNoCaseNoDefault))+ + * ;) */ DeclarationsAndStatements parseDeclarationsAndStatements() { @@ -1722,21 +1737,6 @@ class ClassFour(A, B) if (someTest()) : Super {}}; return node; } - /** - * Parses a DeleteStatement - * - * $(GRAMMAR $(RULEDEF deleteStatement): - * $(RULE deleteExpression) $(LITERAL ';') - * ;) - */ - DeleteStatement parseDeleteStatement() - { - auto node = new DeleteStatement; - node.deleteExpression = parseDeleteExpression(); - expect(TokenType.semicolon); - return node; - } - /** * Parses a Deprecated attribute * @@ -1884,10 +1884,13 @@ class ClassFour(A, B) if (someTest()) : Super {}}; * $(RULE shiftExpression) ($(LITERAL '==') | $(LITERAL '!=')) $(RULE shiftExpression) * ;) */ - EqualExpression parseEqualExpression() + EqualExpression parseEqualExpression(ShiftExpression shift = null) { auto node = new EqualExpression; - // TODO + node.left = shift is null ? parseShiftExpression() : shift; + if (currentIsOneOf(TokenType.equal, TokenType.notEqual)) + node.operator = advance().type; + node.right = parseShiftExpression(); return node; } @@ -1900,13 +1903,11 @@ class ClassFour(A, B) if (someTest()) : Super {}}; */ Expression parseExpression() { - auto node = new Expression; - // TODO - return node; + return parseCommaSeparatedRule!(AssignExpression)(); } /** - * Parses an FinalSwitchStatement + * Parses a FinalSwitchStatement * * $(GRAMMAR $(RULEDEF finalSwitchStatement): * $(LITERAL 'final') $(RULE switchStatement) @@ -1915,7 +1916,8 @@ class ClassFour(A, B) if (someTest()) : Super {}}; FinalSwitchStatement parseFinalSwitchStatement() { auto node = new FinalSwitchStatement; - // TODO + expect(TokenType.final_); + node.switchStatement = parseSwitchStatement(); return node; } @@ -1923,13 +1925,14 @@ class ClassFour(A, B) if (someTest()) : Super {}}; * Parses a Finally * * $(GRAMMAR $(RULEDEF finally): - * $(LITERAL 'finally') $(RULE nonEmptyStatementNoCaseNoDefault) + * $(LITERAL 'finally') $(RULE statementNoCaseNoDefault) * ;) */ Finally parseFinally() { auto node = new Finally; - // TODO + expect(TokenType.finally_); + node.statementNoCaseNoDefault = parseStatementNoCaseNoDefault(); return node; } @@ -1998,9 +2001,7 @@ class ClassFour(A, B) if (someTest()) : Super {}}; */ ForeachTypeList parseForeachTypeList() { - auto node = new ForeachTypeList; - // TODO - return node; + return parseCommaSeparatedRule!(ForeachTypeList, ForeachType)(); } /** @@ -2015,7 +2016,18 @@ class ClassFour(A, B) if (someTest()) : Super {}}; FunctionAttribute parseFunctionAttribute() { auto node = new FunctionAttribute; - // TODO + with (TokenType) switch (curent().type) + { + case at: + node.atAttribute = parseAtAttribute(); + break; + case pure_: + case nothrow_: + node.token = advance(); + break; + default: + break; + } return node; } @@ -2110,7 +2122,10 @@ body {} // six FunctionCallExpression parseFunctionCallExpression() { auto node = new FunctionCallExpression; - // TODO + node.unaryExpression = parseUnaryExpression(); + if (currentIs(TokenType.not)) + node.templateArguments = parseTemplateArguments(); + node.arguments = parseArguments(); return node; } @@ -2124,7 +2139,8 @@ body {} // six FunctionCallStatement parseFunctionCallStatement() { auto node = new FunctionCallStatement; - // TODO + node.functionCallExpression = parseFunctionCallExpression(); + expect(TokenType.semicolon); return node; } @@ -2190,7 +2206,7 @@ body {} // six } /** - * Parses an FunctionLiteralExpression + * Parses a FunctionLiteralExpression * * $(GRAMMAR $(RULEDEF functionLiteralExpression): * (($(LITERAL 'function') | $(LITERAL 'delegate')) $(RULE type)?)? ($(RULE parameters) $(RULE functionAttribute)*)? $(RULE functionBody) @@ -2204,7 +2220,7 @@ body {} // six } /** - * Parses an GotoStatement + * Parses a GotoStatement * * $(GRAMMAR $(RULEDEF gotoStatement): * $(LITERAL 'goto') ($(LITERAL Identifier) | $(LITERAL 'default') | $(LITERAL 'case') $(RULE expression)?) $(LITERAL ';') @@ -2213,7 +2229,19 @@ body {} // six GotoStatement parseGotoStatement() { auto node = new GotoStatement; - // TODO + expect(TokenType.goto_); + with (TokenType) switch (current().type) + { + case identifier: + case default_: + node.token = advance(); + break; + case case_: + node.token = advance(); + node.expression = parseExpression(); + break; + } + expect(TokenType.semicolon); return node; } @@ -2321,10 +2349,14 @@ body {} // six * $(RULE shiftExpression) ($(LITERAL 'is') | $(LITERAL '!') $(LITERAL 'is')) $(RULE shiftExpression) * ;) */ - IdentityExpression parseIdentityExpression() + IdentityExpression parseIdentityExpression(ShiftExpression shift = null) { auto node = new IdentityExpression; - // TODO + node.left = shift is null ? parseShiftExpression() : shift; + if (currentIs(TokenType.not)) + node.negated = true; + expect(TokenType.is_); + node.right = parseShiftExpression(); return node; } @@ -2338,7 +2370,11 @@ body {} // six IfStatement parseIfStatement() { auto node = new IfStatement; - // TODO + expect(TokenType.if_); + expect(TokenType.lParen); + node.expression = parseExpression(); + expect(TokenType.rParen); + node.statementNoCaseNoDefault = parseStatementNoCaseNoDefault(); return node; } @@ -2513,10 +2549,14 @@ import foo, bar, baz; * $(RULE shiftExpression) ($(LITERAL 'in') | $(LITERAL '!') $(LITERAL 'in')) $(RULE shiftExpression) * ;) */ - InExpression parseInExpression() + InExpression parseInExpression(ShiftExpression shift = null) { auto node = new InExpression; - // TODO + node.left = shift is null ? parseShiftExpression() : shift; + if (currentIs(TokenType.not)) + advance(); + expect(TokenType.in_); + node.right = parseShiftExpression(); return node; } @@ -2649,16 +2689,47 @@ interface "Four" * Parses an Invariant * * $(GRAMMAR $(RULEDEF invariant): - * $(LITERAL 'invariant') $(LITERAL '$(LPAREN)') $(LITERAL '$(RPAREN)') $(RULE blockStatement) + * $(LITERAL 'invariant') ($(LITERAL '$(LPAREN)') $(LITERAL '$(RPAREN)'))? $(RULE blockStatement) * ;) */ Invariant parseInvariant() { auto node = new Invariant; - // TODO + if (expect(TokenType.invariant_) is null) return null; + if (currentIs(TokenType.lParen)) + { + advance(); + if (expect(TokenType.rParen) is null) return null; + } + if ((node.blockStatement = parseBlockStatement()) is null) return null; return node; } + unittest + { + auto sourceCode = +q{invariant() {} +invariant{} +invariant() foo(); +}c; + + Parser p = getParserForUnittest(sourceCode, "parseInvariant"); + + auto inv1 = p.parseInvariant(); + assert (inv1 !is null); + assert (inv1.blockStatement !is null); + assert (p.errorCount == 0); + + auto inv2 = p.parseInvariant(); + assert (inv2 !is null); + assert (inv2.blockStatement !is null); + assert (p.errorCount == 0); + + auto inv3 = p.parseInvariant(); + assert (inv3 is null); + assert (p.errorCount > 0); + } + /** * Parses an IsExpression * @@ -2669,7 +2740,10 @@ interface "Four" IsExpression parseIsExpression() { auto node = new IsExpression; + if (expect(TokenType.is_) is null) return null; + if (expect(TokenType.lParen) is null) return null; // TODO + if (expect(TokenType.rParen) is null) return null; return node; } @@ -2683,7 +2757,9 @@ interface "Four" KeyValuePair parseKeyValuePair() { auto node = new KeyValuePair; - // TODO + node.key = parseAssignExpression(); + if (expect(TokenType.colon) is null) return null; + node.value = parseAssignExpression(); return node; } @@ -2697,7 +2773,16 @@ interface "Four" KeyValuePairs parseKeyValuePairs() { auto node = new KeyValuePairs; - // TODO + while (true) + { + auto kvPair = parseKeyValuePair(); + if (kvPair !is null) + node.keyValuePairs ~= kvPair; + if (currentIs(TokenType.comma)) + advance(); + else + break; + } return node; } @@ -2741,7 +2826,9 @@ interface "Four" LastCatch parseLastCatch() { auto node = new LastCatch; - // TODO + if (expect(TokenType.catch_) is null) return null; + if ((node.statementNoCaseNoDefault = parseStatementNoCaseNoDefault()) is null) + return null;; return node; } @@ -2810,7 +2897,10 @@ interface "Four" MixinExpression parseMixinExpression() { auto node = new MixinExpression; - // TODO + expect(TokenType.mixin_); + expect(TokenType.lParen); + node.assignExpression = parseAssignExpression(); + expect(TokenType.rParen); return node; } @@ -2824,7 +2914,12 @@ interface "Four" MixinTemplateName parseMixinTemplateName() { auto node = new MixinTemplateName; - // TODO + if (currentIs(TokenType.typeof_)) + { + node.typeofExpression = parseTypeofExpression(); + expect(TokenType.dot); + } + node.identifierOrTemplateChain = parseIdentifierOrTemplateChain(); return node; } @@ -2838,21 +2933,13 @@ interface "Four" Module parseModule() { Module m = new Module; + if (currentIs(TokenType.module_)) + node.moduleDeclaration = parseModuleDeclaration(); while (moreTokens()) { - switch (current().type) - { - case TokenType.module_: - if (m.moduleDeclaration is null) - m.moduleDeclaration = parseModuleDeclaration(); - else - error("Only one module declaration is allowed per module"); - break; - default: - auto declaration = parseDeclaration(); - if (declaration !is null) - m.declarations ~= declaration; - } + auto declaration = parseDeclaration(); + if (declaration !is null) + m.declarations ~= declaration; } return m; } @@ -2882,27 +2969,27 @@ interface "Four" */ MulExpression parseMulExpression() { - auto node = new MulExpression; - auto left = parseUnaryExpression(); - if (tokens[index] == TokenType.star || tokens[index] == TokenType.div) - { - node.operator = tokens[index++]; - node.right = parseUnaryExpression(); - } - return node; + return parseLeftAssocBinaryExpression!(MulExpression, UnaryExpression, + TokenType.star, TokenType.div, TokenType.mod)(); } /** * Parses a NewAnonClassExpression * * $(GRAMMAR $(RULEDEF newAnonClassExpression): - * $(LITERAL 'new') $(RULE arguments)? $(LITERAL 'class') $(RULE arguments)? $(LITERAL Identifier) $(RULE identifierList)? $(RULE classBody) + * $(LITERAL 'new') $(RULE arguments)? $(LITERAL 'class') $(RULE arguments)? $(RULE baseClassList)? $(RULE classBody) * ;) */ NewAnonClassExpression parseNewAnonClassExpression() { auto node = new NewAnonClassExpression; - // TODO + expect(TokenType.new_); + if (currentIs(TokenType.lParen)) + node.allocatorArguments = parseArguments(); + expect(TokenType.class_); + if (!currentIs(TokenType.lBrace)) + node.baseClassList = parseBaseClassList + node.classBody = parseClassBody(); return node; } @@ -2917,7 +3004,21 @@ interface "Four" NewExpression parseNewExpression() { auto node = new NewExpression; - // TODO + if (peekIsOneOf(TokenType.class_ TokenType.lParen)) + node.newAnonClassExpression = parseNewAnonClassExpression(); + else + { + expect(TokenType.new_); + node.type = parseType(); + if (currentIs(TokenType.lBracket)) + { + advance(); + node.assignExpression = parseAssignExpression(); + expect(TokenType.rBracket); + } + else if (currentIs(TokenType.lParen)) + node.arguments = parseArguments(); + } return node; } @@ -2925,7 +3026,7 @@ interface "Four" * Parses a NonEmptyStatement * * $(GRAMMAR $(RULEDEF nonEmptyStatement): - * $(RULE nonEmptyStatementNoCaseNoDefault) + * $(RULE statementNoCaseNoDefault) * | $(RULE caseStatement) * | $(RULE caseRangeStatement) * | $(RULE defaultStatement) @@ -2934,6 +3035,18 @@ interface "Four" NonEmptyStatement parseNonEmptyStatement() { auto node = new NonEmptyStatement; + with (TokenType) switch (current().type) + { + case default_: + node.defaultStatement = parseDefaultStatement(); + break; + case case_: + // TODO + break; + default: + node.statementNoCaseNoDefault = parseStatementNoCaseNoDefault(); + break; + } return node; } @@ -2964,18 +3077,86 @@ interface "Four" * | $(RULE foreachRangeStatement) * | $(RULE conditionalStatement) * | $(RULE staticAssertStatement) - * | $(RULE assertStatement) * | $(RULE templateMixinStatement) * | $(RULE versionSpecification) * | $(RULE debugSpecification) - * | $(RULE functionCallStatement) - * | $(RULE deleteStatement) + * | $(RULE expressionStatement) * ;) */ StatementNoCaseNoDefault parseStatementNoCaseNoDefault() { auto node = new StatementNoCaseNoDefault; - // TODO + with (TokenType) switch (current().type) + { + case lBrace: + node.blockStatement = parseBlockStatement(); + break; + case if_: + node.ifStatement = parseIfStatement(); + break; + case while_: + node.whileStatement = parseWhileStatement(); + break; + case do_: + node.doStatement = parseDoStatement(); + break; + case for_: + node.forStatement = parseForStatement(); + break; + case foreach_: + // TODO + break; + case switch_: + node.switchStatement = parseSwitchStatement(); + break; + case continue_: + node.continueStatement = parseContinueStatement(); + break; + case break_: + node.breakStatement = parseBreakStatement(); + break; + case return_: + node.returnStatement = parseReturnStatement(); + break; + case goto_: + node.gotoStatement = parseGotoStatement(); + break; + case with_: + node.withStatement = parseWithStatement(); + break; + case synchronized_: + node.synchronizedStatement = parseSynchronizedStatement(); + break; + case try_: + node.tryStatement = parseTryStatement(); + break; + case throw_: + node.throwStatement = parseThrowStatement(); + break; + case scope_: + node.scopeGuardStatement = parseScopeGuardStatement(); + break; + case asm_: + node.asmStatement = parseAsmStatement(); + break; + case assert_: + node.assertStatement = parseAssertStatement(); + break; + case delete_: + node.deleteStatement = parseDeleteStatement(); + break; + default: + break; + // TODO: assignStatement + // TODO: finalSwitchStatement + // TODO: foreachRangeStatement + // TODO: conditionalStatement + // TODO: staticAssertStatement + // TODO: templateMixinStatement + // TODO: versionSpecification + // TODO: debugSpecification + // TODO: functionCallStatement + } return node; } @@ -2991,11 +3172,10 @@ interface "Four" NonVoidInitializer parseNonVoidInitializer() { auto node = new NonVoidInitializer; - // TODO - if (curentIs(TokenType.lBrace)) - node.structInitializer = parseStructInitializer() + if (currentIs(TokenType.lBrace)) + node.structInitializer = parseStructInitializer(); else if (currentIs(TokenType.lBracket)) - node.arrayInitializer = parseArrayInitializer() + node.arrayInitializer = parseArrayInitializer(); else node.assignExpression = parseAssignExpression(); return node; @@ -3025,9 +3205,8 @@ interface "Four" */ OrExpression parseOrExpression() { - auto node = new OrExpression; - // TODO - return node; + return parseLeftAssocBinaryExpression!(OrExpression, XorExpression, + TokenType.bitOr)(); } /** @@ -3040,10 +3219,8 @@ interface "Four" */ OrOrExpression parseOrOrExpression() { - auto node = new OrOrExpression; - node.andAndExpression = parseAndAndExpression(); - - return node; + return parseLeftAssocBinaryExpression!(OrOrExpression, AndAndExpression, + TokenType.logicOr)(); } /** @@ -3128,7 +3305,11 @@ interface "Four" Postblit parsePostblit() { auto node = new Postblit; - // TODO + expect(TokenType.this_); + expect(TokenType.lParen); + expect(TokenType.this_); + expect(TokenType.rParen); + node.functionBody = parseFunctionBody(); return node; } @@ -3139,10 +3320,11 @@ interface "Four" * $(RULE unaryExpression) ($(LITERAL '++') | $(LITERAL '--')) * ;) */ - PostIncDecExpression parsePostIncDecExpression() + PostIncDecExpression parsePostIncDecExpression(UnaryExpression unary = null) { auto node = new PostIncDecExpression; - // TODO + node.unaryExpression = unary is null ? parseUnaryExpression() : unary; + node.operator = advance(); return node; } @@ -3156,9 +3338,8 @@ interface "Four" */ PowExpression parsePowExpression() { - auto node = new PowExpression; - // TODO - return node; + return parseLeftAssocBinaryExpression!(PowExpression, UnaryExpression, + TokenType.pow)(); } /** @@ -3171,7 +3352,8 @@ interface "Four" PragmaDeclaration parsePragmaDeclaration() { auto node = new PragmaDeclaration; - // TODO + node.pragmaExpression = parsePragmaExpression(); + expect(TokenType.semicolon); return node; } @@ -3185,7 +3367,17 @@ interface "Four" PragmaExpression parsePragmaExpression() { auto node = new PragmaExpression; - // TODO + expect(TokenType.pragma_); + expect(TokenType.lParen); + auto ident = expect(TokenType.identifier); + if (ident is null) return null; + node.identifier = *ident; + if (currentIs(TokenType.comma)) + { + advance(); + node.argumentList = parseArgumentList(); + } + expect(TokenType.rParen); return node; } @@ -3199,7 +3391,14 @@ interface "Four" PreIncDecExpression parsePreIncDecExpression() { auto node = new PreIncDecExpression; - // TODO + if (currentIsOneOf(TokenType.increment, TokenType.decrement)) + advance(); + else + { + error(`"++" or "--" expected`); + return null; + } + node.unaryExpression = parseUnaryExpression(); return node; } @@ -3245,7 +3444,50 @@ interface "Four" PrimaryExpression parsePrimaryExpression() { auto node = new PrimaryExpression; - // TODO + with (TokenType) switch (current().type) + { + case identifier: + // TODO + // symbol or type.identifier + break; + case typeof_: + node.typeofExpression = parseTypeofExpression(); + break; + case typeid_: + node.typeidExpression = parseTypeidExpression(); + break; + case lBracket: + // TODO: array literal or associative array literal + break; + case lParen: + advance(); + node.expression = parseExpression(); + expect(TokenType.rParen); + break; + case is_: + node.isExpression = parseIsExpression(); + break; + // TODO: lambda + // TODO: function literal + case traits: + node.traitsExpression = parseTraitsExpression(); + break; + case mixin_: + node.mixinExpression = parseMixinExpression(); + break; + case import_: + node.importExpression = parseImportExpression(); + break; + case dollar: + case this_: + case null_: + case true_: + case false_: + case specialDate: .. case specialPrettyFunction: + case doubleLiteral: .. case wstringLiteral: + primary = advance(); + break; + } return node; } @@ -3260,7 +3502,13 @@ interface "Four" Register parseRegister() { auto node = new Register; - // TODO + node.identifier = *expect(TokenType.identifier); + if (currentIs(TokenType.lParen)) + { + advance(); + node.intLiteral = *expect(TokenType.intLiteral); + expect(TokenType.rParen); + } return node; } @@ -3286,11 +3534,15 @@ interface "Four" * | $(LITERAL '!<=') * ;) */ - RelExpression parseRelExpression() + RelExpression parseRelExpression(ShiftExpression shift = null) { - auto node = new RelExpression; - // TODO - return node; + return parseLeftAssocBinaryExpression!(RelExpression, ShiftExpression, + TokenType.less, TokenType.lessEqual, TokenType.greater, + TokenType.greaterEqual, TokenType.unordered, + TokenType.notLessEqualGreater, TokenType.lessOrGreater, + TokenType.lessEqualGreater, TokenType.notGreater, + TokenType.notGreaterEqual, TokenType.notLess, + TokenType.notLessEqual)(shift); } /** @@ -3314,13 +3566,17 @@ interface "Four" * Parses a ScopeGuardStatement * * $(GRAMMAR $(RULEDEF scopeGuardStatement): - * $(LITERAL 'scope') $(LITERAL '$(LPAREN)') $(LITERAL Identifier) $(LITERAL '$(RPAREN)') $(RULE nonEmptyStatementNoCaseNoDefault) + * $(LITERAL 'scope') $(LITERAL '$(LPAREN)') $(LITERAL Identifier) $(LITERAL '$(RPAREN)') $(RULE statementNoCaseNoDefault) * ;) */ ScopeGuardStatement parseScopeGuardStatement() { auto node = new ScopeGuardStatement; - // TODO + expect(TokenType.scope_); + expect(TokenType.lParen); + node.identifier = *expect(TokenType.identifier); + expect(TokenType.rParen); + node.statementNoCaseNoDefault = parseStatementNoCaseNoDefault(); return node; } @@ -3334,7 +3590,12 @@ interface "Four" SharedStaticConstructor parseSharedStaticConstructor() { auto node = new SharedStaticConstructor; - // TODO + expect(TokenType.shared_); + expect(TokenType.static_); + expect(TokenType.this_); + expect(TokenType.lParen); + expect(TokenType.rParen); + node.functionBody = parseFunctionBody(); return node; } @@ -3348,7 +3609,13 @@ interface "Four" SharedStaticDestructor parseSharedStaticDestructor() { auto node = new SharedStaticDestructor; - // TODO + expect(TokenType.shared_); + expect(TokenType.static_); + expect(TokenType.tilde); + expect(TokenType.this_); + expect(TokenType.lParen); + expect(TokenType.rParen); + node.functionBody = parseFunctionBody(); return node; } @@ -3362,9 +3629,9 @@ interface "Four" */ ShiftExpression parseShiftExpression() { - auto node = new ShiftExpression; - // TODO - return node; + return parseLeftAssocBinaryExpression!(ShiftExpression, AddExpression, + TokenType.shiftLeft, TokenType.shiftRight, + TokenType.unsignedShiftRight)(); } /** @@ -3545,7 +3812,7 @@ interface "Four" version (development) skipBraceContent(); else - assert (0); + static assert (0); //while (tokens[index] != TokenType.rBrace && moreTokens()) // node.structBodyItems ~= parseStructBodyItem(); expect(TokenType.rBrace); @@ -3564,7 +3831,12 @@ interface "Four" StructBodyItem parseStructBodyItem() { auto node = new StructBodyItem; - + if (currentIs(TokenType.invariant_)) + node.invariant_ = parseInvariant(); + else if (startsWith(TokenType.this_, TokenType.lParen, TokenType.this_)) + node.postBlit = parsePostblit(); + else + node.declaration = parseDeclaration(); return node; } @@ -3668,7 +3940,7 @@ interface "Four" } /** - * Parses an SwitchStatement + * Parses a SwitchStatement * * $(GRAMMAR $(RULEDEF switchStatement): * $(LITERAL 'switch') $(LITERAL '$(LPAREN)') $(RULE expression) $(LITERAL '$(RPAREN)') $(RULE switchBody) @@ -3705,7 +3977,7 @@ interface "Four" } /** - * Parses an SynchronizedStatement + * Parses a SynchronizedStatement * * $(GRAMMAR $(RULEDEF synchronizedStatement): * $(LITERAL 'synchronized') ($(LITERAL '$(LPAREN)') $(RULE expression) $(LITERAL '$(RPAREN)'))? $(RULE nonEmptyStatementNoCaseNoDefault) @@ -3726,7 +3998,7 @@ interface "Four" } /** - * Parses an TemplateAliasParameter + * Parses a TemplateAliasParameter * * $(GRAMMAR $(RULEDEF templateAliasParameter): * $(LITERAL 'alias') $(RULE type)? $(LITERAL Identifier) ($(LITERAL ':') ($(RULE type) | $(RULE expression)))? ($(LITERAL '=') ($(RULE type) | $(RULE expression)))? @@ -3735,6 +4007,7 @@ interface "Four" TemplateAliasParameter parseTemplateAliasParameter() { auto node = new TemplateAliasParameter; + expect(TokenType.alias_); // TODO return node; } @@ -3764,9 +4037,7 @@ interface "Four" */ TemplateArgumentList parseTemplateArgumentList() { - auto node = new TemplateArgumentList; - // TODO - return node; + return parseCommaSeparatedRule!(TemplateArgumentList, TemplateArgument)(); } /** @@ -3779,12 +4050,20 @@ interface "Four" TemplateArguments parseTemplateArguments() { auto node = new TemplateArguments; - // TODO + expect(TokenType.not); + if (currentIs(TokenType.lParen)) + { + advance(); + node.templateArgumentList = parseTemplateArgumentList(); + expect(TokenType.rParen); + } + else + node.templateSingleArgument = parseTemplateSingleArgument(); return node; } /** - * Parses an TemplateDeclaration + * Parses a TemplateDeclaration * * $(GRAMMAR $(RULEDEF templateDeclaration): * $(LITERAL 'template') $(LITERAL Identifier) $(RULE templateParameters) $(RULE constraint)? $(LITERAL '{') $(RULE declaration)+ $(LITERAL '}') @@ -3793,7 +4072,16 @@ interface "Four" TemplateDeclaration parseTemplateDeclaration() { auto node = new TemplateDeclaration; - // TODO + expect(TokenType.template_); + node.identifier = *expect(TokenType.identifier); + node.templateParameters = parseTemplateParameters(); + if (currentIs(TokenType.if_)); + node.constraint = parseConstraint(); + expect(TokenType.lBrace); + do + node.declarations ~= parseDeclaration(); + while (!currentIs(TokenType.rBrace)) + expect(TokenType.rBrace); return node; } @@ -3801,13 +4089,14 @@ interface "Four" * Parses a TemplateInstance * * $(GRAMMAR $(RULEDEF templateInstance): - * $(LITERAL Identifier) $(RULE templateArguments) + * $(LITERAL symbol) $(RULE templateArguments) * ;) */ TemplateInstance parseTemplateInstance() { auto node = new TemplateInstance; - // TODO + node.symbol = parseSymbol(); + node.templateArguments = parseTemplateArguments(); return node; } @@ -3875,7 +4164,7 @@ interface "Four" } /** - * Parses an TemplateSingleArgument + * Parses a TemplateSingleArgument * * $(GRAMMAR $(RULEDEF templateSingleArgument): * $(RULE builtinType) @@ -3908,7 +4197,7 @@ interface "Four" } /** - * Parses an TemplateThisParameter + * Parses a TemplateThisParameter * * $(GRAMMAR $(RULEDEF templateThisParameter): * $(LITERAL 'this') $(RULE templateTypeParameter) @@ -3973,7 +4262,20 @@ interface "Four" TemplateValueParameterDefault parseTemplateValueParameterDefault() { auto node = new TemplateValueParameterDefault; - // TODO + expect(TokenType.assign); + with (TokenType) switch (current().type) + { + case specialFile: + case specialModule: + case specialLine: + case specialFunction: + case specialPrettyFunction: + node.token = advance(); + break; + default: + node.assignExpression = parseAssignExpression(); + break; + } return node; } @@ -4018,7 +4320,7 @@ interface "Four" * Parses an TraitsArgument * * $(GRAMMAR $(RULEDEF traitsArgument): - * $(RULE assignExpression) + * $(RULE assignExpression) * | $(RULE type) * ;) */ @@ -4257,7 +4559,6 @@ interface "Four" * $(GRAMMAR $(RULEDEF typeidExpression): * $(LITERAL 'typeid') $(LITERAL '$(LPAREN)')($(RULE type) | $(RULE expression)) $(LITERAL '$(RPAREN)') * ;) - */ TypeidExpression parseTypeidExpression() { @@ -4526,9 +4827,8 @@ interface "Four" */ XorExpression parseXorExpression() { - auto node = new XorExpression; - // TODO - return node; + return parseLeftAssocBinaryExpression!(XorExpression, AndExpression, + TokenType.xor)(); } private bool currentIsMemberFunctionAttribute() const @@ -4548,6 +4848,39 @@ interface "Four" } } + private Left parseLeftAssocBinaryExpression(alias Left, alias Right, Operators ...) + (Right r = null) + { + auto node = new Left; + mixin ("node.right = r is null ? parse" ~ Right.stringof ~ "() : r;"); + while (currentIsOneOf(Operators)) + { + static if (__traits(hasMember, Left, "operator")) + node.operator = advance().type; + else + advance(); + auto newNode = new Left; + newNode.left = node; + mixin ("newNode.right = parse" ~ Right.stringof ~ "();"); + node = newNode; + } + return node; + } + + private ListType parseCommaSeparatedRule(alias ListType, alias ItemType)() + { + auto node = new ListType; + while (true) + { + mixin ("node.items ~= parse" ~ ItemType.stringof ~ "();"); + if (currentIs(TokenType.comma)) + advance(); + else + break; + } + return node; + } + void error(lazy string message) { import std.stdio;