Now handles all but 11 files

This commit is contained in:
Hackerpilot 2013-07-05 04:08:53 +00:00
parent 4edd57eb12
commit 3acdffdc6b
2 changed files with 186 additions and 249 deletions

View File

@ -60,7 +60,6 @@ abstract class ASTVisitor
/** */ void visit(AssocArrayLiteral assocArrayLiteral) { assocArrayLiteral.accept(this); } /** */ void visit(AssocArrayLiteral assocArrayLiteral) { assocArrayLiteral.accept(this); }
/** */ void visit(AtAttribute atAttribute) { atAttribute.accept(this); } /** */ void visit(AtAttribute atAttribute) { atAttribute.accept(this); }
/** */ void visit(Attribute attribute) { attribute.accept(this); } /** */ void visit(Attribute attribute) { attribute.accept(this); }
/** */ void visit(AttributedDeclaration attributedDeclaration) { attributedDeclaration.accept(this); }
/** */ void visit(AutoDeclaration autoDeclaration) { autoDeclaration.accept(this); } /** */ void visit(AutoDeclaration autoDeclaration) { autoDeclaration.accept(this); }
/** */ void visit(BlockStatement blockStatement) { blockStatement.accept(this); } /** */ void visit(BlockStatement blockStatement) { blockStatement.accept(this); }
/** */ void visit(BodyStatement bodyStatement) { bodyStatement.accept(this); } /** */ void visit(BodyStatement bodyStatement) { bodyStatement.accept(this); }
@ -548,21 +547,6 @@ public:
/** */ Token identifier; /** */ Token identifier;
} }
///
class AttributedDeclaration : ASTNode
{
public:
override void accept(ASTVisitor visitor)
{
if (attribute !is null)
visitor.visit(attribute);
if (declaration !is null)
visitor.visit(declaration);
}
/** */ Attribute attribute;
/** */ Declaration declaration;
}
/// ///
class Attribute : ASTNode class Attribute : ASTNode
{ {
@ -571,17 +555,22 @@ public:
/** */ LinkageAttribute linkageAttribute; /** */ LinkageAttribute linkageAttribute;
/** */ AlignAttribute alignAttribute; /** */ AlignAttribute alignAttribute;
/** */ PragmaExpression pragmaExpression; /** */ PragmaExpression pragmaExpression;
/** */ Deprecated deprecated_; /** */ StorageClass storageClass;
/** */ AtAttribute atAttribute;
/** */ TokenType attribute; /** */ TokenType attribute;
} }
///
class AttributeDeclaration : ASTNode
{
mixin(DEFAULT_ACCEPT);
/** */ Attribute attribute;
}
/// ///
class AutoDeclaration : ASTNode class AutoDeclaration : ASTNode
{ {
public: public:
mixin(DEFAULT_ACCEPT); mixin(DEFAULT_ACCEPT);
/** */ StorageClass storageClass;
/** */ Token[] identifiers; /** */ Token[] identifiers;
/** */ Initializer[] initializers; /** */ Initializer[] initializers;
} }
@ -734,8 +723,8 @@ class ConditionalDeclaration : ASTNode
public: public:
mixin(DEFAULT_ACCEPT); mixin(DEFAULT_ACCEPT);
/** */ CompileCondition compileCondition; /** */ CompileCondition compileCondition;
/** */ Declaration[] trueDeclarations; /** */ Declaration trueDeclaration;
/** */ Declaration[] falseDeclarations; /** */ Declaration falseDeclaration;
} }
/// ///
@ -801,7 +790,6 @@ public:
override void accept(ASTVisitor visitor) override void accept(ASTVisitor visitor)
{ {
if (attributedDeclaration !is null) visitor.visit(attributedDeclaration);
if (importDeclaration !is null) visitor.visit(importDeclaration); if (importDeclaration !is null) visitor.visit(importDeclaration);
if (functionDeclaration !is null) visitor.visit(functionDeclaration); if (functionDeclaration !is null) visitor.visit(functionDeclaration);
if (variableDeclaration !is null) visitor.visit(variableDeclaration); if (variableDeclaration !is null) visitor.visit(variableDeclaration);
@ -828,7 +816,8 @@ public:
if (versionSpecification !is null) visitor.visit(versionSpecification); if (versionSpecification !is null) visitor.visit(versionSpecification);
} }
/** */ AttributedDeclaration attributedDeclaration; /** */ Attribute[] attributes;
/** */ AttributeDeclaration attributeDeclaration;
/** */ ImportDeclaration importDeclaration; /** */ ImportDeclaration importDeclaration;
/** */ FunctionDeclaration functionDeclaration; /** */ FunctionDeclaration functionDeclaration;
/** */ VariableDeclaration variableDeclaration; /** */ VariableDeclaration variableDeclaration;
@ -1773,6 +1762,7 @@ class StorageClass : ASTNode
public: public:
mixin(DEFAULT_ACCEPT); mixin(DEFAULT_ACCEPT);
/** */ AtAttribute atAttribute; /** */ AtAttribute atAttribute;
/** */ Deprecated deprecated_;
/** */ Token token; /** */ Token token;
} }

View File

@ -23,7 +23,7 @@
* definitions end with a semicolon (;).) * definitions end with a semicolon (;).)
* ) * )
* *
* The grammar for D starts with the $(LINK2 #.module, module) rule. * The grammar for D starts with the $(LINK2 #module, module) rule.
* *
* Examples: * Examples:
* --- * ---
@ -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)
*/ */
@ -323,7 +323,8 @@ alias core.sys.posix.stdio.fileno fileno;
mixin(traceEnterAndExit!(__FUNCTION__)); mixin(traceEnterAndExit!(__FUNCTION__));
auto node = new ArrayLiteral; auto node = new ArrayLiteral;
if (expect(TokenType.lBracket) is null) return null; if (expect(TokenType.lBracket) is null) return null;
node.argumentList = parseArgumentList(true); if (!currentIs(TokenType.rBracket))
node.argumentList = parseArgumentList(true);
if (expect(TokenType.rBracket) is null) return null; if (expect(TokenType.rBracket) is null) return null;
return node; return node;
} }
@ -743,32 +744,15 @@ alias core.sys.posix.stdio.fileno fileno;
* Parses an Attribute * Parses an Attribute
* *
* $(GRAMMAR $(RULEDEF attribute): * $(GRAMMAR $(RULEDEF attribute):
* $(RULE linkageAttribute) * $(RULE alignAttribute)
* | $(RULE alignAttribute) * | $(RULE linkageAttribute)
* | $(RULE pragmaExpression) * | $(RULE pragmaExpression)
* | $(RULE deprecated) * | $(RULE storageClass)
* | $(RULE atAttribute) * | $(LITERAL 'export')
* | $(LITERAL 'private')
* | $(LITERAL 'package') * | $(LITERAL 'package')
* | $(LITERAL 'private')
* | $(LITERAL 'protected') * | $(LITERAL 'protected')
* | $(LITERAL 'public') * | $(LITERAL 'public')
* | $(LITERAL 'export')
* | $(LITERAL 'extern')
* | $(LITERAL 'final')
* | $(LITERAL 'synchronized')
* | $(LITERAL 'override')
* | $(LITERAL 'abstract')
* | $(LITERAL 'const')
* | $(LITERAL 'auto')
* | $(LITERAL 'scope')
* | $(LITERAL '___gshared')
* | $(LITERAL 'shared')
* | $(LITERAL 'immutable')
* | $(LITERAL 'inout')
* | $(LITERAL 'static')
* | $(LITERAL 'pure')
* | $(LITERAL 'nothrow')
* | $(LITERAL 'enum')
* ;) * ;)
*/ */
Attribute parseAttribute() Attribute parseAttribute()
@ -781,7 +765,7 @@ alias core.sys.posix.stdio.fileno fileno;
if (peekIs(TokenType.lParen)) if (peekIs(TokenType.lParen))
node.linkageAttribute = parseLinkageAttribute(); node.linkageAttribute = parseLinkageAttribute();
else else
node.attribute = advance().type; goto default;
break; break;
case TokenType.align_: case TokenType.align_:
node.alignAttribute = parseAlignAttribute(); node.alignAttribute = parseAlignAttribute();
@ -789,62 +773,32 @@ alias core.sys.posix.stdio.fileno fileno;
case TokenType.pragma_: case TokenType.pragma_:
node.pragmaExpression = parsePragmaExpression(); node.pragmaExpression = parsePragmaExpression();
break; break;
case TokenType.deprecated_:
node.deprecated_ = parseDeprecated();
break;
case TokenType.private_: case TokenType.private_:
case TokenType.package_: case TokenType.package_:
case TokenType.protected_: case TokenType.protected_:
case TokenType.public_: case TokenType.public_:
case TokenType.export_: case TokenType.export_:
case TokenType.final_:
case TokenType.synchronized_:
case TokenType.override_:
case TokenType.abstract_:
case TokenType.const_:
case TokenType.auto_:
case TokenType.scope_:
case TokenType.gshared:
case TokenType.shared_:
case TokenType.immutable_:
case TokenType.inout_:
case TokenType.static_:
case TokenType.pure_:
case TokenType.nothrow_:
case TokenType.enum_:
node.attribute = advance().type; node.attribute = advance().type;
break; break;
case TokenType.at:
node.atAttribute = parseAtAttribute();
break;
default: default:
error("Attribute expected"); node.storageClass = parseStorageClass();
return null; break;
} }
return node; return node;
} }
/** /**
* Parses an AttributedDeclaration * Parses an AttributeDeclaration
* *
* $(GRAMMAR $(RULEDEF attributedDeclaration): * $(GRAMMAR $(RULEDEF attributeDeclaration):
* $(RULE attribute) ($(LITERAL ':') | $(RULE declaration) | $(LITERAL '{') $(RULE declaration)* $(LITERAL '}')) * $(RULE attribute) $(LITERAL ':')
* ;) * ;)
*/ */
AttributedDeclaration parseAttributedDeclaration() AttributeDeclaration parseAttributeDeclaration(Attribute attribute = null)
{ {
mixin(traceEnterAndExit!(__FUNCTION__)); auto node = new AttributeDeclaration;
auto node = new AttributedDeclaration; node.attribute = attribute is null ? parseAttribute() : attribute;
node.attribute = parseAttribute(); expect(TokenType.colon);
switch (current.type)
{
case TokenType.colon:
advance();
break;
default:
node.declaration = parseDeclaration();
break;
}
return node; return node;
} }
@ -859,8 +813,6 @@ alias core.sys.posix.stdio.fileno fileno;
{ {
mixin(traceEnterAndExit!(__FUNCTION__)); mixin(traceEnterAndExit!(__FUNCTION__));
auto node = new AutoDeclaration; auto node = new AutoDeclaration;
node.storageClass = parseStorageClass();
if (node.storageClass is null) return null;
do do
{ {
auto ident = expect(TokenType.identifier); auto ident = expect(TokenType.identifier);
@ -1464,7 +1416,7 @@ class ClassFour(A, B) if (someTest()) : Super {}}c;
auto dec = parseDeclaration(); auto dec = parseDeclaration();
if (dec is null) return null; if (dec is null) return null;
node.trueDeclarations ~= dec; node.trueDeclaration = dec;
if(currentIs(TokenType.else_)) if(currentIs(TokenType.else_))
advance(); advance();
@ -1473,7 +1425,7 @@ class ClassFour(A, B) if (someTest()) : Super {}}c;
auto elseDec = parseDeclaration(); auto elseDec = parseDeclaration();
if (elseDec is null) return null; if (elseDec is null) return null;
node.falseDeclarations ~= elseDec; node.falseDeclaration = elseDec;
return node; return node;
} }
@ -1520,8 +1472,7 @@ class ClassFour(A, B) if (someTest()) : Super {}}c;
* Parses a Constructor * Parses a Constructor
* *
* $(GRAMMAR $(RULEDEF constructor): * $(GRAMMAR $(RULEDEF constructor):
* $(LITERAL 'this') $(RULE templateParameters) $(RULE parameters) $(RULE memberFunctionAttribute)* $(RULE constraint)? $(RULE functionBody) * $(LITERAL 'this') $(RULE templateParameters) $(RULE parameters) $(RULE memberFunctionAttribute)* $(RULE constraint)? ($(RULE functionBody) | $(LITERAL ';'))
* | $(LITERAL 'this') $(RULE parameters) $(RULE memberFunctionAttribute)* ($(RULE functionBody) | $(LITERAL ';'))
* ;) * ;)
*/ */
Constructor parseConstructor() Constructor parseConstructor()
@ -1544,9 +1495,7 @@ class ClassFour(A, B) if (someTest()) : Super {}}c;
if (isTemplate && currentIs(TokenType.if_)) if (isTemplate && currentIs(TokenType.if_))
node.constraint = parseConstraint(); node.constraint = parseConstraint();
if (isTemplate) if (currentIs(TokenType.semicolon))
node.functionBody = parseFunctionBody();
else if (currentIs(TokenType.semicolon))
advance(); advance();
else else
node.functionBody = parseFunctionBody(); node.functionBody = parseFunctionBody();
@ -1640,9 +1589,11 @@ class ClassFour(A, B) if (someTest()) : Super {}}c;
* Parses a Declaration * Parses a Declaration
* *
* $(GRAMMAR $(RULEDEF declaration): * $(GRAMMAR $(RULEDEF declaration):
* $(RULE attribute)* $(declaration2)
* ;
* $(RULEDEF declaration2):
* $(RULE aliasDeclaration) * $(RULE aliasDeclaration)
* | $(RULE aliasThisDeclaration) * | $(RULE aliasThisDeclaration)
* | $(RULE attributedDeclaration)
* | $(RULE classDeclaration) * | $(RULE classDeclaration)
* | $(RULE conditionalDeclaration) * | $(RULE conditionalDeclaration)
* | $(RULE constructor) * | $(RULE constructor)
@ -1664,6 +1615,7 @@ class ClassFour(A, B) if (someTest()) : Super {}}c;
* | $(RULE unionDeclaration) * | $(RULE unionDeclaration)
* | $(RULE unittest) * | $(RULE unittest)
* | $(RULE variableDeclaration) * | $(RULE variableDeclaration)
* | $(RULE attributeDeclaration)
* | $(LITERAL '{') $(RULE declaration)+ $(LITERAL '}') * | $(LITERAL '{') $(RULE declaration)+ $(LITERAL '}')
* ;) * ;)
*/ */
@ -1671,6 +1623,23 @@ class ClassFour(A, B) if (someTest()) : Super {}}c;
{ {
mixin(traceEnterAndExit!(__FUNCTION__)); mixin(traceEnterAndExit!(__FUNCTION__));
auto node = new Declaration; auto node = new Declaration;
do
{
if (!isAttribute())
break;
auto attr = parseAttribute();
if (attr is null)
{
error("attribute is null");
break;
}
if (currentIs(TokenType.colon))
node.attributeDeclaration = parseAttributeDeclaration(attr);
else
node.attributes ~= attr;
} while (true);
with (TokenType) switch (current.type) with (TokenType) switch (current.type)
{ {
case semicolon: case semicolon:
@ -1704,34 +1673,7 @@ class ClassFour(A, B) if (someTest()) : Super {}}c;
node.destructor = parseDestructor(); node.destructor = parseDestructor();
break; break;
case enum_: case enum_:
if (peekIsOneOf(TokenType.lBrace, TokenType.colon)) node.enumDeclaration = parseEnumDeclaration();
node.enumDeclaration = parseEnumDeclaration();
else if (!peekIs(TokenType.identifier))
goto storageClass;
else
{
auto b = setBookmark();
advance();
assert (current.type == identifier);
if (peekIs(TokenType.assign))
{
trace("** 'enum identifier =' ");
goToBookmark(b);
node.variableDeclaration = parseVariableDeclaration();
}
else if (peekIsOneOf(TokenType.lBrace, TokenType.colon, TokenType.semicolon))
{
trace("** 'enum identifier { : ;' ");
goToBookmark(b);
node.enumDeclaration = parseEnumDeclaration();
}
else
{
trace("** something else");
goToBookmark(b);
goto storageClass;
}
}
break; break;
case import_: case import_:
node.importDeclaration = parseImportDeclaration(); node.importDeclaration = parseImportDeclaration();
@ -1753,22 +1695,20 @@ class ClassFour(A, B) if (someTest()) : Super {}}c;
node.sharedStaticConstructor = parseSharedStaticConstructor(); node.sharedStaticConstructor = parseSharedStaticConstructor();
else if (startsWith(shared_, static_, tilde)) else if (startsWith(shared_, static_, tilde))
node.sharedStaticDestructor = parseSharedStaticDestructor(); node.sharedStaticDestructor = parseSharedStaticDestructor();
else if (peekIs(lParen))
goto type;
else else
node.attributedDeclaration = parseAttributedDeclaration(); goto type;
break; break;
case static_: case static_:
if (startsWith(static_, this_)) if (peekIs(this_))
node.staticConstructor = parseStaticConstructor(); node.staticConstructor = parseStaticConstructor();
else if (startsWith(static_, tilde)) else if (peekIs(tilde))
node.staticDestructor = parseStaticDestructor(); node.staticDestructor = parseStaticDestructor();
else if (startsWith(static_, if_)) else if (peekIs(if_))
node.conditionalDeclaration = parseConditionalDeclaration(); node.conditionalDeclaration = parseConditionalDeclaration();
else if (startsWith(static_, assert_)) else if (peekIs(assert_))
node.staticAssertDeclaration = parseStaticAssertDeclaration(); node.staticAssertDeclaration = parseStaticAssertDeclaration();
else else
node.attributedDeclaration = parseAttributedDeclaration(); goto type;
break; break;
case struct_: case struct_:
node.structDeclaration = parseStructDeclaration(); node.structDeclaration = parseStructDeclaration();
@ -1782,9 +1722,26 @@ class ClassFour(A, B) if (someTest()) : Super {}}c;
case unittest_: case unittest_:
node.unittest_ = parseUnittest(); node.unittest_ = parseUnittest();
break; break;
case typeof_:
case bool_: .. case wchar_:
case identifier: case identifier:
if (node.attributes.length > 0
&& node.attributes[$ - 1].storageClass !is null)
{
if (peekIs(assign))
node.variableDeclaration = parseVariableDeclaration(null, true);
else if (peekIs(lParen))
node.functionDeclaration = parseFunctionDeclaration(null, true);
else
goto type;
}
else
goto type;
break;
case const_:
case immutable_:
case inout_:
case scope_:
case typeof_:
mixin (BASIC_TYPE_CASE_RANGE);
type: type:
Type type = parseType(); Type type = parseType();
if (!currentIs(identifier)) if (!currentIs(identifier))
@ -1811,53 +1768,6 @@ class ClassFour(A, B) if (someTest()) : Super {}}c;
case debug_: case debug_:
node.conditionalDeclaration = parseConditionalDeclaration(); node.conditionalDeclaration = parseConditionalDeclaration();
break; break;
case auto_:
if (startsWith(auto_, ref_, identifier, lParen)
|| startsWith(auto_, identifier, lParen))
node.functionDeclaration = parseFunctionDeclaration();
else
goto storageClass;
break;
case ref_:
node.functionDeclaration = parseFunctionDeclaration();
break;
case const_:
if (startsWith(const_, identifier, assign))
node.variableDeclaration = parseVariableDeclaration();
else
goto typeConstructor;
break;
case immutable_:
if (startsWith(immutable_, identifier, assign))
node.variableDeclaration = parseVariableDeclaration();
else
goto typeConstructor;
break;
case inout_:
typeConstructor:
if (peekIs(TokenType.lParen))
goto type;
else
goto case;
case at:
case align_:
case deprecated_:
case private_:
case package_:
case protected_:
case public_:
case export_:
case extern_:
case final_:
case synchronized_:
case override_:
case abstract_:
case gshared:
case pure_:
case nothrow_:
storageClass:
node.attributedDeclaration = parseAttributedDeclaration();
break;
default: default:
error("Declaration expected"); error("Declaration expected");
advance(); advance();
@ -2017,7 +1927,7 @@ class ClassFour(A, B) if (someTest()) : Super {}}c;
* Parses a Destructor * Parses a Destructor
* *
* $(GRAMMAR $(RULEDEF destructor): * $(GRAMMAR $(RULEDEF destructor):
* $(LITERAL '~') $(LITERAL 'this') $(LITERAL '$(LPAREN)') $(LITERAL '$(RPAREN)') $(RULE functionBody) * $(LITERAL '~') $(LITERAL 'this') $(LITERAL '$(LPAREN)') $(LITERAL '$(RPAREN)') ($(RULE functionBody) | $(LITERAL ';'))
* ;) * ;)
*/ */
Destructor parseDestructor() Destructor parseDestructor()
@ -2028,7 +1938,10 @@ class ClassFour(A, B) if (someTest()) : Super {}}c;
if (expect(TokenType.this_) is null) return null; if (expect(TokenType.this_) is null) return null;
if (expect(TokenType.lParen) is null) return null; if (expect(TokenType.lParen) is null) return null;
if (expect(TokenType.rParen) is null) return null; if (expect(TokenType.rParen) is null) return null;
node.functionBody = parseFunctionBody(); if (currentIs(TokenType.semicolon))
advance();
else
node.functionBody = parseFunctionBody();
return node; return node;
} }
@ -2497,47 +2410,23 @@ body {} // six
* Parses a FunctionDeclaration * Parses a FunctionDeclaration
* *
* $(GRAMMAR $(RULEDEF functionDeclaration): * $(GRAMMAR $(RULEDEF functionDeclaration):
* $(RULE memberFunctionAttribute)* ($(RULE type) | $(LITERAL 'auto') $(LITERAL 'ref')? | $(LITERAL 'ref') $(LITERAL 'auto')?) $(LITERAL Identifier) $(RULE templateParameters) $(RULE parameters) $(RULE memberFunctionAttribute)* $(RULE constraint)? $(RULE functionBody) * ($(RULE storageClass) | $(RULE _type)) $(LITERAL Identifier) $(RULE templateParameters) $(RULE parameters) $(RULE memberFunctionAttribute)* $(RULE constraint)? ($(RULE functionBody) | $(LITERAL ';'))
* | $(RULE memberFunctionAttribute)* ($(RULE type) | $(LITERAL 'auto') $(LITERAL 'ref')? | $(LITERAL 'ref') $(LITERAL 'auto')?) $(LITERAL Identifier) $(RULE parameters) $(RULE memberFunctionAttribute)* ($(RULE functionBody) | $(LITERAL ';'))
* ;) * ;)
*/ */
FunctionDeclaration parseFunctionDeclaration(Type type = null) FunctionDeclaration parseFunctionDeclaration(Type type = null, bool isAuto = false)
{ {
mixin(traceEnterAndExit!(__FUNCTION__)); mixin(traceEnterAndExit!(__FUNCTION__));
auto node = new FunctionDeclaration; auto node = new FunctionDeclaration;
if (isAuto)
goto functionName;
while(moreTokens() && currentIsMemberFunctionAttribute()) while(moreTokens() && currentIsMemberFunctionAttribute())
node.memberFunctionAttributes ~= parseMemberFunctionAttribute(); node.memberFunctionAttributes ~= parseMemberFunctionAttribute();
with (TokenType) switch (current.type) node.returnType = type is null ? parseType() : type;
{
case auto_:
advance();
node.hasAuto = true;
if (currentIs(ref_))
{
node.hasRef = true;
advance();
}
break;
case ref_:
advance();
node.hasRef = true;
if (currentIs(auto_))
{
node.hasAuto = true;
advance();
break;
}
else if (startsWith(identifier, lParen))
break;
else
goto default;
default:
node.returnType = type is null ? parseType() : type;
break;
}
functionName:
auto ident = expect(TokenType.identifier); auto ident = expect(TokenType.identifier);
if (ident is null) return null; if (ident is null) return null;
@ -2549,6 +2438,7 @@ body {} // six
return null; return null;
} }
assert (currentIs(TokenType.lParen));
auto p = peekPastParens(); auto p = peekPastParens();
bool isTemplate = p !is null && p.type == TokenType.lParen; bool isTemplate = p !is null && p.type == TokenType.lParen;
@ -2563,9 +2453,7 @@ body {} // six
if (isTemplate && currentIs(TokenType.if_)) if (isTemplate && currentIs(TokenType.if_))
node.constraint = parseConstraint(); node.constraint = parseConstraint();
if (isTemplate) if (currentIs(TokenType.semicolon))
node.functionBody = parseFunctionBody();
else if (currentIs(TokenType.semicolon))
advance(); advance();
else else
node.functionBody = parseFunctionBody(); node.functionBody = parseFunctionBody();
@ -3159,7 +3047,7 @@ invariant() foo();
* Parses an IsExpression * Parses an IsExpression
* *
* $(GRAMMAR $(RULEDEF isExpression): * $(GRAMMAR $(RULEDEF isExpression):
* $(LITERAL'is') $(LITERAL '$(LPAREN)') ($(RULE type) $(LITERAL Identifier)? (($(LITERAL ':') | $(LITERAL '==')) $(RULE typeSpecialization) ($(LITERAL ',') $(RULE templateParameterList))?)?)) $(LITERAL '$(RPAREN)') * $(LITERAL'is') $(LITERAL '$(LPAREN)') ($(RULE type) $(LITERAL Identifier)? (($(LITERAL ':') | $(LITERAL '==')) $(RULE typeSpecialization) ($(LITERAL ',') $(RULE templateParameterList))?)?) $(LITERAL '$(RPAREN)')
* ;) * ;)
*/ */
IsExpression parseIsExpression() IsExpression parseIsExpression()
@ -3851,6 +3739,7 @@ invariant() foo();
goto end; goto end;
if (currentIs(TokenType.vararg)) if (currentIs(TokenType.vararg))
{ {
advance();
node.hasVarargs = true; node.hasVarargs = true;
goto end; goto end;
} }
@ -3909,7 +3798,7 @@ q{(int a, ...)
* Parses a Postblit * Parses a Postblit
* *
* $(GRAMMAR $(RULEDEF parameters): * $(GRAMMAR $(RULEDEF parameters):
* $(LITERAL 'this') $(LITERAL '$(LPAREN)') $(LITERAL 'this') $(LITERAL '$(RPAREN)') $(RULE functionBody) * $(LITERAL 'this') $(LITERAL '$(LPAREN)') $(LITERAL 'this') $(LITERAL '$(RPAREN)') ($(RULE functionBody) | $(LITERAL ';'))
* ;) * ;)
*/ */
Postblit parsePostblit() Postblit parsePostblit()
@ -3919,7 +3808,10 @@ q{(int a, ...)
expect(TokenType.lParen); expect(TokenType.lParen);
expect(TokenType.this_); expect(TokenType.this_);
expect(TokenType.rParen); expect(TokenType.rParen);
node.functionBody = parseFunctionBody(); if (currentIs(TokenType.semicolon))
advance();
else
node.functionBody = parseFunctionBody();
return node; return node;
} }
@ -4467,18 +4359,19 @@ q{(int a, ...)
/** /**
* Parses an StorageClass * Parses an StorageClass
* *
* $(GRAMMAR $(RULE storageClass): * $(GRAMMAR $(RULEDEF storageClass):
* $(RULE atAttribute) * $(RULE atAttribute)
* | $(RULE typeConstructor) * | $(RULE typeConstructor)
* | $(RULE deprecated)
* | $(LITERAL 'abstract') * | $(LITERAL 'abstract')
* | $(LITERAL 'auto') * | $(LITERAL 'auto')
* | $(LITERAL 'deprecated')
* | $(LITERAL 'enum') * | $(LITERAL 'enum')
* | $(LITERAL 'extern') * | $(LITERAL 'extern')
* | $(LITERAL 'final') * | $(LITERAL 'final')
* | $(LITERAL 'nothrow') * | $(LITERAL 'nothrow')
* | $(LITERAL 'override') * | $(LITERAL 'override')
* | $(LITERAL 'pure') * | $(LITERAL 'pure')
* | $(LITERAL 'ref')
* | $(LITERAL '___gshared') * | $(LITERAL '___gshared')
* | $(LITERAL 'scope') * | $(LITERAL 'scope')
* | $(LITERAL 'static') * | $(LITERAL 'static')
@ -4494,23 +4387,26 @@ q{(int a, ...)
node.atAttribute = parseAtAttribute(); node.atAttribute = parseAtAttribute();
if (node.atAttribute is null) return null; if (node.atAttribute is null) return null;
break; break;
case deprecated_:
node.deprecated_ = parseDeprecated();
break;
case const_:
case immutable_:
case inout_:
case shared_:
case abstract_: case abstract_:
case auto_: case auto_:
case deprecated_:
case enum_: case enum_:
case extern_: case extern_:
case final_: case final_:
case nothrow_: case nothrow_:
case override_: case override_:
case pure_: case pure_:
case ref_:
case gshared: case gshared:
case scope_: case scope_:
case static_: case static_:
case synchronized_: case synchronized_:
case const_:
case immutable_:
case inout_:
case shared_:
node.token = advance(); node.token = advance();
break; break;
default: default:
@ -4564,7 +4460,7 @@ q{(int a, ...)
* Parses a StructDeclaration * Parses a StructDeclaration
* *
* $(GRAMMAR $(RULEDEF structDeclaration): * $(GRAMMAR $(RULEDEF structDeclaration):
* $(LITERAL 'struct') $(LITERAL Identifier) ($(RULE templateParameters) $(RULE constraint)? $(RULE structBody) | ($(RULE structBody) | $(LITERAL ';'))) * $(LITERAL 'struct') $(LITERAL Identifier)? ($(RULE templateParameters) $(RULE constraint)? $(RULE structBody) | ($(RULE structBody) | $(LITERAL ';')))
* ;) * ;)
*/ */
StructDeclaration parseStructDeclaration() StructDeclaration parseStructDeclaration()
@ -4572,9 +4468,11 @@ q{(int a, ...)
mixin(traceEnterAndExit!(__FUNCTION__)); mixin(traceEnterAndExit!(__FUNCTION__));
auto node = new StructDeclaration; auto node = new StructDeclaration;
expect(TokenType.struct_); expect(TokenType.struct_);
auto ident = expect(TokenType.identifier); if (currentIs(TokenType.identifier))
if (ident is null) return null; {
node.name = *ident; node.name = advance();
}
if (currentIs(TokenType.lParen)) if (currentIs(TokenType.lParen))
{ {
node.templateParameters = parseTemplateParameters(); node.templateParameters = parseTemplateParameters();
@ -4796,7 +4694,8 @@ q{(int a, ...)
{ {
mixin(traceEnterAndExit!(__FUNCTION__)); mixin(traceEnterAndExit!(__FUNCTION__));
auto node = new TemplateArgument; auto node = new TemplateArgument;
if (isType())
if (isBasicType(current.type) || !isExpression())
{ {
if ((node.type = parseType()) is null) return null; if ((node.type = parseType()) is null) return null;
} }
@ -5708,14 +5607,11 @@ q{doStuff(5)}c;
* | $(RULE autoDeclaration) * | $(RULE autoDeclaration)
* ;) * ;)
*/ */
VariableDeclaration parseVariableDeclaration(Type type = null) VariableDeclaration parseVariableDeclaration(Type type = null, bool isAuto = false)
{ {
mixin (traceEnterAndExit!(__FUNCTION__)); mixin (traceEnterAndExit!(__FUNCTION__));
auto node = new VariableDeclaration; auto node = new VariableDeclaration;
with (TokenType) if (currentIsOneOf(const_, immutable_, inout_, shared_, if (isAuto)
abstract_, auto_, deprecated_, enum_, extern_, final_, nothrow_,
override_, pure_, gshared, scope_, static_, synchronized_)
&& !(peekIs(lParen)))
{ {
node.autoDeclaration = parseAutoDeclaration(); node.autoDeclaration = parseAutoDeclaration();
return node; return node;
@ -5975,6 +5871,58 @@ private:
return parseType() !is null; return parseType() !is null;
} }
bool isAttribute()
{
if (!moreTokens()) return false;
with (TokenType) switch (current.type)
{
case const_:
case immutable_:
case inout_:
return !peekIs(TokenType.lParen);
case static_:
return !peekIsOneOf(assert_, this_, if_, tilde);
case shared_:
return !(startsWith(shared_, static_, this_)
|| startsWith(shared_, static_, tilde)
|| peekIs(TokenType.lParen));
case enum_:
if (peekIsOneOf(lBrace, colon, semicolon))
return false;
else if (peekIs(TokenType.identifier))
{
auto b = setBookmark();
scope(exit) goToBookmark(b);
advance();
if (peekIsOneOf(lBrace, colon, semicolon))
return false;
return true;
}
return true;
case deprecated_:
case private_:
case package_:
case protected_:
case public_:
case export_:
case final_:
case synchronized_:
case override_:
case abstract_:
case auto_:
case scope_:
case gshared:
case pure_:
case nothrow_:
case at:
case ref_:
case extern_:
return true;
default:
return false;
}
}
bool currentIsMemberFunctionAttribute() const bool currentIsMemberFunctionAttribute() const
{ {
switch (current.type) switch (current.type)
@ -6118,21 +6066,19 @@ private:
} }
const(Token)* peekPast(alias O, alias C)() const(Token)* peekPast(alias O, alias C)()
in
{
assert (tokens[index].type == O);
}
body
{ {
if (index >= tokens.length)
return null;
int depth = 1; int depth = 1;
auto i = index; auto i = index;
++i; ++i;
while (i < tokens.length) while (i < tokens.length)
{ {
if (i >= tokens.length)
return null;
if (tokens[i] == O) if (tokens[i] == O)
{
++depth; ++depth;
++i;
}
else if (tokens[i] == C) else if (tokens[i] == C)
{ {
--depth; --depth;
@ -6140,7 +6086,8 @@ private:
if (depth <= 0) if (depth <= 0)
break; break;
} }
++i; else
++i;
} }
return depth == 0 ? &tokens[i] : null; return depth == 0 ? &tokens[i] : null;
} }
@ -6270,8 +6217,8 @@ private:
template traceEnterAndExit(string fun) template traceEnterAndExit(string fun)
{ {
enum traceEnterAndExit = `version (verbose) trace(">> ` ~ fun ~ ` ");` enum traceEnterAndExit = `version (verbose) trace(">>> ` ~ fun ~ ` ");`
~ `version (verbose) scope(exit) trace("<< ` ~ fun ~ ` ");`; ~ `version (verbose) scope(exit) trace("<<< ` ~ fun ~ ` ");`;
} }
version (verbose) version (verbose)