Lots of DDoc changes, some parser work

This commit is contained in:
Hackerpilot 2013-06-01 17:51:45 +00:00
parent 4ad043085a
commit 0e58854fa9
3 changed files with 3869 additions and 3439 deletions

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,7 @@
* LexerConfig config; * LexerConfig config;
* config.iterStyle = IterationStyle.everything; * config.iterStyle = IterationStyle.everything;
* config.tokenStyle = TokenStyle.source; * config.tokenStyle = TokenStyle.source;
* config.versionNumber = 2061; * config.versionNumber = 2064;
* config.vendorString = "Lexer Example"; * config.vendorString = "Lexer Example";
* --- * ---
* Once you have configured the _lexer, call byToken$(LPAREN)$(RPAREN) on your * Once you have configured the _lexer, call byToken$(LPAREN)$(RPAREN) on your
@ -200,7 +200,7 @@ enum IterationStyle
includeWhitespace = 0b0010, includeWhitespace = 0b0010,
/// Include $(LINK2 http://dlang.org/lex.html#specialtokens, special tokens) /// Include $(LINK2 http://dlang.org/lex.html#specialtokens, special tokens)
includeSpecialTokens = 0b0100, includeSpecialTokens = 0b0100,
/// Do not stop iteration on reaching the ___EOF__ token /// Do not stop iteration on reaching the $(D_KEYWORD ___EOF__) token
ignoreEOF = 0b1000, ignoreEOF = 0b1000,
/// Include _everything /// Include _everything
everything = includeComments | includeWhitespace | ignoreEOF everything = includeComments | includeWhitespace | ignoreEOF
@ -215,8 +215,8 @@ enum TokenStyle : uint
/** /**
* Escape sequences will be replaced with their equivalent characters, * Escape sequences will be replaced with their equivalent characters,
* enclosing quote characters will not be included. Special tokens such as * enclosing quote characters will not be included. Special tokens such as
* __VENDOR__ will be replaced with their equivalent strings. Useful for * $(D_KEYWORD ___VENDOR__) will be replaced with their equivalent strings.
* creating a compiler or interpreter. * Useful for creating a compiler or interpreter.
*/ */
default_ = 0b0000, default_ = 0b0000,
@ -236,8 +236,8 @@ enum TokenStyle : uint
includeQuotes = 0b0010, includeQuotes = 0b0010,
/** /**
* Do not replace the value field of the special tokens such as ___DATE__ * Do not replace the value field of the special tokens such as
* with their string equivalents. * $(D_KEYWORD ___DATE__) with their string equivalents.
*/ */
doNotReplaceSpecial = 0b0100, doNotReplaceSpecial = 0b0100,
@ -265,12 +265,12 @@ struct LexerConfig
TokenStyle tokenStyle = tokenStyle.default_; TokenStyle tokenStyle = tokenStyle.default_;
/** /**
* Replacement for the ___VERSION__ token. Defaults to 100. * Replacement for the $(D_KEYWORD ___VERSION__) token. Defaults to 100.
*/ */
uint versionNumber = 100; uint versionNumber = 100;
/** /**
* Replacement for the ___VENDOR__ token. Defaults to $(D_STRING "std.d.lexer") * Replacement for the $(D_KEYWORD ___VENDOR__) token. Defaults to $(D_STRING "std.d.lexer")
*/ */
string vendorString = "std.d.lexer"; string vendorString = "std.d.lexer";
@ -597,7 +597,7 @@ L_advance:
return; return;
} }
if (config.iterStyle & TokenStyle.doNotReplaceSpecial) if (config.tokenStyle & TokenStyle.doNotReplaceSpecial)
return; return;
expandSpecialToken(); expandSpecialToken();
} }
@ -2682,7 +2682,8 @@ immutable(string[TokenType.max + 1]) tokenValues = [
"__LINE__", "__LINE__",
"__MODULE__", "__MODULE__",
"__FUNCTION__", "__FUNCTION__",
"__PRETTY_FUNCTION", "__PRETTY_FUNCTION__",
null,
null, null,
null, null,
null, null,
@ -2704,7 +2705,6 @@ immutable(string[TokenType.max + 1]) tokenValues = [
null, null,
null, null,
null, null,
null,
]; ];
pure string getTokenValue(const TokenType type) pure string getTokenValue(const TokenType type)
@ -2867,6 +2867,7 @@ pure TokenType lookupTokenType(R)(R input)
case '_': if (input[1..$].equal("_DATE__")) return TokenType.specialDate; case '_': if (input[1..$].equal("_DATE__")) return TokenType.specialDate;
else if (input[1..$].equal("_FILE__")) return TokenType.specialFile; else if (input[1..$].equal("_FILE__")) return TokenType.specialFile;
else if (input[1..$].equal("_LINE__")) return TokenType.specialLine; else if (input[1..$].equal("_LINE__")) return TokenType.specialLine;
else if (input[1..$].equal("_vector")) return TokenType.vector;
else if (input[1..$].equal("_TIME__")) return TokenType.specialTime; else if (input[1..$].equal("_TIME__")) return TokenType.specialTime;
else if (input[1..$].equal("_traits")) return TokenType.traits; else break; else if (input[1..$].equal("_traits")) return TokenType.traits; else break;
case 'a': if (input[1..$].equal("bstract")) return TokenType.abstract_; else break; case 'a': if (input[1..$].equal("bstract")) return TokenType.abstract_; else break;
@ -2909,7 +2910,8 @@ pure TokenType lookupTokenType(R)(R input)
switch (input[0]) switch (input[0])
{ {
case 's': if (input[1..$].equal("ynchronized")) return TokenType.synchronized_; else break; case 's': if (input[1..$].equal("ynchronized")) return TokenType.synchronized_; else break;
case '_': if (input[1..$].equal("_FUNCTION__")) return TokenType.specialFunction; else break; case '_': if (input[1..$].equal("_FUNCTION__")) return TokenType.specialFunction;
else if (input[1..$].equal("_parameters")) return TokenType.parameters; else break;
default: break; default: break;
} }
break; break;
@ -3306,7 +3308,8 @@ unittest
~ " interface invariant is lazy macro mixin module new nothrow null" ~ " interface invariant is lazy macro mixin module new nothrow null"
~ " out override pure ref return struct super switch template this" ~ " out override pure ref return struct super switch template this"
~ " throw true try typedef typeid typeof union unittest version volatile" ~ " throw true try typedef typeid typeof union unittest version volatile"
~ " while with __traits __parameters __vector"); ~ " while with __traits __parameters __vector __VENDOR__ __MODULE__"
~ " __VERSION__ __TIMESTAMP__ __PRETTY_FUNCTION__");
auto expected = ["bool", "byte", "cdouble", auto expected = ["bool", "byte", "cdouble",
"cent", "cfloat", "char", "creal", "cent", "cfloat", "char", "creal",
"dchar", "double", "float", "function", "dchar", "double", "float", "function",
@ -3329,8 +3332,11 @@ unittest
"super", "switch", "template", "this", "throw", "super", "switch", "template", "this", "throw",
"true", "try", "typedef", "typeid", "typeof", "true", "try", "typedef", "typeid", "typeof",
"union", "unittest", "version", "volatile", "union", "unittest", "version", "volatile",
"while", "with", "__traits", "__parameters", "__vector"]; "while", "with", "__traits", "__parameters", "__vector",
"__VENDOR__", "__MODULE__", "__VERSION__", "__TIMESTAMP__",
"__PRETTY_FUNCTION__"];
LexerConfig config; LexerConfig config;
config.tokenStyle = TokenStyle.doNotReplaceSpecial;
auto tokens = byToken(source, config); auto tokens = byToken(source, config);
// writeln(tokens.map!"a.value"().array()); // writeln(tokens.map!"a.value"().array());
assert (equal(map!"a.value"(tokens), expected)); assert (equal(map!"a.value"(tokens), expected));
@ -3387,7 +3393,7 @@ unittest
assert (tokens.front.line == 1); assert (tokens.front.line == 1);
assert (tokens.moveFront() == TokenType.int_); assert (tokens.moveFront() == TokenType.int_);
assert (tokens.front.line == 4); assert (tokens.front.line == 4);
assert (isType(tokens.front)); assert (isBasicType(tokens.front));
assert (tokens.front.value == "double"); assert (tokens.front.value == "double");
tokens.popFront(); tokens.popFront();
assert (tokens.front.value == "abcde (a + b) == 0", tokens.front.value); assert (tokens.front.value == "abcde (a + b) == 0", tokens.front.value);

View File

@ -13,7 +13,10 @@
* Authors: Brian Schott * Authors: Brian Schott
* Source: $(PHOBOSSRC std/d/_parser.d) * Source: $(PHOBOSSRC std/d/_parser.d)
* MACROS: * MACROS:
* GRAMMAR = <pre>$0</pre> * GRAMMAR = <pre style="font-weight: bold">$0</pre>
* RULEDEF = <a name="$0"><span>$0</span></a>
* RULE = <a href="#$0"><span style="font-weight: bold">$0</span></a>
* LITERAL = <span style="font-style:italic; color: green; font-weight: normal;">$0</span>
*/ */
module std.d.parser; module std.d.parser;
@ -22,6 +25,7 @@ import std.d.lexer;
import std.d.ast; import std.d.ast;
import std.conv; import std.conv;
import std.algorithm; import std.algorithm;
import std.array;
version(unittest) import std.stdio; version(unittest) import std.stdio;
/** /**
@ -43,8 +47,10 @@ struct Parser
{ {
/** /**
* Parses an AddExpression. * Parses an AddExpression.
* $(GRAMMAR addExpression: mulExpression *
* | addExpression ('+' | '-' | '~') mulExpression * $(GRAMMAR $(RULEDEF addExpression):
* $(RULE mulExpression)
* | $(RULE addExpression) $(LPAREN)$(LITERAL '+') | $(LITERAL'-') | $(LITERAL'~')$(RPAREN) $(RULE mulExpression)
* ;) * ;)
*/ */
AddExpression parseAddExpression() AddExpression parseAddExpression()
@ -63,8 +69,10 @@ struct Parser
} }
/** /**
* Parses an AliasDeclaration * Parses an AliasDeclaration.
* $(GRAMMAR aliasDeclaration: 'alias' (aliasInitializer (',' aliasInitializer)* | type declarator) ';' *
* $(GRAMMAR $(RULEDEF aliasDeclaration):
* $(LITERAL 'alias') $(LPAREN)$(RULE aliasInitializer) $(LPAREN)$(LITERAL ',') $(RULE aliasInitializer)$(RPAREN)* | $(RULE type) $(RULE declarator)$(RPAREN) $(LITERAL ';')
* ;) * ;)
*/ */
AliasDeclaration parseAliasDeclaration() AliasDeclaration parseAliasDeclaration()
@ -80,7 +88,8 @@ struct Parser
/** /**
* Parses an AliasInitializer * Parses an AliasInitializer
* $(GRAMMAR aliasInitializer: Identifier '=' type * $(GRAMMAR $(RULEDEF aliasInitializer):
* $(LITERAL Identifier) $(LITERAL '=') $(RULE type)
* ;) * ;)
*/ */
AliasInitializer parseAliasInitializer() AliasInitializer parseAliasInitializer()
@ -94,7 +103,7 @@ struct Parser
/** /**
* Parses an AliasThisDeclaration * Parses an AliasThisDeclaration
* $(GRAMMAR aliasThisDeclaration: 'alias' Identifier 'this' ';' * $(GRAMMAR $(RULEDEF aliasThisDeclaration): $(LITERAL 'alias') $(LITERAL Identifier) $(LITERAL 'this') $(LITERAL ';')
* ;) * ;)
*/ */
AliasThisDeclaration parseAliasThisDeclaration() AliasThisDeclaration parseAliasThisDeclaration()
@ -109,7 +118,7 @@ struct Parser
/** /**
* Parses an AlignAttribute. * Parses an AlignAttribute.
* $(GRAMMAR alignAttribute: 'align' ('(' IntegerLiteral ')')? * $(GRAMMAR $(RULEDEF alignAttribute): $(LITERAL 'align') ($(LITERAL '$(LPAREN)') $(LITERAL IntegerLiteral) $(LITERAL '$(RPAREN)'))?
* ;) * ;)
*/ */
AlignAttribute parseAlignAttribute() AlignAttribute parseAlignAttribute()
@ -127,8 +136,9 @@ struct Parser
/** /**
* Parses an AndAndExpression * Parses an AndAndExpression
* $(GRAMMAR andAndExpression: orExpression * $(GRAMMAR $(RULEDEF andAndExpression):
* | andAndExpression '&&' orExpression * $(RULE orExpression)
* | $(RULE andAndExpression) $(LITERAL '&&') $(RULE orExpression)
* ;) * ;)
*/ */
AndAndExpression parseAndAndExpression() AndAndExpression parseAndAndExpression()
@ -171,9 +181,11 @@ struct Parser
} }
/** /**
* Parses an Arguments * Parses Arguments
* *
* $(GRAMMAR ) * $(GRAMMAR $(RULEDEF arguments):
* $(LITERAL '$(LPAREN)') $(RULE argumentList)? $(LITERAL '$(RPAREN)')
* ;)
*/ */
Arguments parseArguments() Arguments parseArguments()
{ {
@ -199,7 +211,8 @@ struct Parser
/** /**
* Parses an ArrayLiteral * Parses an ArrayLiteral
* *
* $(GRAMMAR arrayLiteral: '[' argumentList ']' * $(GRAMMAR $(RULEDEF arrayLiteral):
* $(LITERAL '[') $(RULE argumentList) $(LITERAL ']')
* ;) * ;)
*/ */
ArrayLiteral parseArrayLiteral() ArrayLiteral parseArrayLiteral()
@ -490,7 +503,8 @@ struct Parser
/** /**
* Parses an AssocArrayLiteral * Parses an AssocArrayLiteral
* *
* $(GRAMMAR assocArrayLiteral: '[' keyValuePairs ']' * $(GRAMMAR $(RULEDEF assocArrayLiteral):
* $(LITERAL '[') $(RULE keyValuePairs) $(LITERAL ']')
* ;) * ;)
*/ */
AssocArrayLiteral parseAssocArrayLiteral() AssocArrayLiteral parseAssocArrayLiteral()
@ -529,12 +543,27 @@ struct Parser
/** /**
* Parses an AttributedDeclaration * Parses an AttributedDeclaration
* *
* $(GRAMMAR ) * $(GRAMMAR $(RULEDEF attributedDeclaration):
* $(RULE attribute) ($(LITERAL ':') | $(RULE declaration) | $(LITERAL '{') $(RULE declaration)* $(LITERAL '}'))
* ;)
*/ */
AttributedDeclaration parseAttributedDeclaration() AttributedDeclaration parseAttributedDeclaration()
{ {
auto node = new AttributedDeclaration; auto node = new AttributedDeclaration;
node.attribute = parseAttribute();
switch (current().type)
{
case TokenType.colon:
break;
case TokenType.lBrace:
while (moreTokens() && !currentIs(TokenType.rBrace))
node.declarations ~= parseDeclaration();
expect(TokenType.rBrace);
break;
default:
node.declarations ~= parseDeclaration();
break;
}
return node; return node;
} }
@ -553,7 +582,8 @@ struct Parser
/** /**
* Parses a BlockStatement * Parses a BlockStatement
* *
* $(GRAMMAR blockStatement: '{' declarationsAndStatements? '}' * $(GRAMMAR $(RULEDEF blockStatement):
* $(LITERAL '{') $(RULE declarationsAndStatements)? $(LITERAL '}')
* ;) * ;)
*/ */
BlockStatement parseBlockStatement() BlockStatement parseBlockStatement()
@ -569,7 +599,8 @@ struct Parser
/** /**
* Parses a BodyStatement * Parses a BodyStatement
* *
* $(GRAMMAR bodyStatement: 'body' blockStatement * $(GRAMMAR $(RULEDEF bodyStatement):
* $(LITERAL 'body') $(RULE blockStatement)
* ;) * ;)
*/ */
BodyStatement parseBodyStatement() BodyStatement parseBodyStatement()
@ -583,7 +614,8 @@ struct Parser
/** /**
* Parses a BreakStatement * Parses a BreakStatement
* *
* $(GRAMMAR breakStatement: 'break' Identifier? ';' * $(GRAMMAR $(RULEDEF breakStatement):
* $(LITERAL 'break') $(LITERAL Identifier)? $(LITERAL ';')
* ;) * ;)
*/ */
BreakStatement parseBreakStatement() BreakStatement parseBreakStatement()
@ -609,28 +641,29 @@ struct Parser
/** /**
* Parses an BuiltinType * Parses an BuiltinType
* *
* $(GRAMMAR builtinType: 'bool' * $(GRAMMAR $(RULEDEF builtinType):
* | 'byte' * $(LITERAL 'bool')
* | 'ubyte' * | $(LITERAL 'byte')
* | 'short' * | $(LITERAL 'ubyte')
* | 'ushort' * | $(LITERAL 'short')
* | 'int' * | $(LITERAL 'ushort')
* | 'uint' * | $(LITERAL 'int')
* | 'long' * | $(LITERAL 'uint')
* | 'ulong' * | $(LITERAL 'long')
* | 'char' * | $(LITERAL 'ulong')
* | 'wchar' * | $(LITERAL 'char')
* | 'dchar' * | $(LITERAL 'wchar')
* | 'float' * | $(LITERAL 'dchar')
* | 'double' * | $(LITERAL 'float')
* | 'real' * | $(LITERAL 'double')
* | 'ifloat' * | $(LITERAL 'real')
* | 'idouble' * | $(LITERAL 'ifloat')
* | 'ireal' * | $(LITERAL 'idouble')
* | 'cfloat' * | $(LITERAL 'ireal')
* | 'cdouble' * | $(LITERAL 'cfloat')
* | 'creal' * | $(LITERAL 'cdouble')
* | 'void' * | $(LITERAL 'creal')
* | $(LITERAL 'void')
* ;) * ;)
*/ */
BasicType parseBasicType() BasicType parseBasicType()
@ -649,7 +682,8 @@ struct Parser
/** /**
* Parses a CaseRangeStatement * Parses a CaseRangeStatement
* *
* $(GRAMMAR caseRangeStatement: 'case' assignExpression ':' '...' 'case' assignExpression ':' declarationsAndStatements * $(GRAMMAR $(RULEDEF caseRangeStatement):
* $(LITERAL 'case') $(RULE assignExpression) $(LITERAL ':') $(LITERAL '...') $(LITERAL 'case') $(RULE assignExpression) $(LITERAL ':') $(RULE declarationsAndStatements)
* ;) * ;)
*/ */
CaseRangeStatement parseCaseRangeStatement() CaseRangeStatement parseCaseRangeStatement()
@ -669,7 +703,8 @@ struct Parser
/** /**
* Parses an CaseStatement * Parses an CaseStatement
* *
* $(GRAMMAR caseStatement: 'case' argumentList ':' declarationsAndStatements * $(GRAMMAR $(RULEDEF caseStatement):
* $(LITERAL 'case') $(RULE argumentList) $(LITERAL ':') $(RULE declarationsAndStatements)
* ;) * ;)
*/ */
CaseStatement parseCaseStatement() CaseStatement parseCaseStatement()
@ -683,28 +718,55 @@ struct Parser
} }
/** /**
* Parses an CastExpression * Parses a CastExpression
* *
* $(GRAMMAR ) * $(GRAMMAR $(RULEDEF castExpression):
* $(LITERAL 'cast') $(LITERAL '$(LPAREN)') ($(RULE type) | $(RULE castQualifier))? $(LITERAL '$(RPAREN)') $(RULE unaryExpression)
* ;)
*/ */
CastExpression parseCastExpression() CastExpression parseCastExpression()
{ {
auto node = new CastExpression; auto node = new CastExpression;
expect(TokenType.cast_);
expect(TokenType.lParen);
if (isCastQualifier())
node.castQualifier = parseCastQualifier();
else
node.type = parseType();
expect(TokenType.rParen);
node.unaryExpression = parseUnaryExpression();
return node; return node;
} }
private bool isCastQualifier() const
{
switch (current().type)
{
case TokenType.const_:
return peekIsOneOf(TokenType.shared_, TokenType.rParen);
case TokenType.immutable_:
return peekIs(TokenType.rParen);
case TokenType.inout_:
return peekIsOneOf(TokenType.shared_, TokenType.rParen);
case TokenType.shared_:
return peekIsOneOf(TokenType.const_, TokenType.inout_, TokenType.rParen);
default:
return false;
}
}
/** /**
* Parses a CastQualifier * Parses a CastQualifier
* *
* $(GRAMMAR castQualifier: 'const' * $(GRAMMAR $(RULEDEF castQualifier):
* | 'const' 'shared' * $(LITERAL 'const')
* | 'immutable' * | $(LITERAL 'const') $(LITERAL 'shared')
* | 'inout' * | $(LITERAL 'immutable')
* | 'inout' 'shared' * | $(LITERAL 'inout')
* | 'shared' * | $(LITERAL 'inout') $(LITERAL 'shared')
* | 'shared' 'const' * | $(LITERAL 'shared')
* | 'shared' 'inout' * | $(LITERAL 'shared') $(LITERAL 'const')
* | $(LITERAL 'shared') $(LITERAL 'inout')
* ;) * ;)
*/ */
CastQualifier parseCastQualifier() CastQualifier parseCastQualifier()
@ -736,7 +798,8 @@ struct Parser
/** /**
* Parses a Catch * Parses a Catch
* *
* $(GRAMMAR catch_: 'catch' '(' type Identifier? ')' nonEmptyStatementNoCaseNoDefault * $(GRAMMAR $(RULEDEF catch):
* $(LITERAL 'catch') $(LITERAL '$(LPAREN)') $(RULE type) $(LITERAL Identifier)? $(LITERAL '$(RPAREN)') $(RULE nonEmptyStatementNoCaseNoDefault)
* ;) * ;)
*/ */
Catch parseCatch() Catch parseCatch()
@ -767,7 +830,8 @@ struct Parser
/** /**
* Parses an ClassBody * Parses an ClassBody
* *
* $(GRAMMAR classBody: '{' declarationOrInvariant* '}' * $(GRAMMAR $(RULEDEF classBody):
* $(LITERAL '{') $(RULE declarationOrInvariant)* $(LITERAL '}')
* ;) * ;)
*/ */
ClassBody parseClassBody() ClassBody parseClassBody()
@ -783,7 +847,8 @@ struct Parser
/** /**
* Parses an ClassDeclaration * Parses an ClassDeclaration
* *
* $(GRAMMAR classDeclaration: 'class' Identifier (templateParameters constraint?)? (':' identifierList )? classBody * $(GRAMMAR $(RULEDEF classDeclaration):
* $(LITERAL 'class') $(LITERAL Identifier) ($(RULE templateParameters) $(RULE constraint)?)? ($(LITERAL ':') $(RULE identifierList))? $(RULE classBody)
* ;) * ;)
*/ */
ClassDeclaration parseClassDeclaration() ClassDeclaration parseClassDeclaration()
@ -818,9 +883,10 @@ struct Parser
/** /**
* Parses a CompileCondition * Parses a CompileCondition
* *
* $(GRAMMAR compileCondition: versionCondition * $(GRAMMAR $(RULEDEF compileCondition):
* | debugCondition * $(RULE versionCondition)
* | staticIfCondition * | $(RULE debugCondition)
* | $(RULE staticIfCondition)
* ;) * ;)
*/ */
CompileCondition parseCompileCondition() CompileCondition parseCompileCondition()
@ -871,7 +937,8 @@ struct Parser
/** /**
* Parses an Constraint * Parses an Constraint
* *
* $(GRAMMAR constraint: 'if' '(' expression ')' * $(GRAMMAR $(RULEDEF constraint):
* $(LITERAL 'if') $(LITERAL '$(LPAREN)') $(RULE expression) $(LITERAL '$(RPAREN)')
* ;) * ;)
*/ */
Constraint parseConstraint() Constraint parseConstraint()
@ -887,7 +954,8 @@ struct Parser
/** /**
* Parses a Constructor * Parses a Constructor
* *
* $(GRAMMAR constructor: 'this' parameters functionBody * $(GRAMMAR $(RULEDEF constructor):
* $(LITERAL 'this') $(RULE parameters) $(RULE functionBody)
* ;) * ;)
*/ */
Constructor parseConstructor() Constructor parseConstructor()
@ -902,7 +970,8 @@ struct Parser
/** /**
* Parses an ContinueStatement * Parses an ContinueStatement
* *
* $(GRAMMAR continueStatement: 'continue' Identifier? ';' * $(GRAMMAR $(RULEDEF continueStatement):
* $(LITERAL 'continue') $(LITERAL Identifier)? $(LITERAL ';')
* ;) * ;)
*/ */
ContinueStatement parseContinueStatement() ContinueStatement parseContinueStatement()
@ -926,9 +995,10 @@ struct Parser
} }
/** /**
* Parses an DebugCondition * Parses a DebugCondition
* *
* $(GRAMMAR debugCondition: 'debug' ('(' (IntegerLiteral | Identifier) ')')? * $(GRAMMAR $(RULEDEF debugCondition):
* $(LITERAL 'debug') ($(LITERAL '$(LPAREN)') ($(LITERAL IntegerLiteral) | $(LITERAL Identifier)) $(LITERAL '$(RPAREN)'))?
* ;) * ;)
*/ */
DebugCondition parseDebugCondition() DebugCondition parseDebugCondition()
@ -956,7 +1026,8 @@ struct Parser
/** /**
* Parses a DebugSpecification * Parses a DebugSpecification
* *
* $(GRAMMAR debugSpecification: 'debug' '=' (Identifier | IntegerLiteral) ';' * $(GRAMMAR $(RULEDEF debugSpecification):
* $(LITERAL 'debug') $(LITERAL '=') ($(LITERAL Identifier) | $(LITERAL IntegerLiteral)) $(LITERAL ';')
* ;) * ;)
*/ */
DebugSpecification parseDebugSpecification() DebugSpecification parseDebugSpecification()
@ -978,29 +1049,30 @@ struct Parser
/** /**
* Parses a Declaration * Parses a Declaration
* *
* $(GRAMMAR declaration: aliasDeclaration * $(GRAMMAR $(RULEDEF declaration):
* | aliasThisDeclaration * $(RULE aliasDeclaration)
* | attributedDeclaration * | $(RULE aliasThisDeclaration)
* | classDeclaration * | $(RULE attributedDeclaration)
* | conditionalDeclaration * | $(RULE classDeclaration)
* | constructor * | $(RULE conditionalDeclaration)
* | destructor * | $(RULE constructor)
* | enumDeclaration * | $(RULE destructor)
* | functionDeclaration * | $(RULE enumDeclaration)
* | importDeclaration * | $(RULE functionDeclaration)
* | interfaceDeclaration * | $(RULE importDeclaration)
* | mixinDeclaration * | $(RULE interfaceDeclaration)
* | pragmaDeclaration * | $(RULE mixinDeclaration)
* | sharedStaticConstructor * | $(RULE pragmaDeclaration)
* | sharedStaticDestructor * | $(RULE sharedStaticConstructor)
* | staticAssertDeclaration * | $(RULE sharedStaticDestructor)
* | staticConstructor * | $(RULE staticAssertDeclaration)
* | staticDestructor * | $(RULE staticConstructor)
* | structDeclaration * | $(RULE staticDestructor)
* | templateDeclaration * | $(RULE structDeclaration)
* | unionDeclaration * | $(RULE templateDeclaration)
* | unittest * | $(RULE unionDeclaration)
* | variableDeclaration * | $(RULE unittest)
* | $(RULE variableDeclaration)
* ;) * ;)
*/ */
Declaration parseDeclaration() Declaration parseDeclaration()
@ -1094,8 +1166,9 @@ struct Parser
/** /**
* Parses a DeclarationOrInvariant * Parses a DeclarationOrInvariant
* *
* $(GRAMMAR declarationOrInvariant : declaration * $(GRAMMAR $(RULEDEF declarationOrInvariant):
* | invariant * $(RULE declaration)
* | $(RULE invariant)
* ;) * ;)
*/ */
DeclarationOrInvariant parseDeclarationOrInvariant() DeclarationOrInvariant parseDeclarationOrInvariant()
@ -1111,7 +1184,8 @@ struct Parser
/** /**
* Parses a Declarator * Parses a Declarator
* *
* $(GRAMMAR declarator: Identifier declaratorSuffix? ('=' initializer)? * $(GRAMMAR $(RULEDEF declarator):
* $(LITERAL Identifier) $(RULE declaratorSuffix)? ($(LITERAL '=') $(RULE initializer))?
* ;) * ;)
*/ */
Declarator parseDeclarator() Declarator parseDeclarator()
@ -1179,7 +1253,8 @@ struct Parser
/** /**
* Parses a Deprecated attribute * Parses a Deprecated attribute
* *
* $(GRAMMAR deprecated: 'deprecated' ('(' assignExpression ')')? * $(GRAMMAR $(RULEDEF deprecated):
* $(LITERAL 'deprecated') ($(LITERAL '$(LPAREN)') $(RULE assignExpression) $(LITERAL '$(RPAREN)'))?
* ;) * ;)
*/ */
Deprecated parseDeprecated() Deprecated parseDeprecated()
@ -1198,7 +1273,8 @@ struct Parser
/** /**
* Parses a Destructor * Parses a Destructor
* *
* $(GRAMMAR destructor: '~' 'this' '(' ')' functionBody * $(GRAMMAR $(RULEDEF destructor):
* $(LITERAL '~') $(LITERAL 'this') $(LITERAL '$(LPAREN)') $(LITERAL '$(RPAREN)') $(RULE functionBody)
* ;) * ;)
*/ */
Destructor parseDestructor() Destructor parseDestructor()
@ -1213,50 +1289,93 @@ struct Parser
} }
/** /**
* Parses an DoStatement * Parses a DoStatement
* *
* $(GRAMMAR ) * $(GRAMMAR $(RULEDEF doStatement):
* $(LITERAL 'do') $(RULE blockStatement) $(LITERAL 'while') $(LITERAL '$(LPAREN)') $(RULE expression) $(LITERAL '$(RPAREN)') $(LITERAL ';')
* ;)
*/ */
DoStatement parseDoStatement() DoStatement parseDoStatement()
{ {
auto node = new DoStatement; auto node = new DoStatement;
expect(TokenType.do_);
node.blockStatement = parseBlockStatement();
expect(TokenType.while_);
expect(TokenType.lParen);
node.expression = parseExpression();
expect(TokenType.rParen);
expect(TokenType.semicolon);
return node; return node;
} }
/** /**
* Parses an EnumBody * Parses an EnumBody
* *
* $(GRAMMAR ) * $(GRAMMAR $(RULEDEF enumBody):
* $(LITERAL ';')
* | $(LITERAL '{') $(RULE enumMember) ($(LITERAL ',') $(RULE enumMember)?)* $(LITERAL '}')
* ;)
*/ */
EnumBody parseEnumBody() EnumBody parseEnumBody()
{ {
auto node = new EnumBody; auto node = new EnumBody;
if (!currentIs(TokenType.semicolon))
{
expect (TokenType.lBrace);
while (moreTokens())
{
if (!currentIs(TokenType.comma))
node.enumMembers ~= parseEnumMember();
if (currentIs(TokenType.comma))
continue;
else if (currentIs(TokenType.rBrace))
break;
else
{
error(`",", "}" or enum member expected`);
goto ret;
}
}
expect (TokenType.rBrace);
}
ret:
return node; return node;
} }
/** /**
* Parses an EnumDeclaration * Parses an EnumDeclaration
* *
* $(GRAMMAR ) * $(GRAMMAR $(RULEDEF enumDeclaration):
* $(LITERAL 'enum') $(LITERAL Identifier)? ($(LITERAL ':') $(RULE type))? $(RULE enumBody)
* ;)
*/ */
EnumDeclaration parseEnumDeclaration() EnumDeclaration parseEnumDeclaration()
{ {
auto node = new EnumDeclaration; auto node = new EnumDeclaration;
expect(TokenType.enum_);
if (currentIs(TokenType.identifier))
node.identifier = advance();
if (currentIs(TokenType.colon))
{
advance();
node.type = parseType();
}
node.enumBody = parseEnumBody();
return node; return node;
} }
/** /**
* Parses an EnumMember * Parses an EnumMember
* *
* $(GRAMMAR ) * $(GRAMMAR $(RULEDEF enumMember):
* $(LITERAL Identifier)
* | ($(LITERAL Identifier) | $(RULE type)) $(LITERAL '=') $(RULE assignExpression)
* ;)
*/ */
EnumMember parseEnumMember() EnumMember parseEnumMember()
{ {
auto node = new EnumMember; auto node = new EnumMember;
// TODO
return node; return node;
} }
@ -1454,7 +1573,8 @@ struct Parser
/** /**
* Parses an IdentifierChain * Parses an IdentifierChain
* *
* $(GRAMMAR identifierChain: Identifier ('.' Identifier)* * $(GRAMMAR $(RULEDEF identifierChain):
* $(LITERAL Identifier) ($(LITERAL '.') $(LITERAL Identifier))*
* ;) * ;)
*/ */
IdentifierChain parseIdentifierChain() IdentifierChain parseIdentifierChain()
@ -1474,10 +1594,23 @@ struct Parser
return node; return node;
} }
unittest
{
auto input = cast(ubyte[]) "abcde.frocegu.creou.faowe"c;
LexerConfig config;
auto tokens = byToken(input, config);
Parser p;
p.fileName = "test";
p.tokens = tokens.array();
auto chain = p.parseIdentifierChain();
assert (chain.identifiers == ["abcde", "frocegu", "creou", "faowe"]);
}
/** /**
* Parses an IdentifierList * Parses an IdentifierList
* *
* $(GRAMMAR identifierList: Identifier (',' Identifier)* * $(GRAMMAR $(RULEDEF identifierList):
* $(LITERAL Identifier) ($(LITERAL ',') $(LITERAL Identifier))*
* ;) * ;)
*/ */
IdentifierList parseIdentifierList() IdentifierList parseIdentifierList()
@ -1605,6 +1738,20 @@ struct Parser
return node; return node;
} }
/**
* Parses an IndexExpression
*
* $(GRAMMAR $(RULEDEF indexExpression):
* $(RULE unaryExpression) $(LITERAL '[') $(RULE argumentList) $(LITERAL ']')
* ;)
*/
IndexExpression parseImportList()
{
auto node = new IndexExpression;
return node;
}
/** /**
* Parses an InExpression * Parses an InExpression
* *
@ -1753,7 +1900,8 @@ struct Parser
/** /**
* Parses an LinkageAttribute * Parses an LinkageAttribute
* *
* $(GRAMMAR linkageAttribute: 'extern' '(' Identifier '++'? ')' * $(GRAMMAR $(RULEDEF linkageAttribute):
* $(LITERAL 'extern') $(LITERAL '$(LPAREN)') $(LITERAL Identifier) $(LITERAL '++')? $(LITERAL '$(RPAREN)')
* ;) * ;)
*/ */
LinkageAttribute parseLinkageAttribute() LinkageAttribute parseLinkageAttribute()
@ -1786,7 +1934,8 @@ struct Parser
/** /**
* Parses an MixinDeclaration * Parses an MixinDeclaration
* *
* $(GRAMMAR mixinDeclaration: mixinExpression ';' * $(GRAMMAR $(RULEDEF mixinDeclaration):
* $(RULE mixinExpression) $(LITERAL ';')
* ;) * ;)
*/ */
MixinDeclaration parseMixinDeclaration() MixinDeclaration parseMixinDeclaration()
@ -1824,7 +1973,8 @@ struct Parser
/** /**
* Parses a Module * Parses a Module
* *
* $(GRAMMAR module: moduleDeclaration? declaration* * $(GRAMMAR $(RULEDEF module):
* $(RULE moduleDeclaration)? $(RULE declaration)*
* ;) * ;)
*/ */
Module parseModule() Module parseModule()
@ -1850,7 +2000,8 @@ struct Parser
/** /**
* Parses a ModuleDeclaration * Parses a ModuleDeclaration
* *
* $(GRAMMAR moduleDeclaration: 'module' identifierChain ';' * $(GRAMMAR $(RULEDEF moduleDeclaration):
* $(LITERAL 'module') $(RULE identifierChain) $(LITERAL ';')
* ;) * ;)
*/ */
ModuleDeclaration parseModuleDeclaration() ModuleDeclaration parseModuleDeclaration()
@ -1864,8 +2015,9 @@ struct Parser
/** /**
* Parses a MulExpression * Parses a MulExpression
* $(GRAMMAR mulExpression: unaryExpression * $(GRAMMAR $(RULEDEF mulExpression):
* | mulExpression ('*' | '/' | '%') unaryExpression * $(RULE unaryExpression)
* | $(RULE mulExpression) ($(LITERAL '*') | $(LITERAL '/') | $(LITERAL '%')) $(RULE unaryExpression)
* ;) * ;)
*/ */
MulExpression parseMulExpression() MulExpression parseMulExpression()
@ -2233,8 +2385,9 @@ struct Parser
/** /**
* Parses a Statement * Parses a Statement
* *
* $(GRAMMAR statement: ';' * $(GRAMMAR $(RULEDEF statement):
* | nonEmptyStatement * $(LITERAL ';')
* | $(RULE nonEmptyStatement)
* ;) * ;)
*/ */
Statement parseStatement() Statement parseStatement()
@ -2364,9 +2517,10 @@ struct Parser
} }
/** /**
* Parses an StructDeclaration * Parses a StructDeclaration
* *
* $(GRAMMAR structDeclaration: 'struct' Identifier (templateParameters constraint? structBody | (structBody | ';')) * $(GRAMMAR $(RULEDEF structDeclaration):
* $(LITERAL 'struct') $(LITERAL Identifier) ($(RULE templateParameters) $(RULE constraint)? $(RULE structBody) | ($(RULE structBody) | $(LITERAL ';')))
* ;) * ;)
*/ */
StructDeclaration parseStructDeclaration() StructDeclaration parseStructDeclaration()
@ -2881,9 +3035,27 @@ struct Parser
} }
/** /**
* Parses an UnaryExpression * Parses a UnaryExpression
* *
* $(GRAMMAR ) * $(GRAMMAR $(RULEDEF unaryExpression):
* $(RULE primaryExpression)
* | $(LITERAL '&') $(RULE unaryExpression)
* | $(LITERAL '!') $(RULE unaryExpression)
* | $(LITERAL '*') $(RULE unaryExpression)
* | $(LITERAL '+') $(RULE unaryExpression)
* | $(LITERAL '-') $(RULE unaryExpression)
* | $(LITERAL '~') $(RULE unaryExpression)
* | $(RULE newExpression)
* | $(RULE deleteExpression)
* | $(RULE castExpression)
* | $(RULE functionCallExpression)
* | $(RULE preIncDecExpression)
* | $(RULE postIncDecExpression)
* | $(RULE sliceExpression)
* | $(RULE indexExpression)
* | $(RULE unaryExpression) $(LITERAL '.') $(RULE identifierOrTemplateInstance)
* | $(RULE assertExpression)
* ;)
*/ */
UnaryExpression parseUnaryExpression() UnaryExpression parseUnaryExpression()
{ {
@ -2905,9 +3077,11 @@ struct Parser
} }
/** /**
* Parses an Unittest * Parses a Unittest
* *
* $(GRAMMAR ) * $(GRAMMAR $(RULEDEF unittest):
* $(LITERAL 'unittest') $(RULE blockStatement)
* ;)
*/ */
Unittest parseUnittest() Unittest parseUnittest()
{ {
@ -2932,7 +3106,8 @@ struct Parser
/** /**
* Parses a VersionCondition * Parses a VersionCondition
* *
* $(GRAMMAR versionCondition: 'version' '(' (IntegerLiteral | Identifier | 'unittest' | 'assert') ')' * $(GRAMMAR $(RULEDEF versionCondition):
* $(LITERAL 'version') $(LITERAL '$(LPAREN)') ($(LITERAL IntegerLiteral) | $(LITERAL Identifier) | $(LITERAL 'unittest') | $(LITERAL 'assert')) $(LITERAL '$(RPAREN)')
* ;) * ;)
*/ */
VersionCondition parseVersionCondition() VersionCondition parseVersionCondition()
@ -2957,7 +3132,8 @@ struct Parser
/** /**
* Parses a VersionSpecification * Parses a VersionSpecification
* *
* $(GRAMMAR versionSpecification: 'version' '=' (Identifier | IntegerLiteral) ';' * $(GRAMMAR $(RULEDEF versionSpecification):
* $(LITERAL 'version') $(LITERAL '=') ($(LITERAL Identifier) | $(LITERAL IntegerLiteral)) $(LITERAL ';')
* ;) * ;)
*/ */
VersionSpecification parseVersionSpecification() VersionSpecification parseVersionSpecification()
@ -2976,9 +3152,10 @@ struct Parser
} }
/** /**
* Parses an WhileStatement * Parses a WhileStatement
* *
* $(GRAMMAR whileStatement: 'while' '(' expression ')' statementNoCaseNoDefault * $(GRAMMAR $(RULEDEF whileStatement):
* $(LITERAL 'while') $(LITERAL '$(LPAREN)') $(RULE expression) $(LITERAL '$(RPAREN)') $(RULE statementNoCaseNoDefault)
* ;) * ;)
*/ */
WhileStatement parseWhileStatement() WhileStatement parseWhileStatement()
@ -2993,16 +3170,18 @@ struct Parser
} }
/** /**
* Parses an WithStatement * Parses a WithStatement
* *
* $(GRAMMAR ) * $(GRAMMAR $(RULEDEF withStatement):
* $(LITERAL 'with') $(LITERAL '$(LPAREN)') ($(RULE expression) | $(RULE symbol) | $(RULE templateInstance)) $(LITERAL '$(RPAREN)') $(RULE nonEmptyStatementNoCaseNoDefault)
* ;)
*/ */
WithStatement parseWithStatement() WithStatement parseWithStatement()
{ {
auto node = new WithStatement; auto node = new WithStatement;
expect(TokenType.with_); expect(TokenType.with_);
expect(TokenType.lParen); expect(TokenType.lParen);
// magic here // TODO: magic here
expect(TokenType.rParen); expect(TokenType.rParen);
parseNonEmptyStatementNoCaseNoDefault(); parseNonEmptyStatementNoCaseNoDefault();
return node; return node;
@ -3033,7 +3212,7 @@ struct Parser
} }
} }
Token* peekPast(alias O, alias C)() const(Token)* peekPast(alias O, alias C)()
in in
{ {
assert (tokens[index].type == O); assert (tokens[index].type == O);
@ -3059,26 +3238,37 @@ struct Parser
return depth == 0 ? &tokens[i] : null; return depth == 0 ? &tokens[i] : null;
} }
Token* peekPastParens() const(Token)* peekPastParens()
{ {
return peekPast!(TokenType.lParen, TokenType.rParen)(); return peekPast!(TokenType.lParen, TokenType.rParen)();
} }
Token* peekPastBrackets() const(Token)* peekPastBrackets()
{ {
return peekPast!(TokenType.lBracket, TokenType.rBracket)(); return peekPast!(TokenType.lBracket, TokenType.rBracket)();
} }
Token* peekPastBraces() const(Token)* peekPastBraces()
{ {
return peekPast!(TokenType.lBrace, TokenType.rBrace)(); return peekPast!(TokenType.lBrace, TokenType.rBrace)();
} }
bool peekIs(TokenType t) const
{
return index + 1 < tokens.length && tokens[index + 1].type == t;
}
bool peekIsOneOf(TokenType[] types...) const
{
if (index + 1 >= tokens.length) return false;
return canFind(types, tokens[index + 1].type);
}
/** /**
* Returns a token of the specified type if it was the next token, otherwise * Returns a token of the specified type if it was the next token, otherwise
* calls the error function and returns null. * calls the error function and returns null.
*/ */
Token* expect(TokenType type) const(Token)* expect(TokenType type)
{ {
if (tokens[index].type == type) if (tokens[index].type == type)
return &tokens[index++]; return &tokens[index++];
@ -3092,7 +3282,7 @@ struct Parser
/** /**
* Returns: the current token * Returns: the current token
*/ */
Token current() Token current() const
{ {
return tokens[index]; return tokens[index];
} }
@ -3108,20 +3298,20 @@ struct Parser
/** /**
* Returns: true if the current token has the given type * Returns: true if the current token has the given type
*/ */
bool currentIs(TokenType type) bool currentIs(TokenType type) const
{ {
return tokens[index] == type; return index < tokens.length && tokens[index] == type;
} }
/** /**
* Returns: true if the current token is one of the given types * Returns: true if the current token is one of the given types
*/ */
bool currentIsOneOf(TokenType[] types...) bool currentIsOneOf(TokenType[] types...) const
{ {
return canFind(types, current().type); return canFind(types, current().type);
} }
bool startsWith(TokenType[] types...) bool startsWith(TokenType[] types...) const
{ {
for (size_t i = 0; i != types.length; ++i) for (size_t i = 0; i != types.length; ++i)
{ {
@ -3134,13 +3324,13 @@ struct Parser
/** /**
* Returns: true if there are more tokens * Returns: true if there are more tokens
*/ */
bool moreTokens() bool moreTokens() const
{ {
return index < tokens.length; return index < tokens.length;
} }
uint errorCount; uint errorCount;
Token[] tokens; const(Token)[] tokens;
size_t index; size_t index;
string fileName; string fileName;
} }