D-Scanner/std/d/parser.d

3147 lines
54 KiB
D
Executable File

// Written in the D programming language
/**
* This module contains a _parser for D source code.
*
* Examples:
* ---
* // TODO
* ---
*
* Copyright: Brian Schott 2013
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt Boost, License 1.0)
* Authors: Brian Schott
* Source: $(PHOBOSSRC std/d/_parser.d)
* MACROS:
* GRAMMAR = <pre>$0</pre>
*/
module std.d.parser;
import std.d.lexer;
import std.d.ast;
import std.conv;
import std.algorithm;
version(unittest) import std.stdio;
/**
* Params:
* tokens = the tokens parsed by std.d.lexer
* Returns: the parsed module
*/
Module parseModule(R)(R tokens) if (is (ElementType!R == Token))
{
auto parser = new Parser();
parser.tokens = tokens.array();
return parser.parseModule();
}
/**
* Parser structure
*/
struct Parser
{
/**
* Parses an AddExpression.
* $(GRAMMAR addExpression: mulExpression
* | addExpression ('+' | '-' | '~') mulExpression
* ;)
*/
AddExpression parseAddExpression()
{
auto node = new AddExpression;
node.right = parseMulExpression();
while (currentIsOneOf(TokenType.plus, TokenType.minus, TokenType.tilde))
{
node.operator = advance().type;
auto newNode = new AddExpression;
newNode.left = node;
newNode.right = parseMulExpression();
node = newNode;
}
return node;
}
/**
* Parses an AliasDeclaration
* $(GRAMMAR aliasDeclaration: 'alias' (aliasInitializer (',' aliasInitializer)* | type declarator) ';'
* ;)
*/
AliasDeclaration parseAliasDeclaration()
{
auto node = new AliasDeclaration;
expect(TokenType.alias_);
// TODO
expect(TokenType.semicolon);
return node;
}
/**
* Parses an AliasInitializer
* $(GRAMMAR aliasInitializer: Identifier '=' type
* ;)
*/
AliasInitializer parseAliasInitializer()
{
auto node = new AliasInitializer;
node.identifier = *expect(TokenType.identifier);
expect(TokenType.assign);
node.type = parseType();
return node;
}
/**
* Parses an AliasThisDeclaration
* $(GRAMMAR aliasThisDeclaration: 'alias' Identifier 'this' ';'
* ;)
*/
AliasThisDeclaration parseAliasThisDeclaration()
{
auto node = new AliasThisDeclaration;
expect(TokenType.alias_);
node.identifier = *expect(TokenType.identifier);
expect(TokenType.this_);
expect(TokenType.semicolon);
return node;
}
/**
* Parses an AlignAttribute.
* $(GRAMMAR alignAttribute: 'align' ('(' IntegerLiteral ')')?
* ;)
*/
AlignAttribute parseAlignAttribute()
{
auto node = new AlignAttribute;
expect(TokenType.align_);
if (currentIs(TokenType.lParen))
{
expect(TokenType.lParen);
node.intLiteral = *expect(TokenType.intLiteral);
expect(TokenType.rParen);
}
return node;
}
/**
* Parses an AndAndExpression
* $(GRAMMAR andAndExpression: orExpression
* | andAndExpression '&&' orExpression
* ;)
*/
AndAndExpression parseAndAndExpression()
{
auto node = new AndAndExpression;
node.right = parseOrExpression();
while (currentIs(TokenType.logicAnd))
{
advance();
auto node2 = new AndAndExpression;
node2.left = node;
node2.right = parseOrExpression();
node = node2;
}
return node;
}
/**
* Parses an AndExpression
*
* $(GRAMMAR )
*/
AndExpression parseAndExpression()
{
auto node = new AndExpression;
// TODO
return node;
}
/**
* Parses an ArgumentList
*
* $(GRAMMAR )
*/
ArgumentList parseArgumentList()
{
auto node = new ArgumentList;
// TODO
return node;
}
/**
* Parses an Arguments
*
* $(GRAMMAR )
*/
Arguments parseArguments()
{
auto node = new Arguments;
expect(TokenType.lParen);
node.argumentList = parseArgumentList();
expect(TokenType.rParen);
return node;
}
/**
* Parses an ArrayInitializer
*
* $(GRAMMAR )
*/
ArrayInitializer parseArrayInitializer()
{
auto node = new ArrayInitializer;
// TODO
return node;
}
/**
* Parses an ArrayLiteral
*
* $(GRAMMAR arrayLiteral: '[' argumentList ']'
* ;)
*/
ArrayLiteral parseArrayLiteral()
{
auto node = new ArrayLiteral;
expect(TokenType.lBracket);
node.argumentList = parseArgumentList();
expect(TokenType.rBracket);
return node;
}
/**
* Parses an ArrayMemberInitialization
*
* $(GRAMMAR )
*/
ArrayMemberInitialization parseArrayMemberInitialization()
{
auto node = new ArrayMemberInitialization;
// TODO
return node;
}
/**
* Parses an ArrayMemberInitializations
*
* $(GRAMMAR )
*/
ArrayMemberInitializations parseArrayMemberInitializations()
{
auto node = new ArrayMemberInitializations;
// TODO
return node;
}
/**
* Parses an AsmAddExp
*
* $(GRAMMAR )
*/
AsmAddExp parseAsmAddExp()
{
auto node = new AsmAddExp;
// TODO
return node;
}
/**
* Parses an AsmAndExp
*
* $(GRAMMAR )
*/
AsmAndExp parseAsmAndExp()
{
auto node = new AsmAndExp;
// TODO
return node;
}
/**
* Parses an AsmBrExp
*
* $(GRAMMAR )
*/
AsmBrExp parseAsmBrExp()
{
auto node = new AsmBrExp;
// TODO
return node;
}
/**
* Parses an AsmEqualExp
*
* $(GRAMMAR )
*/
AsmEqualExp parseAsmEqualExp()
{
auto node = new AsmEqualExp;
// TODO
return node;
}
/**
* Parses an AsmExp
*
* $(GRAMMAR )
*/
AsmExp parseAsmExp()
{
auto node = new AsmExp;
return node;
}
/**
* Parses an AsmInstruction
*
* $(GRAMMAR )
*/
AsmInstruction parseAsmInstruction()
{
auto node = new AsmInstruction;
return node;
}
/**
* Parses an AsmLogAndExp
*
* $(GRAMMAR )
*/
AsmLogAndExp parseAsmLogAndExp()
{
auto node = new AsmLogAndExp;
return node;
}
/**
* Parses an AsmLogOrExp
*
* $(GRAMMAR )
*/
AsmLogOrExp parseAsmLogOrExp()
{
auto node = new AsmLogOrExp;
return node;
}
/**
* Parses an AsmMulExp
*
* $(GRAMMAR )
*/
AsmMulExp parseAsmMulExp()
{
auto node = new AsmMulExp;
return node;
}
/**
* Parses an AsmOrExp
*
* $(GRAMMAR )
*/
AsmOrExp parseAsmOrExp()
{
auto node = new AsmOrExp;
return node;
}
/**
* Parses an AsmPrimaryExp
*
* $(GRAMMAR )
*/
AsmPrimaryExp parseAsmPrimaryExp()
{
auto node = new AsmPrimaryExp;
return node;
}
/**
* Parses an AsmRelExp
*
* $(GRAMMAR )
*/
AsmRelExp parseAsmRelExp()
{
auto node = new AsmRelExp;
return node;
}
/**
* Parses an AsmShiftExp
*
* $(GRAMMAR )
*/
AsmShiftExp parseAsmShiftExp()
{
auto node = new AsmShiftExp;
return node;
}
/**
* Parses an AsmStatement
*
* $(GRAMMAR )
*/
AsmStatement parseAsmStatement()
{
auto node = new AsmStatement;
return node;
}
/**
* Parses an AsmTypePrefix
*
* $(GRAMMAR )
*/
AsmTypePrefix parseAsmTypePrefix()
{
auto node = new AsmTypePrefix;
return node;
}
/**
* Parses an AsmUnaExp
*
* $(GRAMMAR )
*/
AsmUnaExp parseAsmUnaExp()
{
auto node = new AsmUnaExp;
return node;
}
/**
* Parses an AsmXorExp
*
* $(GRAMMAR )
*/
AsmXorExp parseAsmXorExp()
{
auto node = new AsmXorExp;
return node;
}
/**
* Parses an AssertExpression
*
* $(GRAMMAR )
*/
AssertExpression parseAssertExpression()
{
auto node = new AssertExpression;
return node;
}
/**
* Parses an AssertStatement
*
* $(GRAMMAR )
*/
AssertStatement parseAssertStatement()
{
auto node = new AssertStatement;
return node;
}
/**
* Parses an AssignExpression
*
* $(GRAMMAR )
*/
AssignExpression parseAssignExpression()
{
auto node = new AssignExpression;
return node;
}
/**
* Parses an AssignStatement
*
* $(GRAMMAR )
*/
AssignStatement parseAssignStatement()
{
auto node = new AssignStatement;
return node;
}
/**
* Parses an AssocArrayLiteral
*
* $(GRAMMAR assocArrayLiteral: '[' keyValuePairs ']'
* ;)
*/
AssocArrayLiteral parseAssocArrayLiteral()
{
auto node = new AssocArrayLiteral;
expect(TokenType.lBracket);
node.keyValuePairs = parseKeyValuePairs();
expect(TokenType.rBracket);
return node;
}
/**
* Parses an AtAttribute
*
* $(GRAMMAR )
*/
AtAttribute parseAtAttribute()
{
auto node = new AtAttribute;
return node;
}
/**
* Parses an Attribute
*
* $(GRAMMAR )
*/
Attribute parseAttribute()
{
auto node = new Attribute;
return node;
}
/**
* Parses an AttributedDeclaration
*
* $(GRAMMAR )
*/
AttributedDeclaration parseAttributedDeclaration()
{
auto node = new AttributedDeclaration;
return node;
}
/**
* Parses an AutoDeclaration
*
* $(GRAMMAR )
*/
AutoDeclaration parseAutoDeclaration()
{
auto node = new AutoDeclaration;
return node;
}
/**
* Parses a BlockStatement
*
* $(GRAMMAR blockStatement: '{' declarationsAndStatements? '}'
* ;)
*/
BlockStatement parseBlockStatement()
{
auto node = new BlockStatement();
expect(TokenType.lBrace);
if (!currentIs(TokenType.rBrace))
node.declarationsAndStatements = parseDeclarationsAndStatements();
expect(TokenType.rBrace);
return node;
}
/**
* Parses a BodyStatement
*
* $(GRAMMAR bodyStatement: 'body' blockStatement
* ;)
*/
BodyStatement parseBodyStatement()
{
auto node = new BodyStatement;
expect(TokenType.body_);
node.blockStatement = parseBlockStatement();
return node;
}
/**
* Parses a BreakStatement
*
* $(GRAMMAR breakStatement: 'break' Identifier? ';'
* ;)
*/
BreakStatement parseBreakStatement()
{
expect(TokenType.break_);
auto node = new BreakStatement;
switch (current().type)
{
case TokenType.identifier:
node.identifier = advance();
expect(TokenType.semicolon);
break;
case TokenType.semicolon:
advance();
break;
default:
error("Identifier or semicolon expected following \"break\"");
return null;
}
return node;
}
/**
* Parses an BuiltinType
*
* $(GRAMMAR builtinType: 'bool'
* | 'byte'
* | 'ubyte'
* | 'short'
* | 'ushort'
* | 'int'
* | 'uint'
* | 'long'
* | 'ulong'
* | 'char'
* | 'wchar'
* | 'dchar'
* | 'float'
* | 'double'
* | 'real'
* | 'ifloat'
* | 'idouble'
* | 'ireal'
* | 'cfloat'
* | 'cdouble'
* | 'creal'
* | 'void'
* ;)
*/
BasicType parseBasicType()
{
auto node = new BasicType;
if (isBasicType(current().type))
node.type = advance().type;
else
{
error("Basic type expected");
return null;
}
return node;
}
/**
* Parses a CaseRangeStatement
*
* $(GRAMMAR caseRangeStatement: 'case' assignExpression ':' '...' 'case' assignExpression ':' declarationsAndStatements
* ;)
*/
CaseRangeStatement parseCaseRangeStatement()
{
auto node = new CaseRangeStatement;
expect(TokenType.case_);
node.low = parseAssignExpression();
expect(TokenType.colon);
expect(TokenType.vararg);
expect(TokenType.case_);
node.high = parseAssignExpression();
expect(TokenType.colon);
node.declarationsAndStatements = parseDeclarationsAndStatements();
return node;
}
/**
* Parses an CaseStatement
*
* $(GRAMMAR caseStatement: 'case' argumentList ':' declarationsAndStatements
* ;)
*/
CaseStatement parseCaseStatement()
{
auto node = new CaseStatement;
expect(TokenType.case_);
node.argumentList = parseArgumentList();
expect(TokenType.colon);
node.declarationsAndStatements = parseDeclarationsAndStatements();
return node;
}
/**
* Parses an CastExpression
*
* $(GRAMMAR )
*/
CastExpression parseCastExpression()
{
auto node = new CastExpression;
return node;
}
/**
* Parses a CastQualifier
*
* $(GRAMMAR castQualifier: 'const'
* | 'const' 'shared'
* | 'immutable'
* | 'inout'
* | 'inout' 'shared'
* | 'shared'
* | 'shared' 'const'
* | 'shared' 'inout'
* ;)
*/
CastQualifier parseCastQualifier()
{
auto node = new CastQualifier;
switch (current().type)
{
case TokenType.inout_:
case TokenType.const_:
node.first = advance().type;
if (currentIs(TokenType.shared_))
node.second = advance().type;
break;
case TokenType.shared_:
node.first = advance().type;
if (currentIsOneOf(TokenType.const_, TokenType.inout_))
node.second = advance().type;
break;
case TokenType.immutable_:
node.first = advance().type;
break;
default:
error("const, immutable, inout, or shared expected");
return null;
}
return node;
}
/**
* Parses a Catch
*
* $(GRAMMAR catch_: 'catch' '(' type Identifier? ')' nonEmptyStatementNoCaseNoDefault
* ;)
*/
Catch parseCatch()
{
auto node = new Catch;
expect(TokenType.catch_);
expect(TokenType.lParen);
node.type = parseType();
if (currentIs(TokenType.identifier))
node.identifier = advance();
expect(TokenType.rParen);
node.nonEmptyStatementNoCaseNoDefault = parseNonEmptyStatementNoCaseNoDefault();
return node;
}
/**
* Parses a Catches
*
* $(GRAMMAR )
*/
Catches parseCatches()
{
auto node = new Catches;
return node;
}
/**
* Parses an ClassBody
*
* $(GRAMMAR classBody: '{' declarationOrInvariant* '}'
* ;)
*/
ClassBody parseClassBody()
{
auto node = new ClassBody;
expect(TokenType.lBrace);
while (!currentIs(TokenType.rBrace))
node.declarationOrInvariants ~= parseDeclarationOrInvariant();
expect(TokenType.rBrace);
return node;
}
/**
* Parses an ClassDeclaration
*
* $(GRAMMAR classDeclaration: 'class' Identifier (templateParameters constraint?)? (':' identifierList )? classBody
* ;)
*/
ClassDeclaration parseClassDeclaration()
{
auto node = new ClassDeclaration;
expect(TokenType.class_);
node.name = *expect(TokenType.identifier);
if (currentIs(TokenType.lParen))
{
node.templateParameters = parseTemplateParameters();
if (currentIs(TokenType.if_))
node.constraint = parseConstraint();
}
if (currentIs(TokenType.colon))
node.superClasses = parseIdentifierList();
node.classBody = parseClassBody();
return node;
}
/**
* Parses an CmpExpression
*
* $(GRAMMAR )
*/
CmpExpression parseCmpExpression()
{
auto node = new CmpExpression;
return node;
}
/**
* Parses a CompileCondition
*
* $(GRAMMAR compileCondition: versionCondition
* | debugCondition
* | staticIfCondition
* ;)
*/
CompileCondition parseCompileCondition()
{
auto node = new CompileCondition;
switch (current().type)
{
case TokenType.version_:
node.versionCondition = parseVersionCondition();
break;
case TokenType.debug_:
node.debugCondition = parseDebugCondition();
break;
case TokenType.static_:
node.staticIfCondition = parseStaticIfCondition();
break;
default:
error(`"version", "debug", or "static" expected`);
return null;
}
return node;
}
/**
* Parses an ConditionalDeclaration
*
* $(GRAMMAR )
*/
ConditionalDeclaration parseConditionalDeclaration()
{
auto node = new ConditionalDeclaration;
return node;
}
/**
* Parses an ConditionalStatement
*
* $(GRAMMAR )
*/
ConditionalStatement parseConditionalStatement()
{
auto node = new ConditionalStatement;
return node;
}
/**
* Parses an Constraint
*
* $(GRAMMAR constraint: 'if' '(' expression ')'
* ;)
*/
Constraint parseConstraint()
{
auto node = new Constraint;
expect(TokenType.if_);
expect(TokenType.lParen);
node.expression = parseExpression();
expect(TokenType.rParen);
return node;
}
/**
* Parses a Constructor
*
* $(GRAMMAR constructor: 'this' parameters functionBody
* ;)
*/
Constructor parseConstructor()
{
auto node = new Constructor;
expect(TokenType.this_);
node.parameters = parseParameters();
node.functionBody = parseFunctionBody();
return node;
}
/**
* Parses an ContinueStatement
*
* $(GRAMMAR continueStatement: 'continue' Identifier? ';'
* ;)
*/
ContinueStatement parseContinueStatement()
{
expect(TokenType.continue_);
auto node = new ContinueStatement;
switch (current().type)
{
case TokenType.identifier:
node.identifier = advance();
expect(TokenType.semicolon);
break;
case TokenType.semicolon:
advance();
break;
default:
error(`Identifier or semicolon expected following "continue"`);
return null;
}
return node;
}
/**
* Parses an DebugCondition
*
* $(GRAMMAR debugCondition: 'debug' ('(' (IntegerLiteral | Identifier) ')')?
* ;)
*/
DebugCondition parseDebugCondition()
{
auto node = new DebugCondition;
expect(TokenType.debug_);
if (currentIs(TokenType.lParen))
{
advance();
node.hasIdentifierOrInteger = true;
if (currentIsOneOf(TokenType.intLiteral, TokenType.identifier))
node.identifierOrInteger = advance();
else
{
error(`Integer literal or identifier expected`);
return null;
}
expect(TokenType.rParen);
}
else
node.hasIdentifierOrInteger = false;
return node;
}
/**
* Parses a DebugSpecification
*
* $(GRAMMAR debugSpecification: 'debug' '=' (Identifier | IntegerLiteral) ';'
* ;)
*/
DebugSpecification parseDebugSpecification()
{
auto node = new DebugSpecification;
expect(TokenType.debug_);
expect(TokenType.assign);
if (currentIsOneOf(TokenType.identifier, TokenType.intLiteral))
node.identifierOrInteger = advance();
else
{
error("Integer literal or identifier expected");
return null;
}
expect(TokenType.semicolon);
return node;
}
/**
* Parses a Declaration
*
* $(GRAMMAR declaration: aliasDeclaration
* | aliasThisDeclaration
* | attributedDeclaration
* | classDeclaration
* | conditionalDeclaration
* | constructor
* | destructor
* | enumDeclaration
* | functionDeclaration
* | importDeclaration
* | interfaceDeclaration
* | mixinDeclaration
* | pragmaDeclaration
* | sharedStaticConstructor
* | sharedStaticDestructor
* | staticAssertDeclaration
* | staticConstructor
* | staticDestructor
* | structDeclaration
* | templateDeclaration
* | unionDeclaration
* | unittest
* | variableDeclaration
* ;)
*/
Declaration parseDeclaration()
{
auto node = new Declaration;
switch (current().type)
{
case TokenType.alias_:
if (startsWith(TokenType.alias_, TokenType.identifier, TokenType.this_))
node.aliasThisDeclaration = parseAliasThisDeclaration();
else
node.aliasDeclaration = parseAliasDeclaration();
break;
case TokenType.class_:
node.classDeclaration = parseClassDeclaration();
break;
case TokenType.this_:
node.constructor = parseConstructor();
break;
case TokenType.tilde:
node.destructor = parseDestructor();
break;
case TokenType.enum_:
node.enumDeclaration = parseEnumDeclaration();
break;
case TokenType.import_:
node.importDeclaration = parseImportDeclaration();
break;
case TokenType.interface_:
node.interfaceDeclaration = parseInterfaceDeclaration();
break;
case TokenType.mixin_:
node.mixinDeclaration = parseMixinDeclaration();
break;
case TokenType.pragma_:
node.pragmaDeclaration = parsePragmaDeclaration();
break;
case TokenType.shared_:
// TODO:
// sharedStaticConstructor shared static this
// sharedStaticDestructor shared static ~ this
// attributedDeclaration shared anything else
break;
case TokenType.static_:
// TODO:
// staticConstructor static this
// staticDestructor static ~
// attributedDeclaration static anything else
// conditionalDeclaration static if
break;
case TokenType.struct_:
node.structDeclaration = parseStructDeclaration();
break;
case TokenType.template_:
node.templateDeclaration = parseTemplateDeclaration();
break;
case TokenType.union_:
node.unionDeclaration = parseUnionDeclaration();
break;
case TokenType.unittest_:
node.unittest_ = parseUnittest();
break;
case TokenType.identifier:
// TODO:
// variableDeclaration
// functionDeclaration
break;
case TokenType.version_:
case TokenType.debug_:
node.conditionalDeclaration = parseConditionalDeclaration();
break;
default:
error("Declaration expected");
return null;
}
return node;
}
/**
* Parses an DeclarationsAndStatements
*
* $(GRAMMAR )
*/
DeclarationsAndStatements parseDeclarationsAndStatements()
{
auto node = new DeclarationsAndStatements;
return node;
}
/**
* Parses a DeclarationOrInvariant
*
* $(GRAMMAR declarationOrInvariant : declaration
* | invariant
* ;)
*/
DeclarationOrInvariant parseDeclarationOrInvariant()
{
auto node = new DeclarationOrInvariant;
if (currentIs(TokenType.invariant_))
node.invariant_ = parseInvariant();
else
node.declaration = parseDeclaration();
return node;
}
/**
* Parses a Declarator
*
* $(GRAMMAR declarator: Identifier declaratorSuffix? ('=' initializer)?
* ;)
*/
Declarator parseDeclarator()
{
auto node = new Declarator;
node.identifier = *expect(TokenType.identifier);
if (currentIs(TokenType.lBracket))
node.declaratorSuffix = parseDeclaratorSuffix();
if (currentIs(TokenType.assign))
{
advance();
node.initializer = parseInitializer();
}
return node;
}
/**
* Parses an DeclaratorSuffix
*
* $(GRAMMAR )
*/
DeclaratorSuffix parseDeclaratorSuffix()
{
auto node = new DeclaratorSuffix;
return node;
}
/**
* Parses an DefaultStatement
*
* $(GRAMMAR )
*/
DefaultStatement parseDefaultStatement()
{
auto node = new DefaultStatement;
return node;
}
/**
* Parses an DeleteExpression
*
* $(GRAMMAR )
*/
DeleteExpression parseDeleteExpression()
{
auto node = new DeleteExpression;
return node;
}
/**
* Parses an DeleteStatement
*
* $(GRAMMAR )
*/
DeleteStatement parseDeleteStatement()
{
auto node = new DeleteStatement;
return node;
}
/**
* Parses a Deprecated attribute
*
* $(GRAMMAR deprecated: 'deprecated' ('(' assignExpression ')')?
* ;)
*/
Deprecated parseDeprecated()
{
auto node = new Deprecated;
expect(TokenType.deprecated_);
if (currentIs(TokenType.lParen))
{
advance();
node.assignExpression = parseAssignExpression();
expect(TokenType.rParen);
}
return node;
}
/**
* Parses a Destructor
*
* $(GRAMMAR destructor: '~' 'this' '(' ')' functionBody
* ;)
*/
Destructor parseDestructor()
{
auto node = new Destructor;
expect(TokenType.tilde);
expect(TokenType.this_);
expect(TokenType.lParen);
expect(TokenType.rParen);
node.functionBody = parseFunctionBody();
return node;
}
/**
* Parses an DoStatement
*
* $(GRAMMAR )
*/
DoStatement parseDoStatement()
{
auto node = new DoStatement;
return node;
}
/**
* Parses an EnumBody
*
* $(GRAMMAR )
*/
EnumBody parseEnumBody()
{
auto node = new EnumBody;
return node;
}
/**
* Parses an EnumDeclaration
*
* $(GRAMMAR )
*/
EnumDeclaration parseEnumDeclaration()
{
auto node = new EnumDeclaration;
return node;
}
/**
* Parses an EnumMember
*
* $(GRAMMAR )
*/
EnumMember parseEnumMember()
{
auto node = new EnumMember;
return node;
}
/**
* Parses an EqualExpression
*
* $(GRAMMAR )
*/
EqualExpression parseEqualExpression()
{
auto node = new EqualExpression;
return node;
}
/**
* Parses an Expression
*
* $(GRAMMAR )
*/
Expression parseExpression()
{
auto node = new Expression;
return node;
}
/**
* Parses an FinalSwitchStatement
*
* $(GRAMMAR )
*/
FinalSwitchStatement parseFinalSwitchStatement()
{
auto node = new FinalSwitchStatement;
return node;
}
/**
* Parses an Finally
*
* $(GRAMMAR )
*/
Finally parseFinally()
{
auto node = new Finally;
return node;
}
/**
* Parses an ForStatement
*
* $(GRAMMAR )
*/
ForStatement parseForStatement()
{
auto node = new ForStatement;
return node;
}
/**
* Parses an ForeachRangeStatement
*
* $(GRAMMAR )
*/
ForeachRangeStatement parseForeachRangeStatement()
{
auto node = new ForeachRangeStatement;
return node;
}
/**
* Parses an ForeachStatement
*
* $(GRAMMAR )
*/
ForeachStatement parseForeachStatement()
{
auto node = new ForeachStatement;
return node;
}
/**
* Parses an ForeachType
*
* $(GRAMMAR )
*/
ForeachType parseForeachType()
{
auto node = new ForeachType;
return node;
}
/**
* Parses an ForeachTypeList
*
* $(GRAMMAR )
*/
ForeachTypeList parseForeachTypeList()
{
auto node = new ForeachTypeList;
return node;
}
/**
* Parses an FunctionAttribute
*
* $(GRAMMAR )
*/
FunctionAttribute parseFunctionAttribute()
{
auto node = new FunctionAttribute;
return node;
}
/**
* Parses an FunctionBody
*
* $(GRAMMAR )
*/
FunctionBody parseFunctionBody()
{
auto node = new FunctionBody;
return node;
}
/**
* Parses an FunctionCallExpression
*
* $(GRAMMAR )
*/
FunctionCallExpression parseFunctionCallExpression()
{
auto node = new FunctionCallExpression;
return node;
}
/**
* Parses an FunctionCallStatement
*
* $(GRAMMAR )
*/
FunctionCallStatement parseFunctionCallStatement()
{
auto node = new FunctionCallStatement;
return node;
}
/**
* Parses an FunctionDeclaration
*
* $(GRAMMAR )
*/
FunctionDeclaration parseFunctionDeclaration()
{
auto node = new FunctionDeclaration;
return node;
}
/**
* Parses an FunctionLiteralExpression
*
* $(GRAMMAR )
*/
FunctionLiteralExpression parseFunctionLiteralExpression()
{
auto node = new FunctionLiteralExpression;
return node;
}
/**
* Parses an GotoStatement
*
* $(GRAMMAR )
*/
GotoStatement parseGotoStatement()
{
auto node = new GotoStatement;
return node;
}
/**
* Parses an IdentifierChain
*
* $(GRAMMAR identifierChain: Identifier ('.' Identifier)*
* ;)
*/
IdentifierChain parseIdentifierChain()
{
auto node = new IdentifierChain;
while (true)
{
node.identifiers ~= *expect(TokenType.identifier);
if (currentIs(TokenType.dot))
{
advance();
continue;
}
else
break;
}
return node;
}
/**
* Parses an IdentifierList
*
* $(GRAMMAR identifierList: Identifier (',' Identifier)*
* ;)
*/
IdentifierList parseIdentifierList()
{
auto node = new IdentifierList;
while (true)
{
node.identifiers ~= *expect(TokenType.identifier);
if (currentIs(TokenType.comma))
{
advance();
continue;
}
else
break;
}
return node;
}
/**
* Parses an IdentifierOrTemplateChain
*
* $(GRAMMAR )
*/
IdentifierOrTemplateChain parseIdentifierOrTemplateChain()
{
auto node = new IdentifierOrTemplateChain;
return node;
}
/**
* Parses an IdentifierOrTemplateInstance
*
* $(GRAMMAR )
*/
IdentifierOrTemplateInstance parseIdentifierOrTemplateInstance()
{
auto node = new IdentifierOrTemplateInstance;
return node;
}
/**
* Parses an IdentityExpression
*
* $(GRAMMAR )
*/
IdentityExpression parseIdentityExpression()
{
auto node = new IdentityExpression;
return node;
}
/**
* Parses an IfStatement
*
* $(GRAMMAR )
*/
IfStatement parseIfStatement()
{
auto node = new IfStatement;
return node;
}
/**
* Parses an ImportBind
*
* $(GRAMMAR )
*/
ImportBind parseImportBind()
{
auto node = new ImportBind;
return node;
}
/**
* Parses an ImportBindings
*
* $(GRAMMAR )
*/
ImportBindings parseImportBindings()
{
auto node = new ImportBindings;
return node;
}
/**
* Parses an ImportDeclaration
*
* $(GRAMMAR )
*/
ImportDeclaration parseImportDeclaration()()
{
auto node = new ImportDeclaration;
return node;
}
/**
* Parses an ImportExpression
*
* $(GRAMMAR )
*/
ImportExpression parseImportExpression()
{
auto node = new ImportExpression;
return node;
}
/**
* Parses an ImportList
*
* $(GRAMMAR )
*/
ImportList parseImportList()
{
auto node = new ImportList;
return node;
}
/**
* Parses an InExpression
*
* $(GRAMMAR )
*/
InExpression parseInExpression()
{
auto node = new InExpression;
return node;
}
/**
* Parses an InStatement
*
* $(GRAMMAR )
*/
InStatement parseInStatement()
{
auto node = new InStatement;
return node;
}
/**
* Parses an Initialize
*
* $(GRAMMAR )
*/
Initialize parseInitialize()
{
auto node = new Initialize;
return node;
}
/**
* Parses an Initializer
*
* $(GRAMMAR )
*/
Initializer parseInitializer()
{
auto node = new Initializer;
return node;
}
/**
* Parses an InterfaceDeclaration
*
* $(GRAMMAR )
*/
InterfaceDeclaration parseInterfaceDeclaration()
{
auto node = new InterfaceDeclaration;
return node;
}
/**
* Parses an Invariant
*
* $(GRAMMAR )
*/
Invariant parseInvariant()
{
auto node = new Invariant;
return node;
}
/**
* Parses an IsExpression
*
* $(GRAMMAR )
*/
IsExpression parseIsExpression()
{
auto node = new IsExpression;
return node;
}
/**
* Parses an KeyValuePair
*
* $(GRAMMAR )
*/
KeyValuePair parseKeyValuePair()
{
auto node = new KeyValuePair;
return node;
}
/**
* Parses an KeyValuePairs
*
* $(GRAMMAR )
*/
KeyValuePairs parseKeyValuePairs()
{
auto node = new KeyValuePairs;
return node;
}
/**
* Parses an LabeledStatement
*
* $(GRAMMAR )
*/
LabeledStatement parseLabeledStatement()
{
auto node = new LabeledStatement;
node.identifier = *expect(TokenType.identifier);
expect(TokenType.colon);
node.statement = parseStatement();
return node;
}
/**
* Parses an LambdaExpression
*
* $(GRAMMAR )
*/
LambdaExpression parseLambdaExpression()
{
auto node = new LambdaExpression;
return node;
}
/**
* Parses an LastCatch
*
* $(GRAMMAR )
*/
LastCatch parseLastCatch()
{
auto node = new LastCatch;
return node;
}
/**
* Parses an LinkageAttribute
*
* $(GRAMMAR linkageAttribute: 'extern' '(' Identifier '++'? ')'
* ;)
*/
LinkageAttribute parseLinkageAttribute()
{
auto node = new LinkageAttribute;
expect(TokenType.extern_);
expect(TokenType.lParen);
node.identifier = *expect(TokenType.identifier);
if (currentIs(TokenType.increment))
{
advance();
node.hasPlusPlus = true;
}
expect(TokenType.rParen);
return node;
}
/**
* Parses an MemberFunctionAttribute
*
* $(GRAMMAR )
*/
MemberFunctionAttribute parseMemberFunctionAttribute()
{
auto node = new MemberFunctionAttribute;
return node;
}
/**
* Parses an MixinDeclaration
*
* $(GRAMMAR mixinDeclaration: mixinExpression ';'
* ;)
*/
MixinDeclaration parseMixinDeclaration()
{
auto node = new MixinDeclaration;
node.mixinExpression = parseMixinExpression();
expect(TokenType.semicolon);
return node;
}
/**
* Parses an MixinExpression
*
* $(GRAMMAR )
*/
MixinExpression parseMixinExpression()
{
auto node = new MixinExpression;
return node;
}
/**
* Parses an MixinTemplateName
*
* $(GRAMMAR )
*/
MixinTemplateName parseMixinTemplateName()
{
auto node = new MixinTemplateName;
return node;
}
/**
* Parses a Module
*
* $(GRAMMAR module: moduleDeclaration? declaration*
* ;)
*/
Module parseModule()
{
Module m = new Module;
while (index < tokens.length)
{
switch (tokens[index].type)
{
case TokenType.module_:
if (m.moduleDeclaration is null)
m.moduleDeclaration = parseModuleDeclaration();
else
error("Only one module declaration is allowed per module");
break;
default:
m.declarations ~= parseDeclaration();
}
}
return m;
}
/**
* Parses a ModuleDeclaration
*
* $(GRAMMAR moduleDeclaration: 'module' identifierChain ';'
* ;)
*/
ModuleDeclaration parseModuleDeclaration()
{
auto node = new ModuleDeclaration;
expect(TokenType.module_);
node.moduleName = parseIdentifierChain();
expect(TokenType.semicolon);
return node;
}
/**
* Parses a MulExpression
* $(GRAMMAR mulExpression: unaryExpression
* | mulExpression ('*' | '/' | '%') unaryExpression
* ;)
*/
MulExpression parseMulExpression()
{
auto node = new MulExpression;
auto left = parseUnaryExpression();
if (tokens[index] == TokenType.star || tokens[index] == TokenType.div)
{
node.operator = tokens[index++];
node.right = parseUnaryExpression();
}
return node;
}
/**
* Parses an NewAnonClassExpression
*
* $(GRAMMAR )
*/
NewAnonClassExpression parseNewAnonClassExpression()
{
auto node = new NewAnonClassExpression;
return node;
}
/**
* Parses an NewExpression
*
* $(GRAMMAR )
*/
NewExpression parseNewExpression()
{
auto node = new NewExpression;
return node;
}
/**
* Parses an NonEmptyStatement
*
* $(GRAMMAR )
*/
NonEmptyStatement parseNonEmptyStatement()
{
auto node = new NonEmptyStatement;
return node;
}
/**
* Parses an NonEmptyStatementNoCaseNoDefault
*
* $(GRAMMAR )
*/
NonEmptyStatementNoCaseNoDefault parseNonEmptyStatementNoCaseNoDefault()
{
auto node = new NonEmptyStatementNoCaseNoDefault;
return node;
}
/**
* Parses an NonVoidInitializer
*
* $(GRAMMAR )
*/
NonVoidInitializer parseNonVoidInitializer()
{
auto node = new NonVoidInitializer;
return node;
}
/**
* Parses an Opcode
*
* $(GRAMMAR )
*/
Opcode parseOpcode()
{
auto node = new Opcode;
return node;
}
/**
* Parses an Operand
*
* $(GRAMMAR )
*/
Operand parseOperand()
{
auto node = new Operand;
return node;
}
/**
* Parses an Operands
*
* $(GRAMMAR )
*/
Operands parseOperands()
{
auto node = new Operands;
return node;
}
/**
* Parses an OrExpression
*
* $(GRAMMAR )
*/
OrExpression parseOrExpression()
{
auto node = new OrExpression;
return node;
}
/**
* Parses an OrOrExpression
*
* $(GRAMMAR )
*/
OrOrExpression parseOrOrExpression()
{
auto node = new OrOrExpression;
return node;
}
/**
* Parses an OutStatement
*
* $(GRAMMAR )
*/
OutStatement parseOutStatement()
{
auto node = new OutStatement;
return node;
}
/**
* Parses an Parameter
*
* $(GRAMMAR )
*/
Parameter parseParameter()
{
auto node = new Parameter;
return node;
}
/**
* Parses an ParameterAttribute
*
* $(GRAMMAR )
*/
ParameterAttribute parseParameterAttribute()
{
auto node = new ParameterAttribute;
return node;
}
/**
* Parses an Parameters
*
* $(GRAMMAR )
*/
Parameters parseParameters()
{
auto node = new Parameters;
return node;
}
/**
* Parses an PostIncDecExpression
*
* $(GRAMMAR )
*/
PostIncDecExpression parsePostIncDecExpression()
{
auto node = new PostIncDecExpression;
return node;
}
/**
* Parses an PowExpression
*
* $(GRAMMAR )
*/
PowExpression parsePowExpression()
{
auto node = new PowExpression;
return node;
}
/**
* Parses an PragmaDeclaration
*
* $(GRAMMAR )
*/
PragmaDeclaration parsePragmaDeclaration()
{
auto node = new PragmaDeclaration;
return node;
}
/**
* Parses an PragmaExpression
*
* $(GRAMMAR )
*/
PragmaExpression parsePragmaExpression()
{
auto node = new PragmaExpression;
return node;
}
/**
* Parses an PreIncDecExpression
*
* $(GRAMMAR )
*/
PreIncDecExpression parsePreIncDecExpression()
{
auto node = new PreIncDecExpression;
return node;
}
/**
* Parses an PrimaryExpression
*
* $(GRAMMAR )
*/
PrimaryExpression parsePrimaryExpression()
{
auto node = new PrimaryExpression;
return node;
}
/**
* Parses an ProtectionAttribute
*
* $(GRAMMAR )
*/
ProtectionAttribute parseProtectionAttribute()
{
auto node = new ProtectionAttribute;
return node;
}
/**
* Parses an Register
*
* $(GRAMMAR )
*/
Register parseRegister()
{
auto node = new Register;
return node;
}
/**
* Parses an RelExpression
*
* $(GRAMMAR )
*/
RelExpression parseRelExpression()
{
auto node = new RelExpression;
return node;
}
/**
* Parses an ReturnStatement
*
* $(GRAMMAR )
*/
ReturnStatement parseReturnStatement()
{
auto node = new ReturnStatement;
expect(TokenType.return_);
if (tokens[index] != TokenType.semicolon)
node.expression = parseExpression();
expect(TokenType.semicolon);
return node;
}
/**
* Parses an ScopeGuardStatement
*
* $(GRAMMAR )
*/
ScopeGuardStatement parseScopeGuardStatement()
{
auto node = new ScopeGuardStatement;
return node;
}
/**
* Parses an SharedStaticConstructor
*
* $(GRAMMAR )
*/
SharedStaticConstructor parseSharedStaticConstructor()
{
auto node = new SharedStaticConstructor;
return node;
}
/**
* Parses an SharedStaticDestructor
*
* $(GRAMMAR )
*/
SharedStaticDestructor parseSharedStaticDestructor()
{
auto node = new SharedStaticDestructor;
return node;
}
/**
* Parses an ShiftExpression
*
* $(GRAMMAR )
*/
ShiftExpression parseShiftExpression()
{
auto node = new ShiftExpression;
return node;
}
/**
* Parses an SingleImport
*
* $(GRAMMAR )
*/
SingleImport parseSingleImport()
{
auto node = new SingleImport;
return node;
}
/**
* Parses a Statement
*
* $(GRAMMAR statement: ';'
* | nonEmptyStatement
* ;)
*/
Statement parseStatement()
{
auto node = new Statement;
if (currentIs(TokenType.semicolon))
advance();
else
node.nonEmptyStatement = parseNonEmptyStatement();
return node;
}
/**
* Parses an StatementNoCaseNoDefault
*
* $(GRAMMAR )
*/
StatementNoCaseNoDefault parseStatementNoCaseNoDefault()
{
auto node = new StatementNoCaseNoDefault;
if (tokens[index] != TokenType.semicolon)
node.nonEmptyStatementNoCaseNoDefault = parseNonEmptyStatementNoCaseNoDefault();
else
expect(TokenType.semicolon);
return node;
}
/**
* Parses an StaticAssertDeclaration
*
* $(GRAMMAR )
*/
StaticAssertDeclaration parseStaticAssertDeclaration()
{
auto node = new StaticAssertDeclaration;
node.staticAssertStatement = parseStaticAssertStatement();
return node;
}
/**
* Parses an StaticAssertStatement
*
* $(GRAMMAR )
*/
StaticAssertStatement parseStaticAssertStatement()
{
auto node = new StaticAssertStatement;
expect(TokenType.static_);
node.assertStatement = parseAssertStatement();
return node;
}
/**
* Parses an StaticConstructor
*
* $(GRAMMAR )
*/
StaticConstructor parseStaticConstructor()
{
auto node = new StaticConstructor;
expect(TokenType.static_);
expect(TokenType.this_);
expect(TokenType.lParen);
expect(TokenType.rParen);
node.functionBody = parseFunctionBody();
return node;
}
/**
* Parses an StaticDestructor
*
* $(GRAMMAR )
*/
StaticDestructor parseStaticDestructor()
{
auto node = new StaticDestructor;
expect(TokenType.static_);
expect(TokenType.tilde);
expect(TokenType.this_);
expect(TokenType.lParen);
expect(TokenType.rParen);
node.functionBody = parseFunctionBody();
return node;
}
/**
* Parses an StaticIfCondition
*
* $(GRAMMAR )
*/
StaticIfCondition parseStaticIfCondition()
{
auto node = new StaticIfCondition;
expect(TokenType.static_);
expect(TokenType.if_);
expect(TokenType.lParen);
node.assignExpression = parseAssignExpression();
expect(TokenType.rParen);
return node;
}
/**
* Parses an StorageClass
*
* $(GRAMMAR )
*/
StorageClass parseStorageClass()
{
auto node = new StorageClass;
return node;
}
/**
* Parses an StructBody
*
* $(GRAMMAR )
*/
StructBody parseStructBody()
{
auto node = new StructBody;
expect(TokenType.lBrace);
while (tokens[index] != TokenType.rBrace && moreTokens())
node.declarations ~= parseDeclaration();
expect(TokenType.rBrace);
return node;
}
/**
* Parses an StructDeclaration
*
* $(GRAMMAR structDeclaration: 'struct' Identifier (templateParameters constraint? structBody | (structBody | ';'))
* ;)
*/
StructDeclaration parseStructDeclaration()
{
auto node = new StructDeclaration;
expect(TokenType.struct_);
node.identifier = *expect(TokenType.identifier);
if (currentIs(TokenType.lParen))
{
node.templateParameters = parseTemplateParameters();
if (tokens[index] == TokenType.if_)
node.constraint = parseConstraint();
node.structBody = parseStructBody();
}
else if (currentIs(TokenType.lBrace))
{
node.structBody = parseStructBody();
}
else if (currentIs(TokenType.semicolon))
advance();
else
{
error("Template Parameters, Struct Body, or Semicolon expected");
return null;
}
return node;
}
/**
* Parses an StructInitializer
*
* $(GRAMMAR )
*/
StructInitializer parseStructInitializer()
{
auto node = new StructInitializer;
expect(TokenType.lBrace);
node.structMemberInitializers = parseStructMemberInitializers();
expect(TokenType.rBrace);
return node;
}
/**
* Parses an StructMemberInitializer
*
* $(GRAMMAR )
*/
StructMemberInitializer parseStructMemberInitializer()
{
auto node = new StructMemberInitializer;
if (startsWith(TokenType.identifier, TokenType.colon))
{
node.identifier = tokens[index++];
index++;
}
node.nonVoidInitializer = parseNonVoidInitializer();
return node;
}
/**
* Parses an StructMemberInitializers
*
* $(GRAMMAR )
*/
StructMemberInitializers parseStructMemberInitializers()
{
auto node = new StructMemberInitializers;
return node;
}
/**
* Parses an SwitchBody
*
* $(GRAMMAR )
*/
SwitchBody parseSwitchBody()
{
auto node = new SwitchBody;
expect(TokenType.lBrace);
while (moreTokens() && tokens[index] != TokenType.rBrace)
node.statements ~= parseStatement();
expect(TokenType.rBrace);
return node;
}
/**
* Parses an SwitchStatement
*
* $(GRAMMAR )
*/
SwitchStatement parseSwitchStatement()
{
auto node = new SwitchStatement;
expect(TokenType.switch_);
expect(TokenType.lParen);
node.expression = parseExpression();
expect(TokenType.rParen);
node.switchBody = parseSwitchBody();
return node;
}
/**
* Parses an Symbol
*
* $(GRAMMAR )
*/
Symbol parseSymbol()
{
auto node = new Symbol;
if (tokens[index] == TokenType.dot)
{
node.hasDot = true;
++index;
}
node.identifierOrTemplateChain = parseIdentifierOrTemplateChain();
return node;
}
/**
* Parses an SynchronizedStatement
*
* $(GRAMMAR )
*/
SynchronizedStatement parseSynchronizedStatement()
{
auto node = new SynchronizedStatement;
expect(TokenType.synchronized_);
if (tokens[index] == TokenType.lParen)
{
expect(TokenType.lParen);
node.expression = parseExpression();
expect(TokenType.rParen);
}
node.nonEmptyStatementNoCaseNoDefault = parseNonEmptyStatementNoCaseNoDefault();
return node;
}
/**
* Parses an TemplateAliasParameter
*
* $(GRAMMAR )
*/
TemplateAliasParameter parseTemplateAliasParameter()
{
auto node = new TemplateAliasParameter;
return node;
}
/**
* Parses an TemplateArgument
*
* $(GRAMMAR )
*/
TemplateArgument parseTemplateArgument()
{
auto node = new TemplateArgument;
return node;
}
/**
* Parses an TemplateArgumentList
*
* $(GRAMMAR )
*/
TemplateArgumentList parseTemplateArgumentList()
{
auto node = new TemplateArgumentList;
return node;
}
/**
* Parses an TemplateArguments
*
* $(GRAMMAR )
*/
TemplateArguments parseTemplateArguments()
{
auto node = new TemplateArguments;
return node;
}
/**
* Parses an TemplateDeclaration
*
* $(GRAMMAR )
*/
TemplateDeclaration parseTemplateDeclaration()
{
auto node = new TemplateDeclaration;
return node;
}
/**
* Parses an TemplateInstance
*
* $(GRAMMAR )
*/
TemplateInstance parseTemplateInstance()
{
auto node = new TemplateInstance;
return node;
}
/**
* Parses an TemplateMixinStatement
*
* $(GRAMMAR )
*/
TemplateMixinStatement parseTemplateMixinStatement()
{
auto node = new TemplateMixinStatement;
return node;
}
/**
* Parses an TemplateParameter
*
* $(GRAMMAR )
*/
TemplateParameter parseTemplateParameter()
{
auto node = new TemplateParameter;
return node;
}
/**
* Parses an TemplateParameterList
*
* $(GRAMMAR )
*/
TemplateParameterList parseTemplateParameterList()
{
auto node = new TemplateParameterList;
return node;
}
/**
* Parses an TemplateParameters
*
* $(GRAMMAR )
*/
TemplateParameters parseTemplateParameters()
{
auto node = new TemplateParameters;
return node;
}
/**
* Parses an TemplateSingleArgument
*
* $(GRAMMAR )
*/
TemplateSingleArgument parseTemplateSingleArgument()
{
auto node = new TemplateSingleArgument;
return node;
}
/**
* Parses an TemplateThisParameter
*
* $(GRAMMAR )
*/
TemplateThisParameter parseTemplateThisParameter()
{
auto node = new TemplateThisParameter;
return node;
}
/**
* Parses an TemplateTupleParameter
*
* $(GRAMMAR )
*/
TemplateTupleParameter parseTemplateTupleParameter()
{
auto node = new TemplateTupleParameter;
return node;
}
/**
* Parses an TemplateTypeParameter
*
* $(GRAMMAR )
*/
TemplateTypeParameter parseTemplateTypeParameter()
{
auto node = new TemplateTypeParameter;
return node;
}
/**
* Parses an TemplateValueParameter
*
* $(GRAMMAR )
*/
TemplateValueParameter parseTemplateValueParameter()
{
auto node = new TemplateValueParameter;
return node;
}
/**
* Parses an TemplateValueParameterDefault
*
* $(GRAMMAR )
*/
TemplateValueParameterDefault parseTemplateValueParameterDefault()
{
auto node = new TemplateValueParameterDefault;
return node;
}
/**
* Parses an TernaryExpression
*
* $(GRAMMAR )
*/
TernaryExpression parseTernaryExpression()
{
auto node = new TernaryExpression;
node.orOrExpression = parseOrOrExpression();
if (tokens[index] == TokenType.ternary)
{
++index;
node.expression = parseExpression();
expect(TokenType.colon);
node.ternaryExpression = parseTernaryExpression();
}
return node;
}
/**
* Parses an ThrowStatement
*
* $(GRAMMAR )
*/
ThrowStatement parseThrowStatement()
{
auto node = new ThrowStatement;
expect(TokenType.throw_);
node.expression = parseExpression();
expect(TokenType.semicolon);
return node;
}
/**
* Parses an TraitsArgument
*
* $(GRAMMAR )
*/
TraitsArgument parseTraitsArgument()
{
auto node = new TraitsArgument;
return node;
}
/**
* Parses an TraitsExpression
*
* $(GRAMMAR )
*/
TraitsExpression parseTraitsExpression()
{
auto node = new TraitsExpression;
return node;
}
/**
* Parses an TryStatement
*
* $(GRAMMAR )
*/
TryStatement parseTryStatement()
{
auto node = new TryStatement;
return node;
}
/**
* Parses an Type
*
* $(GRAMMAR )
*/
Type parseType()
{
auto node = new Type;
return node;
}
/**
* Parses an Type2
*
* $(GRAMMAR )
*/
Type2 parseType2()
{
auto node = new Type2;
return node;
}
/**
* Parses an Type3
*
* $(GRAMMAR )
*/
Type3 parseType3()
{
auto node = new Type3;
return node;
}
/**
* Parses an TypeConstructor
*
* $(GRAMMAR )
*/
TypeConstructor parseTypeConstructor()
{
auto node = new TypeConstructor;
return node;
}
/**
* Parses an TypeConstructors
*
* $(GRAMMAR )
*/
TypeConstructors parseTypeConstructors()
{
auto node = new TypeConstructors;
return node;
}
/**
* Parses an TypeSpecialization
*
* $(GRAMMAR )
*/
TypeSpecialization parseTypeSpecialization()
{
auto node = new TypeSpecialization;
return node;
}
/**
* Parses an TypeSuffix
*
* $(GRAMMAR )
*/
TypeSuffix parseTypeSuffix()
{
auto node = new TypeSuffix;
return node;
}
/**
* Parses an TypeidExpression
*
* $(GRAMMAR )
*/
TypeidExpression parseTypeidExpression()
{
auto node = new TypeidExpression;
return node;
}
/**
* Parses an TypeofExpression
*
* $(GRAMMAR )
*/
TypeofExpression parseTypeofExpression()
{
auto node = new TypeofExpression;
expect(TokenType.typeof_);
expect(TokenType.lParen);
if (tokens[index] == TokenType.return_)
node.return_ = tokens[index];
else
node.expression = parseExpression();
expect(TokenType.rParen);
return node;
}
/**
* Parses an UnaryExpression
*
* $(GRAMMAR )
*/
UnaryExpression parseUnaryExpression()
{
auto node = new UnaryExpression;
return node;
}
/**
* Parses an UnionDeclaration
*
* $(GRAMMAR )
*/
UnionDeclaration parseUnionDeclaration()
{
auto node = new UnionDeclaration;
return node;
}
/**
* Parses an Unittest
*
* $(GRAMMAR )
*/
Unittest parseUnittest()
{
auto node = new Unittest;
expect(TokenType.unittest_);
node.blockStatement = parseBlockStatement();
return node;
}
/**
* Parses a VariableDeclaration
*
* $(GRAMMAR )
*/
VariableDeclaration parseVariableDeclaration()
{
auto node = new VariableDeclaration;
return node;
}
/**
* Parses a VersionCondition
*
* $(GRAMMAR versionCondition: 'version' '(' (IntegerLiteral | Identifier | 'unittest' | 'assert') ')'
* ;)
*/
VersionCondition parseVersionCondition()
{
auto node = new VersionCondition;
expect(TokenType.version_);
expect(TokenType.lParen);
if (currentIsOneOf(TokenType.intLiteral, TokenType.identifier,
TokenType.unittest_, TokenType.assert_))
{
node.token = advance();
}
else
{
error(`Expected an integer literal, an identifier, "assert", or "unittest"`);
return null;
}
expect(TokenType.rParen);
return node;
}
/**
* Parses a VersionSpecification
*
* $(GRAMMAR versionSpecification: 'version' '=' (Identifier | IntegerLiteral) ';'
* ;)
*/
VersionSpecification parseVersionSpecification()
{
auto node = new VersionSpecification;
expect(TokenType.version_);
expect(TokenType.assign);
if (!currentIsOneOf(TokenType.identifier, TokenType.intLiteral))
{
error("Identifier or integer literal expected");
return null;
}
node.token = advance();
expect(TokenType.semicolon);
return node;
}
/**
* Parses an WhileStatement
*
* $(GRAMMAR whileStatement: 'while' '(' expression ')' statementNoCaseNoDefault
* ;)
*/
WhileStatement parseWhileStatement()
{
auto node = new WhileStatement;
expect(TokenType.while_);
expect(TokenType.lParen);
node.expression = parseExpression();
expect(TokenType.rParen);
node.statementNoCaseNoDefault = parseStatementNoCaseNoDefault();
return node;
}
/**
* Parses an WithStatement
*
* $(GRAMMAR )
*/
WithStatement parseWithStatement()
{
auto node = new WithStatement;
expect(TokenType.with_);
expect(TokenType.lParen);
// magic here
expect(TokenType.rParen);
parseNonEmptyStatementNoCaseNoDefault();
return node;
}
/**
* Parses an XorExpression
*
* $(GRAMMAR )
*/
XorExpression parseXorExpression()
{
auto node = new XorExpression;
// TODO
return node;
}
void error(string message)
{
++errorCount;
import std.stdio;
stderr.writefln("%s(%d:%d): %s", fileName, tokens[index].line,
tokens[index].column, message);
while (index < tokens.length)
{
if (tokens[++index].type == TokenType.semicolon)
break;
}
}
Token* peekPast(alias O, alias C)()
in
{
assert (tokens[index].type == O);
}
body
{
int depth = 1;
auto i = index;
++i;
while (index < tokens.length)
{
if (tokens[i] == O)
++depth;
else if (tokens[i] == C)
{
--depth;
++i;
if (depth <= 0)
break;
}
++i;
}
return depth == 0 ? &tokens[i] : null;
}
Token* peekPastParens()
{
return peekPast!(TokenType.lParen, TokenType.rParen)();
}
Token* peekPastBrackets()
{
return peekPast!(TokenType.lBracket, TokenType.rBracket)();
}
Token* peekPastBraces()
{
return peekPast!(TokenType.lBrace, TokenType.rBrace)();
}
/**
* Returns a token of the specified type if it was the next token, otherwise
* calls the error function and returns null.
*/
Token* expect(TokenType type)
{
if (tokens[index].type == type)
return &tokens[index++];
else
{
error("Expected " ~ to!string(type));
return null;
}
}
/**
* Returns: the current token
*/
Token current()
{
return tokens[index];
}
/**
* Advances to the next token and returns the current token
*/
Token advance()
{
return tokens[index++];
}
/**
* Returns: true if the current token has the given type
*/
bool currentIs(TokenType type)
{
return tokens[index] == type;
}
/**
* Returns: true if the current token is one of the given types
*/
bool currentIsOneOf(TokenType[] types...)
{
return canFind(types, current().type);
}
bool startsWith(TokenType[] types...)
{
for (size_t i = 0; i != types.length; ++i)
{
if (tokens[index + i].type != types[i])
return false;
}
return true;
}
/**
* Returns: true if there are more tokens
*/
bool moreTokens()
{
return index < tokens.length;
}
uint errorCount;
Token[] tokens;
size_t index;
string fileName;
}