Unary and Primary expression parsing

This commit is contained in:
Hackerpilot 2013-06-24 02:33:40 +00:00
parent 38105d542f
commit 1beef6a901
4 changed files with 335 additions and 164 deletions

View File

@ -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;
}

View File

@ -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,
"=",
"@",
"&",

View File

@ -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)();
}

View File

@ -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)