From 1beef6a9017f9a2d9e80ef26394780145f9ff033 Mon Sep 17 00:00:00 2001 From: Hackerpilot Date: Mon, 24 Jun 2013 02:33:40 +0000 Subject: [PATCH] Unary and Primary expression parsing --- std/d/ast.d | 80 ++++------ std/d/lexer.d | 2 + std/d/parser.d | 410 ++++++++++++++++++++++++++++++++++++------------- std/d/tester.d | 7 +- 4 files changed, 335 insertions(+), 164 deletions(-) diff --git a/std/d/ast.d b/std/d/ast.d index 775801f..c594478 100755 --- a/std/d/ast.d +++ b/std/d/ast.d @@ -68,7 +68,6 @@ abstract class ASTVisitor /** */ void visit(BreakStatement breakStatement) { breakStatement.accept(this); } /** */ void visit(BaseClass baseClass) { baseClass.accept(this); } /** */ void visit(BaseClassList baseClassList) { baseClassList.accept(this); } - /** */ void visit(BasicType builtinType) { builtinType.accept(this); } /** */ void visit(CaseRangeStatement caseRangeStatement) { caseRangeStatement.accept(this); } /** */ void visit(CaseStatement caseStatement) { caseStatement.accept(this); } /** */ void visit(CastExpression castExpression) { castExpression.accept(this); } @@ -101,6 +100,7 @@ abstract class ASTVisitor /** */ void visit(EnumMember enumMember) { enumMember.accept(this); } /** */ void visit(EqualExpression equalExpression) { equalExpression.accept(this); } /** */ void visit(Expression expression) { expression.accept(this); } + /** */ void visit(ExpressionStatement expressionStatement) { expressionStatement.accept(this); } /** */ void visit(FinalSwitchStatement finalSwitchStatement) { finalSwitchStatement.accept(this); } /** */ void visit(Finally finally_) { finally_.accept(this); } /** */ void visit(ForStatement forStatement) { forStatement.accept(this); } @@ -157,7 +157,6 @@ abstract class ASTVisitor /** */ void visit(OrOrExpression orOrExpression) { orOrExpression.accept(this); } /** */ void visit(OutStatement outStatement) { outStatement.accept(this); } /** */ void visit(Parameter parameter) { parameter.accept(this); } - /** */ void visit(ParameterAttribute parameterAttribute) { parameterAttribute.accept(this); } /** */ void visit(Parameters parameters) { parameters.accept(this); } /** */ void visit(Postblit postblit) { postblit.accept(this); } /** */ void visit(PostIncDecExpression postIncDecExpression) { postIncDecExpression.accept(this); } @@ -216,7 +215,6 @@ abstract class ASTVisitor /** */ void visit(TryStatement tryStatement) { tryStatement.accept(this); } /** */ void visit(Type type) { type.accept(this); } /** */ void visit(Type2 type2) { type2.accept(this); } - /** */ void visit(TypeConstructor typeConstructor) { typeConstructor.accept(this); } /** */ void visit(TypeConstructors typeConstructors) { typeConstructors.accept(this); } /** */ void visit(TypeSpecialization typeSpecialization) { typeSpecialization.accept(this); } /** */ void visit(TypeSuffix typeSuffix) { typeSuffix.accept(this); } @@ -653,15 +651,7 @@ class BaseClassList : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */ BaseClass[] baseClasses; -} - -/// -class BasicType : ASTNode -{ -public: - mixin(DEFAULT_ACCEPT); - /** */ TokenType type; + /** */ BaseClass[] items; } /// @@ -1005,6 +995,14 @@ public: /** */ AssignExpression[] items; } +/// +class ExpressionStatement : ASTNode +{ +public: + mixin(DEFAULT_ACCEPT); + /** */ Expression expression; +} + /// class FinalSwitchStatement : ASTNode { @@ -1070,7 +1068,7 @@ class ForeachTypeList : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */ ForeachType[] foreachTypes; + /** */ ForeachType[] items; } /// @@ -1078,7 +1076,7 @@ class FunctionAttribute : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */ Token pureOrNothrow; + /** */ Token token; /** */ AtAttribute atAttribute; } @@ -1130,7 +1128,7 @@ class FunctionLiteralExpression : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */ Token functionOrDelegate; + /** */ TokenType functionOrDelegate; /** */ Type type; /** */ Parameters parameters; /** */ FunctionAttribute[] functionAttributes; @@ -1503,12 +1501,11 @@ public: /** */ ForeachRangeStatement foreachRangeStatement; /** */ ConditionalStatement conditionalStatement; /** */ StaticAssertStatement staticAssertStatement; - /** */ AssertStatement assertStatement; /** */ TemplateMixinStatement templateMixinStatement; /** */ VersionSpecification versionSpecification; /** */ DebugSpecification debugSpecification; /** */ FunctionCallStatement functionCallStatement; - /** */ DeleteStatement deleteStatement; + /** */ ExpressionStatement expressionStatement; } /// @@ -1570,19 +1567,11 @@ class Parameter : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */ ParameterAttribute[] paramaterAttributes; + /** */ TokenType[] parameterAttributes; /** */ Type type; /** */ Token name; /** */ bool vararg; -} - -/// -class ParameterAttribute: ASTNode -{ -public: - mixin(DEFAULT_ACCEPT); - /** */ Token attribute; - /** */ TypeConstructor typeConstructor; + /** */ AssignExpression default_; } /// @@ -1590,7 +1579,7 @@ class Parameters : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */ Parameter[] paramaters; + /** */ Parameter[] parameters; /** */ bool hasVarargs; } @@ -1673,7 +1662,7 @@ class Register : ASTNode public: mixin(DEFAULT_ACCEPT); /** */ Token identifier; - /** */ Token integerLiteral; + /** */ Token intLiteral; /** */ bool hasIntegerLiteral; } @@ -1805,8 +1794,7 @@ class StorageClass : ASTNode public: mixin(DEFAULT_ACCEPT); /** */ AtAttribute atAttribute; - /** */ TypeConstructor typeConstructor; - /** */ Token storageClass; + /** */ Token token; } /// @@ -1927,7 +1915,7 @@ class TemplateArgumentList : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */ TemplateArgument[] templateArguments; + /** */ TemplateArgument[] items; } /// @@ -1955,7 +1943,7 @@ class TemplateInstance : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */ Token identifier; + /** */ Symbol symbol; /** */ TemplateArguments templateArguments; } @@ -1986,7 +1974,7 @@ class TemplateParameterList : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */ TemplateParameter[] templateParameters; + /** */ TemplateParameter[] items; } /// @@ -2003,7 +1991,6 @@ class TemplateSingleArgument : ASTNode public: mixin(DEFAULT_ACCEPT); /** */ Token token; - /** */ BasicType builtinType; } /// @@ -2103,7 +2090,7 @@ class Type : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */ TypeConstructors typeConstructors; + /** */ TokenType[] typeConstructors; /** */ TypeSuffix[] typeSuffixes; /** */ Type2 type2; } @@ -2113,28 +2100,20 @@ class Type2 : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */ BasicType basicType; + /** */ Token basicType; /** */ Symbol symbol; /** */ TypeofExpression typeofExpression; /** */ IdentifierOrTemplateChain identifierOrTemplateChain; - /** */ TypeConstructor typeConstructor; + /** */ TokenType typeConstructor; /** */ Type type; } -/// -class TypeConstructor : ASTNode -{ -public: - mixin(DEFAULT_ACCEPT); - /** */ Token typeConstructor; -} - /// class TypeConstructors : ASTNode { public: mixin(DEFAULT_ACCEPT); - /** */ TypeConstructor[] typeConstructors; + /** */ TokenType[] items; } /// @@ -2183,17 +2162,14 @@ class UnaryExpression : ASTNode public: mixin(DEFAULT_ACCEPT); /** */ PrimaryExpression primaryExpression; - /** */ UnaryExpression unaryExpression; /** */ Token prefix; - /** */ PreIncDecExpression preIncDecExpression; - /** */ PostIncDecExpression postIncDecExpression; + /** */ Token suffix; + /** */ UnaryExpression unaryExpression; /** */ NewExpression newExpression; /** */ DeleteExpression deleteExpression; /** */ CastExpression castExpression; /** */ FunctionCallExpression functionCallExpression; /** */ ArgumentList argumentList; - /** */ AssignExpression low; - /** */ AssignExpression high; /** */ IdentifierOrTemplateInstance identifierOrTemplateInstance; /** */ AssertExpression assertExpression; } diff --git a/std/d/lexer.d b/std/d/lexer.d index d12faad..7205639 100755 --- a/std/d/lexer.d +++ b/std/d/lexer.d @@ -2009,6 +2009,7 @@ pure nothrow bool isMisc(ref const Token t) */ enum TokenType: ushort { + invalid, /// Not a valid token assign, /// = at, /// @ bitAnd, /// & @@ -2506,6 +2507,7 @@ bool isRangeEoF(R)(ref R range) // Lookup table for token values package immutable(string[TokenType.max + 1]) tokenValues = [ + null, "=", "@", "&", diff --git a/std/d/parser.d b/std/d/parser.d index 3c0e45c..20afa6e 100755 --- a/std/d/parser.d +++ b/std/d/parser.d @@ -56,7 +56,7 @@ * MACROS: * GRAMMAR = $(D_CODE $0) * RULEDEF = $(DDOC_ANCHOR $0) $(B $0) - * RULE = $(LINK2 #.$0, $(B $0)) + * RULE = $(LINK2 #$0, $(B $0)) * LITERAL = $(D_STRING $0) */ @@ -70,7 +70,9 @@ import std.array; version (unittest) import std.stdio; version = development; +//version = verbose; version(development) import std.stdio; +version(verbose) import std.stdio; // TODO: any place that says *expect(...) needs to be fixed @@ -101,6 +103,7 @@ struct Parser */ AddExpression parseAddExpression() { + version(verbose) writeln("parseAddExpression"); return parseLeftAssocBinaryExpression!(AddExpression, MulExpression, TokenType.plus, TokenType.minus, TokenType.tilde)(); } @@ -182,6 +185,7 @@ struct Parser */ AndAndExpression parseAndAndExpression() { + version(verbose) writeln("parseAndAndExpression"); return parseLeftAssocBinaryExpression!(AndAndExpression, OrExpression, TokenType.logicAnd)(); } @@ -196,6 +200,7 @@ struct Parser */ AndExpression parseAndExpression() { + version(verbose) writeln("parseAndExpression"); return parseLeftAssocBinaryExpression!(AndExpression, CmpExpression, TokenType.bitAnd)(); } @@ -605,6 +610,7 @@ struct Parser */ AssignExpression parseAssignExpression() { + version(verbose) writeln("parseAssignExpression"); auto node = new AssignExpression; node.ternaryExpression = parseTernaryExpression(); if (currentIsOneOf(TokenType.assign, TokenType.unsignedShiftRightEqual, @@ -630,12 +636,7 @@ struct Parser AssignStatement parseAssignStatement() { auto node = new AssignStatement; - if (currentIsOneOf(TokenType.increment, TokenType.decrement)) - node.preIncDecExpression = parsePreIncDecExpression(); - else - { // TODO - } expect(TokenType.semicolon); return node; } @@ -676,9 +677,12 @@ struct Parser node.identifier = advance(); break; case lParen: - node.argumentlist = parseArgumentList(); + node.argumentList = parseArgumentList(); expect(rParen); break; + default: + error(`"(", or identifier expected`); + return null; } return node; } @@ -814,9 +818,9 @@ struct Parser { auto node = new BlockStatement(); expect(TokenType.lBrace); - skipBraceContent(); - //if (!currentIs(TokenType.rBrace)) - // node.declarationsAndStatements = parseDeclarationsAndStatements(); + version (development) skipBraceContent(); + if (!currentIs(TokenType.rBrace)) + node.declarationsAndStatements = parseDeclarationsAndStatements(); expect(TokenType.rBrace); return node; } @@ -922,17 +926,13 @@ struct Parser * | $(LITERAL 'void') * ;) */ - BasicType parseBasicType() + Token parseBasicType() { - auto node = new BasicType; if (isBasicType(current().type)) - node.type = advance().type; - else - { - error("Basic type expected"); - return null; - } - return node; + return advance(); + error("Basic type expected"); + Token t; + return t; } /** @@ -1278,6 +1278,7 @@ class ClassFour(A, B) if (someTest()) : Super {}}; */ CmpExpression parseCmpExpression() { + version(verbose) writeln("parseCmpExpression"); auto node = new CmpExpression; auto shift = parseShiftExpression(); with (TokenType) switch (current().type) @@ -1375,7 +1376,7 @@ class ClassFour(A, B) if (someTest()) : Super {}}; auto node = new ConditionalStatement; node.compileCondition = parseCompileCondition(); node.trueStatement = parseStatementNoCaseNoDefault(); - if (currentIs(TokenType.else)) + if (currentIs(TokenType.else_)) { advance(); node.falseStatement = parseStatementNoCaseNoDefault(); @@ -1892,6 +1893,7 @@ class ClassFour(A, B) if (someTest()) : Super {}}; */ EqualExpression parseEqualExpression(ShiftExpression shift = null) { + version(verbose) writeln("parseEqualExpression"); auto node = new EqualExpression; node.left = shift is null ? parseShiftExpression() : shift; if (currentIsOneOf(TokenType.equal, TokenType.notEqual)) @@ -1909,9 +1911,24 @@ class ClassFour(A, B) if (someTest()) : Super {}}; */ Expression parseExpression() { - return parseCommaSeparatedRule!(AssignExpression)(); + return parseCommaSeparatedRule!(Expression, AssignExpression)(); } + /** + * Parses an ExpressionStatement + * + * $(GRAMMAR $(RULEDEF expressionStatement): + * $(RULE expression) $(LITERAL ';') + * ;) + */ + ExpressionStatement parseExpressionStatement(Expression expression = null) + { + auto node = new ExpressionStatement; + node.expression = expression is null ? parseExpression() : expression; + expect(TokenType.semicolon); + return node; + } + /** * Parses a FinalSwitchStatement * @@ -2022,7 +2039,7 @@ class ClassFour(A, B) if (someTest()) : Super {}}; FunctionAttribute parseFunctionAttribute() { auto node = new FunctionAttribute; - with (TokenType) switch (curent().type) + with (TokenType) switch (current().type) { case at: node.atAttribute = parseAtAttribute(); @@ -2125,10 +2142,10 @@ body {} // six * $(RULE unaryExpression) $(RULE templateArguments)? $(RULE arguments) * ;) */ - FunctionCallExpression parseFunctionCallExpression() + FunctionCallExpression parseFunctionCallExpression(UnaryExpression unary = null) { auto node = new FunctionCallExpression; - node.unaryExpression = parseUnaryExpression(); + node.unaryExpression = unary is null ? parseUnaryExpression() : unary; if (currentIs(TokenType.not)) node.templateArguments = parseTemplateArguments(); node.arguments = parseArguments(); @@ -2246,6 +2263,9 @@ body {} // six node.token = advance(); node.expression = parseExpression(); break; + default: + error(`Identifier, "default", or "case" expected`); + return null; } expect(TokenType.semicolon); return node; @@ -2275,7 +2295,7 @@ body {} // six return node; } - unittest + unittest // TODO { auto input = cast(ubyte[]) "abcde.frocegu.creou.faowe"c; LexerConfig config; @@ -2370,7 +2390,7 @@ body {} // six * Parses an IfStatement * * $(GRAMMAR $(RULEDEF ifStatement): - * $(LITERAL 'if') $(LITERAL '$(LPAREN)') $(RULE expression) $(LITERAL '$(RPAREN)') $(RULE nonEmptyStatementNoCaseNoDefault) ($(LITERAL 'else') $(RULE nonEmptyStatementNoCaseNoDefault))? + * $(LITERAL 'if') $(LITERAL '$(LPAREN)') $(RULE expression) $(LITERAL '$(RPAREN)') $(RULE statementNoCaseNoDefault) ($(LITERAL 'else') $(RULE statementNoCaseNoDefault))? * ;) */ IfStatement parseIfStatement() @@ -2380,7 +2400,12 @@ body {} // six expect(TokenType.lParen); node.expression = parseExpression(); expect(TokenType.rParen); - node.statementNoCaseNoDefault = parseStatementNoCaseNoDefault(); + node.thenStatement = parseStatementNoCaseNoDefault(); + if (currentIs(TokenType.else_)) + { + advance(); + node.elseStatement = parseStatementNoCaseNoDefault(); + } return node; } @@ -2834,7 +2859,7 @@ invariant() foo(); auto node = new LastCatch; if (expect(TokenType.catch_) is null) return null; if ((node.statementNoCaseNoDefault = parseStatementNoCaseNoDefault()) is null) - return null;; + return null; return node; } @@ -2940,7 +2965,7 @@ invariant() foo(); { Module m = new Module; if (currentIs(TokenType.module_)) - node.moduleDeclaration = parseModuleDeclaration(); + m.moduleDeclaration = parseModuleDeclaration(); while (moreTokens()) { auto declaration = parseDeclaration(); @@ -2975,6 +3000,7 @@ invariant() foo(); */ MulExpression parseMulExpression() { + version(verbose) writeln("parseMulExpression"); return parseLeftAssocBinaryExpression!(MulExpression, UnaryExpression, TokenType.star, TokenType.div, TokenType.mod)(); } @@ -2994,7 +3020,7 @@ invariant() foo(); node.allocatorArguments = parseArguments(); expect(TokenType.class_); if (!currentIs(TokenType.lBrace)) - node.baseClassList = parseBaseClassList + node.baseClassList = parseBaseClassList; node.classBody = parseClassBody(); return node; } @@ -3010,7 +3036,7 @@ invariant() foo(); NewExpression parseNewExpression() { auto node = new NewExpression; - if (peekIsOneOf(TokenType.class_ TokenType.lParen)) + if (peekIsOneOf(TokenType.class_, TokenType.lParen)) node.newAnonClassExpression = parseNewAnonClassExpression(); else { @@ -3145,13 +3171,10 @@ invariant() foo(); case asm_: node.asmStatement = parseAsmStatement(); break; - case assert_: - node.assertStatement = parseAssertStatement(); - break; case delete_: - node.deleteStatement = parseDeleteStatement(); - break; + case assert_: default: + node.expressionStatement = parseExpressionStatement(); break; // TODO: assignStatement // TODO: finalSwitchStatement @@ -3211,6 +3234,7 @@ invariant() foo(); */ OrExpression parseOrExpression() { + version(verbose) writeln("parseOrExpression"); return parseLeftAssocBinaryExpression!(OrExpression, XorExpression, TokenType.bitOr)(); } @@ -3225,6 +3249,7 @@ invariant() foo(); */ OrOrExpression parseOrOrExpression() { + version(verbose) writeln("parseOrOrExpression"); return parseLeftAssocBinaryExpression!(OrOrExpression, AndAndExpression, TokenType.logicOr)(); } @@ -3260,7 +3285,27 @@ invariant() foo(); Parameter parseParameter() { auto node = new Parameter; - // TODO + while (moreTokens()) + { + TokenType type = parseParameterAttribute(false); + if (type == TokenType.invalid) + break; + else + node.parameterAttributes ~= type; + } + node.type = parseType(); + if (node.type is null) return null; + if (currentIs(TokenType.identifier)) + { + node.name = advance(); + if (currentIs(TokenType.vararg)) + node.vararg = true; + else if (currentIs(TokenType.assign)) + { + advance(); + node.default_ = parseAssignExpression(); + } + } return node; } @@ -3278,29 +3323,90 @@ invariant() foo(); * | $(LITERAL 'auto') * ;) */ - ParameterAttribute parseParameterAttribute() + TokenType parseParameterAttribute(bool validate = false) { - auto node = new ParameterAttribute; - // TODO - return node; + with (TokenType) switch (current().type) + { + case immutable_: + case shared_: + case const_: + case inout_: + case final_: + case in_: + case lazy_: + case out_: + case ref_: + case scope_: + case auto_: + return advance().type; + default: + if (validate) error("Parameter attribute expected"); + return invalid; + } } /** * Parses Parameters * * $(GRAMMAR $(RULEDEF parameters): - * $(LITERAL '$(LPAREN)') (($(RULE parameter) ($(LITERAL ',') $(RULE parameter))*)? ($(LITERAL ',') $(LITERAL '...'))? | $(LITERAL '...')) $(LITERAL '$(RPAREN)') + * $(LITERAL '$(LPAREN)') $(RULE parameter) ($(LITERAL ',') $(RULE parameter))* ($(LITERAL ',') $(LITERAL '...'))? $(LITERAL '$(RPAREN)') + * | $(LITERAL '$(LPAREN)') $(LITERAL '...') $(LITERAL '$(RPAREN)') + * | $(LITERAL '$(LPAREN)') $(LITERAL '$(RPAREN)') * ;) */ Parameters parseParameters() { auto node = new Parameters; expect(TokenType.lParen); - version(development) skipParenContent(); + if (currentIs(TokenType.rParen)) + goto end; + if (currentIs(TokenType.vararg)) + { + node.hasVarargs = true; + goto end; + } + while (moreTokens()) + { + if (currentIs(TokenType.vararg)) + { + node.hasVarargs = true; + break; + } + if (currentIs(TokenType.rParen)) + break; + auto param = parseParameter(); + if (param is null) + break; + node.parameters ~= param; + if (currentIs(TokenType.comma)) + advance(); + else + break; + } + end: expect(TokenType.rParen); return node; } + unittest + { + string sourceCode = +q{(int a, ...) +(double ...)}c; + + Parser p = getParserForUnittest(sourceCode, "parseParameters"); + + Parameters params1 = p.parseParameters(); + assert (params1.hasVarargs); + assert (params1.paramaters.length == 1); + assert (params1.paramaters[0].name == "a"); + + Parameters params2 = p.parseParameters(); + assert (params2.paramaters.length == 1); + assert (params2.paramaters[0].vararg); + assert (params2.paramaters[0].type !is null); + } + /** * Parses a Postblit * @@ -3449,6 +3555,7 @@ invariant() foo(); */ PrimaryExpression parsePrimaryExpression() { + version(verbose) writeln("parsePrimaryExpression"); auto node = new PrimaryExpression; with (TokenType) switch (current().type) { @@ -3491,8 +3598,12 @@ invariant() foo(); case false_: case specialDate: .. case specialPrettyFunction: case doubleLiteral: .. case wstringLiteral: - primary = advance(); + version(verbose) writeln("special or literal ", index, " ", current()); + node.primary = advance(); break; + default: + error(`Primary expression expected`); + return null; } return node; } @@ -3635,6 +3746,7 @@ invariant() foo(); */ ShiftExpression parseShiftExpression() { + version(verbose) writeln("parseShiftExpression"); return parseLeftAssocBinaryExpression!(ShiftExpression, AddExpression, TokenType.shiftLeft, TokenType.shiftRight, TokenType.unsignedShiftRight)(); @@ -3702,22 +3814,7 @@ invariant() foo(); StaticAssertDeclaration parseStaticAssertDeclaration() { auto node = new StaticAssertDeclaration; - node.staticAssertStatement = parseStaticAssertStatement(); - return node; - } - - /** - * Parses a StaticAssertStatement - * - * $(GRAMMAR $(RULEDEF staticAssertStatement): - * $(LITERAL 'static') $(RULE assertStatement) - * ;) - */ - StaticAssertStatement parseStaticAssertStatement() - { - auto node = new StaticAssertStatement; - expect(TokenType.static_); - node.assertStatement = parseAssertStatement(); + // TODO return node; } @@ -3840,7 +3937,7 @@ invariant() foo(); if (currentIs(TokenType.invariant_)) node.invariant_ = parseInvariant(); else if (startsWith(TokenType.this_, TokenType.lParen, TokenType.this_)) - node.postBlit = parsePostblit(); + node.postblit = parsePostblit(); else node.declaration = parseDeclaration(); return node; @@ -4081,12 +4178,12 @@ invariant() foo(); expect(TokenType.template_); node.identifier = *expect(TokenType.identifier); node.templateParameters = parseTemplateParameters(); - if (currentIs(TokenType.if_)); + if (currentIs(TokenType.if_)) node.constraint = parseConstraint(); expect(TokenType.lBrace); do node.declarations ~= parseDeclaration(); - while (!currentIs(TokenType.rBrace)) + while (!currentIs(TokenType.rBrace)); expect(TokenType.rBrace); return node; } @@ -4116,7 +4213,13 @@ invariant() foo(); TemplateMixinStatement parseTemplateMixinStatement() { auto node = new TemplateMixinStatement; - // TODO + expect(TokenType.mixin_); + node.mixinTemplateName = parseMixinTemplateName(); + if (currentIs(TokenType.not)) + node.templateArguments = parseTemplateArguments(); + if (currentIs(TokenType.identifier)) + node.identifier = advance(); + expect(TokenType.semicolon); return node; } @@ -4147,10 +4250,8 @@ invariant() foo(); */ TemplateParameterList parseTemplateParameterList() { - auto node = new TemplateParameterList; - // TODO - return node; - } + return parseCommaSeparatedRule!(TemplateParameterList, TemplateParameter)(); + } /** * Parses TemplateParameters @@ -4163,8 +4264,10 @@ invariant() foo(); { auto node = new TemplateParameters; expect(TokenType.lParen); - // TODO - version (development) skipParenContent(); + version (development) + skipParenContent(); + else + node.templateParameterList = parseTemplateParameterList(); expect(TokenType.rParen); return node; } @@ -4198,7 +4301,22 @@ invariant() foo(); TemplateSingleArgument parseTemplateSingleArgument() { auto node = new TemplateSingleArgument; - // TODO + with (TokenType) switch (current().type) + { + case true_: + case false_: + case null_: + case this_: + case identifier: + case specialDate: .. case specialTokenSequence: + case doubleLiteral: .. case wstringLiteral: + case bool_: .. case wchar_: + node.token = advance(); + break; + default: + error(`Invalid template argument. (Try enclosing in parenthesis?)`); + return null; + } return node; } @@ -4212,7 +4330,8 @@ invariant() foo(); TemplateThisParameter parseTemplateThisParameter() { auto node = new TemplateThisParameter; - // TODO + expect(TokenType.this_); + node.templateTypeParameter = parseTemplateTypeParameter(); return node; } @@ -4294,6 +4413,7 @@ invariant() foo(); */ TernaryExpression parseTernaryExpression() { + version(verbose) writeln("parseTernaryExpression"); auto node = new TernaryExpression; node.orOrExpression = parseOrOrExpression(); if (currentIs(TokenType.ternary)) @@ -4395,7 +4515,8 @@ invariant() foo(); case TokenType.immutable_: case TokenType.inout_: case TokenType.shared_: - node.typeConstructors = parseTypeConstructors(); + if (!peekIs(TokenType.lParen)) + node.typeConstructors = parseTypeConstructors(); break; default: break; @@ -4474,11 +4595,20 @@ invariant() foo(); * | $(LITERAL 'shared') * ;) */ - TypeConstructor parseTypeConstructor() + TokenType parseTypeConstructor(bool validate = false) { - auto node = new TypeConstructor; - // TODO - return node; + with (TokenType) switch (current().type) + { + case const_: + case immutable_: + case inout_: + case shared_: + return advance().type; + default: + if (validate) + error(`"const", "immutable", "inout", or "shared" expected`); + return invalid; + } } /** @@ -4488,11 +4618,18 @@ invariant() foo(); * $(RULE typeConstructor)+ * ;) */ - TypeConstructors parseTypeConstructors() + TokenType[] parseTypeConstructors() { - auto node = new TypeConstructors; - // TODO - return node; + TokenType[] r; + while (moreTokens()) + { + TokenType type = parseTypeConstructor(false); + if (type == TokenType.invalid) + break; + else + r ~= type; + } + return r; } /** @@ -4519,7 +4656,27 @@ invariant() foo(); TypeSpecialization parseTypeSpecialization() { auto node = new TypeSpecialization; - // TODO + with (TokenType) switch (current().type) + { + case struct_: + case union_: + case interface_: + case enum_: + case function_: + case delegate_: + case super_: + case const_: + case immutable_: + case inout_: + case shared_: + case return_: + case parameters: + node.token = advance(); + break; + default: + node.type = parseType(); + break; + } return node; } @@ -4607,58 +4764,90 @@ invariant() foo(); * | $(LITERAL '+') $(RULE unaryExpression) * | $(LITERAL '-') $(RULE unaryExpression) * | $(LITERAL '~') $(RULE unaryExpression) + * | $(LITERAL '++') $(RULE unaryExpression) + * | $(LITERAL '--') $(RULE unaryExpression) * | $(RULE newExpression) * | $(RULE deleteExpression) * | $(RULE castExpression) + * | $(RULE assertExpression) * | $(RULE functionCallExpression) - * | $(RULE preIncDecExpression) - * | $(RULE postIncDecExpression) * | $(RULE sliceExpression) * | $(RULE indexExpression) * | $(RULE unaryExpression) $(LITERAL '.') $(RULE identifierOrTemplateInstance) - * | $(RULE assertExpression) + * | $(RULE unaryExpression) ($(LITERAL '--') + * | $(RULE unaryExpression) ($(LITERAL '++') * ;) */ UnaryExpression parseUnaryExpression() { + version(verbose) writeln("parseUnaryExpression"); auto node = new UnaryExpression; - switch (current().type) + with(TokenType) switch (current().type) { - case TokenType.bitAnd: - case TokenType.not: - case TokenType.star: - case TokenType.plus: - case TokenType.minus: - case TokenType.tilde: - node.prefix = advance; + case bitAnd: + case not: + case star: + case plus: + case minus: + case tilde: + case increment: + case decrement: + node.prefix = advance(); node.unaryExpression = parseUnaryExpression(); return node; - case TokenType.new_: + case new_: node.newExpression = parseNewExpression(); return node; - case TokenType.delete_: + case delete_: node.deleteExpression = parseDeleteExpression(); return node; - case TokenType.cast_: + case cast_: node.castExpression = parseCastExpression; return node; - case TokenType.increment: - case TokenType.decrement: - node.preIncDecExpression = parsePreIncDecExpression(); - return node; - case TokenType.assert_: + case assert_: node.assertExpression = parseAssertExpression(); return node; - default: - // TODO: - // primary - // functionCall - // postIncDec - // slice - // index - // unary.identifierOrTemplateInstance - return node; + default: + node.primaryExpression = parsePrimaryExpression(); } + + loop: while (true) with (TokenType) switch (current().type) + { + case not: + index++; + bool jump = peekPastParens().type == TokenType.lParen; + index--; + if (jump) + goto case lParen; + else + { + error(`Function call expected`); + return null; + } + case lParen: + auto n = new UnaryExpression(); + n.functionCallExpression = parseFunctionCallExpression(node); + node = n; + break; + case increment: + case decrement: + auto n = new UnaryExpression(); + n.unaryExpression = node; + n.suffix = advance(); + node = n; + break; + case lBracket: + assert (false); + case dot: + advance(); + auto n = new UnaryExpression(); + n.unaryExpression = node; + n.identifierOrTemplateInstance = parseIdentifierOrTemplateInstance(); + break; + default: + break loop; + } + return node; } /** @@ -4833,6 +5022,7 @@ invariant() foo(); */ XorExpression parseXorExpression() { + version(verbose) writeln("parseXorExpression"); return parseLeftAssocBinaryExpression!(XorExpression, AndExpression, TokenType.xor)(); } diff --git a/std/d/tester.d b/std/d/tester.d index 5382152..ece38df 100644 --- a/std/d/tester.d +++ b/std/d/tester.d @@ -24,8 +24,11 @@ class TestVisitor : ASTVisitor override void visit(VariableDeclaration varDec) { - writeln("variable ", varDec.declarators[0].identifier.value, - " on line ", varDec.declarators[0].identifier.line); + foreach (decl; varDec.declarators) + { + writeln("variable ", decl.identifier.value, + " on line ", decl.identifier.line); + } } override void visit(ImportDeclaration impDec)