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(BreakStatement breakStatement) { breakStatement.accept(this); }
/** */ void visit(BaseClass baseClass) { baseClass.accept(this); } /** */ void visit(BaseClass baseClass) { baseClass.accept(this); }
/** */ void visit(BaseClassList baseClassList) { baseClassList.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(CaseRangeStatement caseRangeStatement) { caseRangeStatement.accept(this); }
/** */ void visit(CaseStatement caseStatement) { caseStatement.accept(this); } /** */ void visit(CaseStatement caseStatement) { caseStatement.accept(this); }
/** */ void visit(CastExpression castExpression) { castExpression.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(EnumMember enumMember) { enumMember.accept(this); }
/** */ void visit(EqualExpression equalExpression) { equalExpression.accept(this); } /** */ void visit(EqualExpression equalExpression) { equalExpression.accept(this); }
/** */ void visit(Expression expression) { expression.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(FinalSwitchStatement finalSwitchStatement) { finalSwitchStatement.accept(this); }
/** */ void visit(Finally finally_) { finally_.accept(this); } /** */ void visit(Finally finally_) { finally_.accept(this); }
/** */ void visit(ForStatement forStatement) { forStatement.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(OrOrExpression orOrExpression) { orOrExpression.accept(this); }
/** */ void visit(OutStatement outStatement) { outStatement.accept(this); } /** */ void visit(OutStatement outStatement) { outStatement.accept(this); }
/** */ void visit(Parameter parameter) { parameter.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(Parameters parameters) { parameters.accept(this); }
/** */ void visit(Postblit postblit) { postblit.accept(this); } /** */ void visit(Postblit postblit) { postblit.accept(this); }
/** */ void visit(PostIncDecExpression postIncDecExpression) { postIncDecExpression.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(TryStatement tryStatement) { tryStatement.accept(this); }
/** */ void visit(Type type) { type.accept(this); } /** */ void visit(Type type) { type.accept(this); }
/** */ void visit(Type2 type2) { type2.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(TypeConstructors typeConstructors) { typeConstructors.accept(this); }
/** */ void visit(TypeSpecialization typeSpecialization) { typeSpecialization.accept(this); } /** */ void visit(TypeSpecialization typeSpecialization) { typeSpecialization.accept(this); }
/** */ void visit(TypeSuffix typeSuffix) { typeSuffix.accept(this); } /** */ void visit(TypeSuffix typeSuffix) { typeSuffix.accept(this); }
@ -653,15 +651,7 @@ class BaseClassList : ASTNode
{ {
public: public:
mixin(DEFAULT_ACCEPT); mixin(DEFAULT_ACCEPT);
/** */ BaseClass[] baseClasses; /** */ BaseClass[] items;
}
///
class BasicType : ASTNode
{
public:
mixin(DEFAULT_ACCEPT);
/** */ TokenType type;
} }
/// ///
@ -1005,6 +995,14 @@ public:
/** */ AssignExpression[] items; /** */ AssignExpression[] items;
} }
///
class ExpressionStatement : ASTNode
{
public:
mixin(DEFAULT_ACCEPT);
/** */ Expression expression;
}
/// ///
class FinalSwitchStatement : ASTNode class FinalSwitchStatement : ASTNode
{ {
@ -1070,7 +1068,7 @@ class ForeachTypeList : ASTNode
{ {
public: public:
mixin(DEFAULT_ACCEPT); mixin(DEFAULT_ACCEPT);
/** */ ForeachType[] foreachTypes; /** */ ForeachType[] items;
} }
/// ///
@ -1078,7 +1076,7 @@ class FunctionAttribute : ASTNode
{ {
public: public:
mixin(DEFAULT_ACCEPT); mixin(DEFAULT_ACCEPT);
/** */ Token pureOrNothrow; /** */ Token token;
/** */ AtAttribute atAttribute; /** */ AtAttribute atAttribute;
} }
@ -1130,7 +1128,7 @@ class FunctionLiteralExpression : ASTNode
{ {
public: public:
mixin(DEFAULT_ACCEPT); mixin(DEFAULT_ACCEPT);
/** */ Token functionOrDelegate; /** */ TokenType functionOrDelegate;
/** */ Type type; /** */ Type type;
/** */ Parameters parameters; /** */ Parameters parameters;
/** */ FunctionAttribute[] functionAttributes; /** */ FunctionAttribute[] functionAttributes;
@ -1503,12 +1501,11 @@ public:
/** */ ForeachRangeStatement foreachRangeStatement; /** */ ForeachRangeStatement foreachRangeStatement;
/** */ ConditionalStatement conditionalStatement; /** */ ConditionalStatement conditionalStatement;
/** */ StaticAssertStatement staticAssertStatement; /** */ StaticAssertStatement staticAssertStatement;
/** */ AssertStatement assertStatement;
/** */ TemplateMixinStatement templateMixinStatement; /** */ TemplateMixinStatement templateMixinStatement;
/** */ VersionSpecification versionSpecification; /** */ VersionSpecification versionSpecification;
/** */ DebugSpecification debugSpecification; /** */ DebugSpecification debugSpecification;
/** */ FunctionCallStatement functionCallStatement; /** */ FunctionCallStatement functionCallStatement;
/** */ DeleteStatement deleteStatement; /** */ ExpressionStatement expressionStatement;
} }
/// ///
@ -1570,19 +1567,11 @@ class Parameter : ASTNode
{ {
public: public:
mixin(DEFAULT_ACCEPT); mixin(DEFAULT_ACCEPT);
/** */ ParameterAttribute[] paramaterAttributes; /** */ TokenType[] parameterAttributes;
/** */ Type type; /** */ Type type;
/** */ Token name; /** */ Token name;
/** */ bool vararg; /** */ bool vararg;
} /** */ AssignExpression default_;
///
class ParameterAttribute: ASTNode
{
public:
mixin(DEFAULT_ACCEPT);
/** */ Token attribute;
/** */ TypeConstructor typeConstructor;
} }
/// ///
@ -1590,7 +1579,7 @@ class Parameters : ASTNode
{ {
public: public:
mixin(DEFAULT_ACCEPT); mixin(DEFAULT_ACCEPT);
/** */ Parameter[] paramaters; /** */ Parameter[] parameters;
/** */ bool hasVarargs; /** */ bool hasVarargs;
} }
@ -1673,7 +1662,7 @@ class Register : ASTNode
public: public:
mixin(DEFAULT_ACCEPT); mixin(DEFAULT_ACCEPT);
/** */ Token identifier; /** */ Token identifier;
/** */ Token integerLiteral; /** */ Token intLiteral;
/** */ bool hasIntegerLiteral; /** */ bool hasIntegerLiteral;
} }
@ -1805,8 +1794,7 @@ class StorageClass : ASTNode
public: public:
mixin(DEFAULT_ACCEPT); mixin(DEFAULT_ACCEPT);
/** */ AtAttribute atAttribute; /** */ AtAttribute atAttribute;
/** */ TypeConstructor typeConstructor; /** */ Token token;
/** */ Token storageClass;
} }
/// ///
@ -1927,7 +1915,7 @@ class TemplateArgumentList : ASTNode
{ {
public: public:
mixin(DEFAULT_ACCEPT); mixin(DEFAULT_ACCEPT);
/** */ TemplateArgument[] templateArguments; /** */ TemplateArgument[] items;
} }
/// ///
@ -1955,7 +1943,7 @@ class TemplateInstance : ASTNode
{ {
public: public:
mixin(DEFAULT_ACCEPT); mixin(DEFAULT_ACCEPT);
/** */ Token identifier; /** */ Symbol symbol;
/** */ TemplateArguments templateArguments; /** */ TemplateArguments templateArguments;
} }
@ -1986,7 +1974,7 @@ class TemplateParameterList : ASTNode
{ {
public: public:
mixin(DEFAULT_ACCEPT); mixin(DEFAULT_ACCEPT);
/** */ TemplateParameter[] templateParameters; /** */ TemplateParameter[] items;
} }
/// ///
@ -2003,7 +1991,6 @@ class TemplateSingleArgument : ASTNode
public: public:
mixin(DEFAULT_ACCEPT); mixin(DEFAULT_ACCEPT);
/** */ Token token; /** */ Token token;
/** */ BasicType builtinType;
} }
/// ///
@ -2103,7 +2090,7 @@ class Type : ASTNode
{ {
public: public:
mixin(DEFAULT_ACCEPT); mixin(DEFAULT_ACCEPT);
/** */ TypeConstructors typeConstructors; /** */ TokenType[] typeConstructors;
/** */ TypeSuffix[] typeSuffixes; /** */ TypeSuffix[] typeSuffixes;
/** */ Type2 type2; /** */ Type2 type2;
} }
@ -2113,28 +2100,20 @@ class Type2 : ASTNode
{ {
public: public:
mixin(DEFAULT_ACCEPT); mixin(DEFAULT_ACCEPT);
/** */ BasicType basicType; /** */ Token basicType;
/** */ Symbol symbol; /** */ Symbol symbol;
/** */ TypeofExpression typeofExpression; /** */ TypeofExpression typeofExpression;
/** */ IdentifierOrTemplateChain identifierOrTemplateChain; /** */ IdentifierOrTemplateChain identifierOrTemplateChain;
/** */ TypeConstructor typeConstructor; /** */ TokenType typeConstructor;
/** */ Type type; /** */ Type type;
} }
///
class TypeConstructor : ASTNode
{
public:
mixin(DEFAULT_ACCEPT);
/** */ Token typeConstructor;
}
/// ///
class TypeConstructors : ASTNode class TypeConstructors : ASTNode
{ {
public: public:
mixin(DEFAULT_ACCEPT); mixin(DEFAULT_ACCEPT);
/** */ TypeConstructor[] typeConstructors; /** */ TokenType[] items;
} }
/// ///
@ -2183,17 +2162,14 @@ class UnaryExpression : ASTNode
public: public:
mixin(DEFAULT_ACCEPT); mixin(DEFAULT_ACCEPT);
/** */ PrimaryExpression primaryExpression; /** */ PrimaryExpression primaryExpression;
/** */ UnaryExpression unaryExpression;
/** */ Token prefix; /** */ Token prefix;
/** */ PreIncDecExpression preIncDecExpression; /** */ Token suffix;
/** */ PostIncDecExpression postIncDecExpression; /** */ UnaryExpression unaryExpression;
/** */ NewExpression newExpression; /** */ NewExpression newExpression;
/** */ DeleteExpression deleteExpression; /** */ DeleteExpression deleteExpression;
/** */ CastExpression castExpression; /** */ CastExpression castExpression;
/** */ FunctionCallExpression functionCallExpression; /** */ FunctionCallExpression functionCallExpression;
/** */ ArgumentList argumentList; /** */ ArgumentList argumentList;
/** */ AssignExpression low;
/** */ AssignExpression high;
/** */ IdentifierOrTemplateInstance identifierOrTemplateInstance; /** */ IdentifierOrTemplateInstance identifierOrTemplateInstance;
/** */ AssertExpression assertExpression; /** */ AssertExpression assertExpression;
} }

View File

@ -2009,6 +2009,7 @@ pure nothrow bool isMisc(ref const Token t)
*/ */
enum TokenType: ushort enum TokenType: ushort
{ {
invalid, /// Not a valid token
assign, /// = assign, /// =
at, /// @ at, /// @
bitAnd, /// & bitAnd, /// &
@ -2506,6 +2507,7 @@ bool isRangeEoF(R)(ref R range)
// Lookup table for token values // Lookup table for token values
package immutable(string[TokenType.max + 1]) tokenValues = [ package immutable(string[TokenType.max + 1]) tokenValues = [
null,
"=", "=",
"@", "@",
"&", "&",

View File

@ -56,7 +56,7 @@
* MACROS: * MACROS:
* GRAMMAR = $(D_CODE $0) * GRAMMAR = $(D_CODE $0)
* RULEDEF = $(DDOC_ANCHOR $0) $(B $0) * RULEDEF = $(DDOC_ANCHOR $0) $(B $0)
* RULE = $(LINK2 #.$0, $(B $0)) * RULE = $(LINK2 #$0, $(B $0))
* LITERAL = $(D_STRING $0) * LITERAL = $(D_STRING $0)
*/ */
@ -70,7 +70,9 @@ import std.array;
version (unittest) import std.stdio; version (unittest) import std.stdio;
version = development; version = development;
//version = verbose;
version(development) import std.stdio; version(development) import std.stdio;
version(verbose) import std.stdio;
// TODO: any place that says *expect(...) needs to be fixed // TODO: any place that says *expect(...) needs to be fixed
@ -101,6 +103,7 @@ struct Parser
*/ */
AddExpression parseAddExpression() AddExpression parseAddExpression()
{ {
version(verbose) writeln("parseAddExpression");
return parseLeftAssocBinaryExpression!(AddExpression, MulExpression, return parseLeftAssocBinaryExpression!(AddExpression, MulExpression,
TokenType.plus, TokenType.minus, TokenType.tilde)(); TokenType.plus, TokenType.minus, TokenType.tilde)();
} }
@ -182,6 +185,7 @@ struct Parser
*/ */
AndAndExpression parseAndAndExpression() AndAndExpression parseAndAndExpression()
{ {
version(verbose) writeln("parseAndAndExpression");
return parseLeftAssocBinaryExpression!(AndAndExpression, OrExpression, return parseLeftAssocBinaryExpression!(AndAndExpression, OrExpression,
TokenType.logicAnd)(); TokenType.logicAnd)();
} }
@ -196,6 +200,7 @@ struct Parser
*/ */
AndExpression parseAndExpression() AndExpression parseAndExpression()
{ {
version(verbose) writeln("parseAndExpression");
return parseLeftAssocBinaryExpression!(AndExpression, CmpExpression, return parseLeftAssocBinaryExpression!(AndExpression, CmpExpression,
TokenType.bitAnd)(); TokenType.bitAnd)();
} }
@ -605,6 +610,7 @@ struct Parser
*/ */
AssignExpression parseAssignExpression() AssignExpression parseAssignExpression()
{ {
version(verbose) writeln("parseAssignExpression");
auto node = new AssignExpression; auto node = new AssignExpression;
node.ternaryExpression = parseTernaryExpression(); node.ternaryExpression = parseTernaryExpression();
if (currentIsOneOf(TokenType.assign, TokenType.unsignedShiftRightEqual, if (currentIsOneOf(TokenType.assign, TokenType.unsignedShiftRightEqual,
@ -630,12 +636,7 @@ struct Parser
AssignStatement parseAssignStatement() AssignStatement parseAssignStatement()
{ {
auto node = new AssignStatement; auto node = new AssignStatement;
if (currentIsOneOf(TokenType.increment, TokenType.decrement))
node.preIncDecExpression = parsePreIncDecExpression();
else
{
// TODO // TODO
}
expect(TokenType.semicolon); expect(TokenType.semicolon);
return node; return node;
} }
@ -676,9 +677,12 @@ struct Parser
node.identifier = advance(); node.identifier = advance();
break; break;
case lParen: case lParen:
node.argumentlist = parseArgumentList(); node.argumentList = parseArgumentList();
expect(rParen); expect(rParen);
break; break;
default:
error(`"(", or identifier expected`);
return null;
} }
return node; return node;
} }
@ -814,9 +818,9 @@ struct Parser
{ {
auto node = new BlockStatement(); auto node = new BlockStatement();
expect(TokenType.lBrace); expect(TokenType.lBrace);
skipBraceContent(); version (development) skipBraceContent();
//if (!currentIs(TokenType.rBrace)) if (!currentIs(TokenType.rBrace))
// node.declarationsAndStatements = parseDeclarationsAndStatements(); node.declarationsAndStatements = parseDeclarationsAndStatements();
expect(TokenType.rBrace); expect(TokenType.rBrace);
return node; return node;
} }
@ -922,17 +926,13 @@ struct Parser
* | $(LITERAL 'void') * | $(LITERAL 'void')
* ;) * ;)
*/ */
BasicType parseBasicType() Token parseBasicType()
{ {
auto node = new BasicType;
if (isBasicType(current().type)) if (isBasicType(current().type))
node.type = advance().type; return advance();
else
{
error("Basic type expected"); error("Basic type expected");
return null; Token t;
} return t;
return node;
} }
/** /**
@ -1278,6 +1278,7 @@ class ClassFour(A, B) if (someTest()) : Super {}};
*/ */
CmpExpression parseCmpExpression() CmpExpression parseCmpExpression()
{ {
version(verbose) writeln("parseCmpExpression");
auto node = new CmpExpression; auto node = new CmpExpression;
auto shift = parseShiftExpression(); auto shift = parseShiftExpression();
with (TokenType) switch (current().type) with (TokenType) switch (current().type)
@ -1375,7 +1376,7 @@ class ClassFour(A, B) if (someTest()) : Super {}};
auto node = new ConditionalStatement; auto node = new ConditionalStatement;
node.compileCondition = parseCompileCondition(); node.compileCondition = parseCompileCondition();
node.trueStatement = parseStatementNoCaseNoDefault(); node.trueStatement = parseStatementNoCaseNoDefault();
if (currentIs(TokenType.else)) if (currentIs(TokenType.else_))
{ {
advance(); advance();
node.falseStatement = parseStatementNoCaseNoDefault(); node.falseStatement = parseStatementNoCaseNoDefault();
@ -1892,6 +1893,7 @@ class ClassFour(A, B) if (someTest()) : Super {}};
*/ */
EqualExpression parseEqualExpression(ShiftExpression shift = null) EqualExpression parseEqualExpression(ShiftExpression shift = null)
{ {
version(verbose) writeln("parseEqualExpression");
auto node = new EqualExpression; auto node = new EqualExpression;
node.left = shift is null ? parseShiftExpression() : shift; node.left = shift is null ? parseShiftExpression() : shift;
if (currentIsOneOf(TokenType.equal, TokenType.notEqual)) if (currentIsOneOf(TokenType.equal, TokenType.notEqual))
@ -1909,7 +1911,22 @@ class ClassFour(A, B) if (someTest()) : Super {}};
*/ */
Expression parseExpression() 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;
} }
/** /**
@ -2022,7 +2039,7 @@ class ClassFour(A, B) if (someTest()) : Super {}};
FunctionAttribute parseFunctionAttribute() FunctionAttribute parseFunctionAttribute()
{ {
auto node = new FunctionAttribute; auto node = new FunctionAttribute;
with (TokenType) switch (curent().type) with (TokenType) switch (current().type)
{ {
case at: case at:
node.atAttribute = parseAtAttribute(); node.atAttribute = parseAtAttribute();
@ -2125,10 +2142,10 @@ body {} // six
* $(RULE unaryExpression) $(RULE templateArguments)? $(RULE arguments) * $(RULE unaryExpression) $(RULE templateArguments)? $(RULE arguments)
* ;) * ;)
*/ */
FunctionCallExpression parseFunctionCallExpression() FunctionCallExpression parseFunctionCallExpression(UnaryExpression unary = null)
{ {
auto node = new FunctionCallExpression; auto node = new FunctionCallExpression;
node.unaryExpression = parseUnaryExpression(); node.unaryExpression = unary is null ? parseUnaryExpression() : unary;
if (currentIs(TokenType.not)) if (currentIs(TokenType.not))
node.templateArguments = parseTemplateArguments(); node.templateArguments = parseTemplateArguments();
node.arguments = parseArguments(); node.arguments = parseArguments();
@ -2246,6 +2263,9 @@ body {} // six
node.token = advance(); node.token = advance();
node.expression = parseExpression(); node.expression = parseExpression();
break; break;
default:
error(`Identifier, "default", or "case" expected`);
return null;
} }
expect(TokenType.semicolon); expect(TokenType.semicolon);
return node; return node;
@ -2275,7 +2295,7 @@ body {} // six
return node; return node;
} }
unittest unittest // TODO
{ {
auto input = cast(ubyte[]) "abcde.frocegu.creou.faowe"c; auto input = cast(ubyte[]) "abcde.frocegu.creou.faowe"c;
LexerConfig config; LexerConfig config;
@ -2370,7 +2390,7 @@ body {} // six
* Parses an IfStatement * Parses an IfStatement
* *
* $(GRAMMAR $(RULEDEF 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() IfStatement parseIfStatement()
@ -2380,7 +2400,12 @@ body {} // six
expect(TokenType.lParen); expect(TokenType.lParen);
node.expression = parseExpression(); node.expression = parseExpression();
expect(TokenType.rParen); expect(TokenType.rParen);
node.statementNoCaseNoDefault = parseStatementNoCaseNoDefault(); node.thenStatement = parseStatementNoCaseNoDefault();
if (currentIs(TokenType.else_))
{
advance();
node.elseStatement = parseStatementNoCaseNoDefault();
}
return node; return node;
} }
@ -2834,7 +2859,7 @@ invariant() foo();
auto node = new LastCatch; auto node = new LastCatch;
if (expect(TokenType.catch_) is null) return null; if (expect(TokenType.catch_) is null) return null;
if ((node.statementNoCaseNoDefault = parseStatementNoCaseNoDefault()) is null) if ((node.statementNoCaseNoDefault = parseStatementNoCaseNoDefault()) is null)
return null;; return null;
return node; return node;
} }
@ -2940,7 +2965,7 @@ invariant() foo();
{ {
Module m = new Module; Module m = new Module;
if (currentIs(TokenType.module_)) if (currentIs(TokenType.module_))
node.moduleDeclaration = parseModuleDeclaration(); m.moduleDeclaration = parseModuleDeclaration();
while (moreTokens()) while (moreTokens())
{ {
auto declaration = parseDeclaration(); auto declaration = parseDeclaration();
@ -2975,6 +3000,7 @@ invariant() foo();
*/ */
MulExpression parseMulExpression() MulExpression parseMulExpression()
{ {
version(verbose) writeln("parseMulExpression");
return parseLeftAssocBinaryExpression!(MulExpression, UnaryExpression, return parseLeftAssocBinaryExpression!(MulExpression, UnaryExpression,
TokenType.star, TokenType.div, TokenType.mod)(); TokenType.star, TokenType.div, TokenType.mod)();
} }
@ -2994,7 +3020,7 @@ invariant() foo();
node.allocatorArguments = parseArguments(); node.allocatorArguments = parseArguments();
expect(TokenType.class_); expect(TokenType.class_);
if (!currentIs(TokenType.lBrace)) if (!currentIs(TokenType.lBrace))
node.baseClassList = parseBaseClassList node.baseClassList = parseBaseClassList;
node.classBody = parseClassBody(); node.classBody = parseClassBody();
return node; return node;
} }
@ -3010,7 +3036,7 @@ invariant() foo();
NewExpression parseNewExpression() NewExpression parseNewExpression()
{ {
auto node = new NewExpression; auto node = new NewExpression;
if (peekIsOneOf(TokenType.class_ TokenType.lParen)) if (peekIsOneOf(TokenType.class_, TokenType.lParen))
node.newAnonClassExpression = parseNewAnonClassExpression(); node.newAnonClassExpression = parseNewAnonClassExpression();
else else
{ {
@ -3145,13 +3171,10 @@ invariant() foo();
case asm_: case asm_:
node.asmStatement = parseAsmStatement(); node.asmStatement = parseAsmStatement();
break; break;
case assert_:
node.assertStatement = parseAssertStatement();
break;
case delete_: case delete_:
node.deleteStatement = parseDeleteStatement(); case assert_:
break;
default: default:
node.expressionStatement = parseExpressionStatement();
break; break;
// TODO: assignStatement // TODO: assignStatement
// TODO: finalSwitchStatement // TODO: finalSwitchStatement
@ -3211,6 +3234,7 @@ invariant() foo();
*/ */
OrExpression parseOrExpression() OrExpression parseOrExpression()
{ {
version(verbose) writeln("parseOrExpression");
return parseLeftAssocBinaryExpression!(OrExpression, XorExpression, return parseLeftAssocBinaryExpression!(OrExpression, XorExpression,
TokenType.bitOr)(); TokenType.bitOr)();
} }
@ -3225,6 +3249,7 @@ invariant() foo();
*/ */
OrOrExpression parseOrOrExpression() OrOrExpression parseOrOrExpression()
{ {
version(verbose) writeln("parseOrOrExpression");
return parseLeftAssocBinaryExpression!(OrOrExpression, AndAndExpression, return parseLeftAssocBinaryExpression!(OrOrExpression, AndAndExpression,
TokenType.logicOr)(); TokenType.logicOr)();
} }
@ -3260,7 +3285,27 @@ invariant() foo();
Parameter parseParameter() Parameter parseParameter()
{ {
auto node = new Parameter; 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; return node;
} }
@ -3278,29 +3323,90 @@ invariant() foo();
* | $(LITERAL 'auto') * | $(LITERAL 'auto')
* ;) * ;)
*/ */
ParameterAttribute parseParameterAttribute() TokenType parseParameterAttribute(bool validate = false)
{ {
auto node = new ParameterAttribute; with (TokenType) switch (current().type)
// TODO {
return node; 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 * Parses Parameters
* *
* $(GRAMMAR $(RULEDEF 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() Parameters parseParameters()
{ {
auto node = new Parameters; auto node = new Parameters;
expect(TokenType.lParen); 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); expect(TokenType.rParen);
return node; 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 * Parses a Postblit
* *
@ -3449,6 +3555,7 @@ invariant() foo();
*/ */
PrimaryExpression parsePrimaryExpression() PrimaryExpression parsePrimaryExpression()
{ {
version(verbose) writeln("parsePrimaryExpression");
auto node = new PrimaryExpression; auto node = new PrimaryExpression;
with (TokenType) switch (current().type) with (TokenType) switch (current().type)
{ {
@ -3491,8 +3598,12 @@ invariant() foo();
case false_: case false_:
case specialDate: .. case specialPrettyFunction: case specialDate: .. case specialPrettyFunction:
case doubleLiteral: .. case wstringLiteral: case doubleLiteral: .. case wstringLiteral:
primary = advance(); version(verbose) writeln("special or literal ", index, " ", current());
node.primary = advance();
break; break;
default:
error(`Primary expression expected`);
return null;
} }
return node; return node;
} }
@ -3635,6 +3746,7 @@ invariant() foo();
*/ */
ShiftExpression parseShiftExpression() ShiftExpression parseShiftExpression()
{ {
version(verbose) writeln("parseShiftExpression");
return parseLeftAssocBinaryExpression!(ShiftExpression, AddExpression, return parseLeftAssocBinaryExpression!(ShiftExpression, AddExpression,
TokenType.shiftLeft, TokenType.shiftRight, TokenType.shiftLeft, TokenType.shiftRight,
TokenType.unsignedShiftRight)(); TokenType.unsignedShiftRight)();
@ -3702,22 +3814,7 @@ invariant() foo();
StaticAssertDeclaration parseStaticAssertDeclaration() StaticAssertDeclaration parseStaticAssertDeclaration()
{ {
auto node = new StaticAssertDeclaration; auto node = new StaticAssertDeclaration;
node.staticAssertStatement = parseStaticAssertStatement(); // TODO
return node;
}
/**
* Parses a StaticAssertStatement
*
* $(GRAMMAR $(RULEDEF staticAssertStatement):
* $(LITERAL 'static') $(RULE assertStatement)
* ;)
*/
StaticAssertStatement parseStaticAssertStatement()
{
auto node = new StaticAssertStatement;
expect(TokenType.static_);
node.assertStatement = parseAssertStatement();
return node; return node;
} }
@ -3840,7 +3937,7 @@ invariant() foo();
if (currentIs(TokenType.invariant_)) if (currentIs(TokenType.invariant_))
node.invariant_ = parseInvariant(); node.invariant_ = parseInvariant();
else if (startsWith(TokenType.this_, TokenType.lParen, TokenType.this_)) else if (startsWith(TokenType.this_, TokenType.lParen, TokenType.this_))
node.postBlit = parsePostblit(); node.postblit = parsePostblit();
else else
node.declaration = parseDeclaration(); node.declaration = parseDeclaration();
return node; return node;
@ -4081,12 +4178,12 @@ invariant() foo();
expect(TokenType.template_); expect(TokenType.template_);
node.identifier = *expect(TokenType.identifier); node.identifier = *expect(TokenType.identifier);
node.templateParameters = parseTemplateParameters(); node.templateParameters = parseTemplateParameters();
if (currentIs(TokenType.if_)); if (currentIs(TokenType.if_))
node.constraint = parseConstraint(); node.constraint = parseConstraint();
expect(TokenType.lBrace); expect(TokenType.lBrace);
do do
node.declarations ~= parseDeclaration(); node.declarations ~= parseDeclaration();
while (!currentIs(TokenType.rBrace)) while (!currentIs(TokenType.rBrace));
expect(TokenType.rBrace); expect(TokenType.rBrace);
return node; return node;
} }
@ -4116,7 +4213,13 @@ invariant() foo();
TemplateMixinStatement parseTemplateMixinStatement() TemplateMixinStatement parseTemplateMixinStatement()
{ {
auto node = new TemplateMixinStatement; 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; return node;
} }
@ -4147,9 +4250,7 @@ invariant() foo();
*/ */
TemplateParameterList parseTemplateParameterList() TemplateParameterList parseTemplateParameterList()
{ {
auto node = new TemplateParameterList; return parseCommaSeparatedRule!(TemplateParameterList, TemplateParameter)();
// TODO
return node;
} }
/** /**
@ -4163,8 +4264,10 @@ invariant() foo();
{ {
auto node = new TemplateParameters; auto node = new TemplateParameters;
expect(TokenType.lParen); expect(TokenType.lParen);
// TODO version (development)
version (development) skipParenContent(); skipParenContent();
else
node.templateParameterList = parseTemplateParameterList();
expect(TokenType.rParen); expect(TokenType.rParen);
return node; return node;
} }
@ -4198,7 +4301,22 @@ invariant() foo();
TemplateSingleArgument parseTemplateSingleArgument() TemplateSingleArgument parseTemplateSingleArgument()
{ {
auto node = new TemplateSingleArgument; 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; return node;
} }
@ -4212,7 +4330,8 @@ invariant() foo();
TemplateThisParameter parseTemplateThisParameter() TemplateThisParameter parseTemplateThisParameter()
{ {
auto node = new TemplateThisParameter; auto node = new TemplateThisParameter;
// TODO expect(TokenType.this_);
node.templateTypeParameter = parseTemplateTypeParameter();
return node; return node;
} }
@ -4294,6 +4413,7 @@ invariant() foo();
*/ */
TernaryExpression parseTernaryExpression() TernaryExpression parseTernaryExpression()
{ {
version(verbose) writeln("parseTernaryExpression");
auto node = new TernaryExpression; auto node = new TernaryExpression;
node.orOrExpression = parseOrOrExpression(); node.orOrExpression = parseOrOrExpression();
if (currentIs(TokenType.ternary)) if (currentIs(TokenType.ternary))
@ -4395,6 +4515,7 @@ invariant() foo();
case TokenType.immutable_: case TokenType.immutable_:
case TokenType.inout_: case TokenType.inout_:
case TokenType.shared_: case TokenType.shared_:
if (!peekIs(TokenType.lParen))
node.typeConstructors = parseTypeConstructors(); node.typeConstructors = parseTypeConstructors();
break; break;
default: default:
@ -4474,11 +4595,20 @@ invariant() foo();
* | $(LITERAL 'shared') * | $(LITERAL 'shared')
* ;) * ;)
*/ */
TypeConstructor parseTypeConstructor() TokenType parseTypeConstructor(bool validate = false)
{ {
auto node = new TypeConstructor; with (TokenType) switch (current().type)
// TODO {
return node; 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)+ * $(RULE typeConstructor)+
* ;) * ;)
*/ */
TypeConstructors parseTypeConstructors() TokenType[] parseTypeConstructors()
{ {
auto node = new TypeConstructors; TokenType[] r;
// TODO while (moreTokens())
return node; {
TokenType type = parseTypeConstructor(false);
if (type == TokenType.invalid)
break;
else
r ~= type;
}
return r;
} }
/** /**
@ -4519,7 +4656,27 @@ invariant() foo();
TypeSpecialization parseTypeSpecialization() TypeSpecialization parseTypeSpecialization()
{ {
auto node = new TypeSpecialization; 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; return node;
} }
@ -4607,58 +4764,90 @@ invariant() foo();
* | $(LITERAL '+') $(RULE unaryExpression) * | $(LITERAL '+') $(RULE unaryExpression)
* | $(LITERAL '-') $(RULE unaryExpression) * | $(LITERAL '-') $(RULE unaryExpression)
* | $(LITERAL '~') $(RULE unaryExpression) * | $(LITERAL '~') $(RULE unaryExpression)
* | $(LITERAL '++') $(RULE unaryExpression)
* | $(LITERAL '--') $(RULE unaryExpression)
* | $(RULE newExpression) * | $(RULE newExpression)
* | $(RULE deleteExpression) * | $(RULE deleteExpression)
* | $(RULE castExpression) * | $(RULE castExpression)
* | $(RULE assertExpression)
* | $(RULE functionCallExpression) * | $(RULE functionCallExpression)
* | $(RULE preIncDecExpression)
* | $(RULE postIncDecExpression)
* | $(RULE sliceExpression) * | $(RULE sliceExpression)
* | $(RULE indexExpression) * | $(RULE indexExpression)
* | $(RULE unaryExpression) $(LITERAL '.') $(RULE identifierOrTemplateInstance) * | $(RULE unaryExpression) $(LITERAL '.') $(RULE identifierOrTemplateInstance)
* | $(RULE assertExpression) * | $(RULE unaryExpression) ($(LITERAL '--')
* | $(RULE unaryExpression) ($(LITERAL '++')
* ;) * ;)
*/ */
UnaryExpression parseUnaryExpression() UnaryExpression parseUnaryExpression()
{ {
version(verbose) writeln("parseUnaryExpression");
auto node = new UnaryExpression; auto node = new UnaryExpression;
switch (current().type) with(TokenType) switch (current().type)
{ {
case TokenType.bitAnd: case bitAnd:
case TokenType.not: case not:
case TokenType.star: case star:
case TokenType.plus: case plus:
case TokenType.minus: case minus:
case TokenType.tilde: case tilde:
node.prefix = advance; case increment:
case decrement:
node.prefix = advance();
node.unaryExpression = parseUnaryExpression(); node.unaryExpression = parseUnaryExpression();
return node; return node;
case TokenType.new_: case new_:
node.newExpression = parseNewExpression(); node.newExpression = parseNewExpression();
return node; return node;
case TokenType.delete_: case delete_:
node.deleteExpression = parseDeleteExpression(); node.deleteExpression = parseDeleteExpression();
return node; return node;
case TokenType.cast_: case cast_:
node.castExpression = parseCastExpression; node.castExpression = parseCastExpression;
return node; return node;
case TokenType.increment: case assert_:
case TokenType.decrement:
node.preIncDecExpression = parsePreIncDecExpression();
return node;
case TokenType.assert_:
node.assertExpression = parseAssertExpression(); node.assertExpression = parseAssertExpression();
return node; return node;
default: default:
// TODO: node.primaryExpression = parsePrimaryExpression();
// primary
// functionCall
// postIncDec
// slice
// index
// unary.identifierOrTemplateInstance
return node;
} }
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() XorExpression parseXorExpression()
{ {
version(verbose) writeln("parseXorExpression");
return parseLeftAssocBinaryExpression!(XorExpression, AndExpression, return parseLeftAssocBinaryExpression!(XorExpression, AndExpression,
TokenType.xor)(); TokenType.xor)();
} }

View File

@ -24,8 +24,11 @@ class TestVisitor : ASTVisitor
override void visit(VariableDeclaration varDec) override void visit(VariableDeclaration varDec)
{ {
writeln("variable ", varDec.declarators[0].identifier.value, foreach (decl; varDec.declarators)
" on line ", varDec.declarators[0].identifier.line); {
writeln("variable ", decl.identifier.value,
" on line ", decl.identifier.line);
}
} }
override void visit(ImportDeclaration impDec) override void visit(ImportDeclaration impDec)