More work on the various expression parsing functions

This commit is contained in:
Hackerpilot 2013-06-25 01:18:09 -07:00
parent 1beef6a901
commit 635ddf79a0
4 changed files with 247 additions and 69 deletions

View File

@ -224,6 +224,7 @@ abstract class ASTVisitor
/** */ void visit(UnionDeclaration unionDeclaration) { unionDeclaration.accept(this); } /** */ void visit(UnionDeclaration unionDeclaration) { unionDeclaration.accept(this); }
/** */ void visit(Unittest unittest_) { unittest_.accept(this); } /** */ void visit(Unittest unittest_) { unittest_.accept(this); }
/** */ void visit(VariableDeclaration variableDeclaration) { variableDeclaration.accept(this); } /** */ void visit(VariableDeclaration variableDeclaration) { variableDeclaration.accept(this); }
/** */ void visit(Vector vector) { vector.accept(this); }
/** */ void visit(VersionCondition versionCondition) { versionCondition.accept(this); } /** */ void visit(VersionCondition versionCondition) { versionCondition.accept(this); }
/** */ void visit(VersionSpecification versionSpecification) { versionSpecification.accept(this); } /** */ void visit(VersionSpecification versionSpecification) { versionSpecification.accept(this); }
/** */ void visit(WhileStatement whileStatement) { whileStatement.accept(this); } /** */ void visit(WhileStatement whileStatement) { whileStatement.accept(this); }
@ -1641,8 +1642,9 @@ class PrimaryExpression : ASTNode
public: public:
mixin(DEFAULT_ACCEPT); mixin(DEFAULT_ACCEPT);
/** */ Token primary; /** */ Token primary;
/** */ Token identifier;
/** */ IdentifierOrTemplateInstance identifierOrTemplateInstance; /** */ IdentifierOrTemplateInstance identifierOrTemplateInstance;
/** */ Type type; /** */ TokenType basicType;
/** */ TypeofExpression typeofExpression; /** */ TypeofExpression typeofExpression;
/** */ TypeidExpression typeidExpression; /** */ TypeidExpression typeidExpression;
/** */ ArrayLiteral arrayLiteral; /** */ ArrayLiteral arrayLiteral;
@ -1654,6 +1656,7 @@ public:
/** */ TraitsExpression traitsExpression; /** */ TraitsExpression traitsExpression;
/** */ MixinExpression mixinExpression; /** */ MixinExpression mixinExpression;
/** */ ImportExpression importExpression; /** */ ImportExpression importExpression;
/** */ Vector vector;
} }
/// ///
@ -1819,7 +1822,7 @@ class StructDeclaration : ASTNode
{ {
public: public:
mixin(DEFAULT_ACCEPT); mixin(DEFAULT_ACCEPT);
/** */ Token identifier; /** */ Token name;
/** */ TemplateParameters templateParameters; /** */ TemplateParameters templateParameters;
/** */ Constraint constraint; /** */ Constraint constraint;
/** */ StructBody structBody; /** */ StructBody structBody;
@ -2132,6 +2135,7 @@ public:
mixin(DEFAULT_ACCEPT); mixin(DEFAULT_ACCEPT);
/** */ Token delegateOrFunction; /** */ Token delegateOrFunction;
/** */ bool star; /** */ bool star;
/** */ bool array;
/** */ Type type; /** */ Type type;
/** */ AssignExpression assignExpression; /** */ AssignExpression assignExpression;
/** */ Parameters parameters; /** */ Parameters parameters;
@ -2204,6 +2208,14 @@ public:
/** */ AutoDeclaration autoDeclaration; /** */ AutoDeclaration autoDeclaration;
} }
///
class Vector : ASTNode
{
public:
mixin(DEFAULT_ACCEPT);
/** */ Type type;
}
/// ///
class VersionCondition : ASTNode class VersionCondition : ASTNode
{ {

View File

@ -2084,7 +2084,6 @@ enum TokenType: ushort
dchar_, /// $(D_KEYWORD dchar) dchar_, /// $(D_KEYWORD dchar)
double_, /// $(D_KEYWORD double) double_, /// $(D_KEYWORD double)
float_, /// $(D_KEYWORD float) float_, /// $(D_KEYWORD float)
function_, /// $(D_KEYWORD function)
idouble_, /// $(D_KEYWORD idouble) idouble_, /// $(D_KEYWORD idouble)
ifloat_, /// $(D_KEYWORD ifloat) ifloat_, /// $(D_KEYWORD ifloat)
int_, /// $(D_KEYWORD int) int_, /// $(D_KEYWORD int)
@ -2134,6 +2133,7 @@ enum TokenType: ushort
debug_, /// $(D_KEYWORD debug) debug_, /// $(D_KEYWORD debug)
default_, /// $(D_KEYWORD default) default_, /// $(D_KEYWORD default)
delegate_, /// $(D_KEYWORD delegate) delegate_, /// $(D_KEYWORD delegate)
function_, /// $(D_KEYWORD function)
delete_, /// $(D_KEYWORD delete) delete_, /// $(D_KEYWORD delete)
do_, /// $(D_KEYWORD do) do_, /// $(D_KEYWORD do)
else_, /// $(D_KEYWORD else) else_, /// $(D_KEYWORD else)
@ -2581,7 +2581,6 @@ package immutable(string[TokenType.max + 1]) tokenValues = [
"dchar", "dchar",
"double", "double",
"float", "float",
"function",
"idouble", "idouble",
"ifloat", "ifloat",
"int", "int",
@ -2629,6 +2628,7 @@ package immutable(string[TokenType.max + 1]) tokenValues = [
"debug", "debug",
"default", "default",
"delegate", "delegate",
"function",
"delete", "delete",
"do", "do",
"else", "else",

View File

@ -70,7 +70,7 @@ import std.array;
version (unittest) import std.stdio; version (unittest) import std.stdio;
version = development; version = development;
//version = verbose; version = verbose;
version(development) import std.stdio; version(development) import std.stdio;
version(verbose) import std.stdio; version(verbose) import std.stdio;
@ -81,9 +81,10 @@ version(verbose) import std.stdio;
* tokens = the tokens parsed by std.d.lexer * tokens = the tokens parsed by std.d.lexer
* Returns: the parsed module * Returns: the parsed module
*/ */
Module parseModule(const(Token)[] tokens) Module parseModule(const(Token)[] tokens, string fileName)
{ {
auto parser = new Parser(); auto parser = new Parser();
parser.fileName = fileName;
parser.tokens = tokens; parser.tokens = tokens;
return parser.parseModule(); return parser.parseModule();
} }
@ -3285,6 +3286,7 @@ invariant() foo();
Parameter parseParameter() Parameter parseParameter()
{ {
auto node = new Parameter; auto node = new Parameter;
version (verbose) writeln("parseParameter");
while (moreTokens()) while (moreTokens())
{ {
TokenType type = parseParameterAttribute(false); TokenType type = parseParameterAttribute(false);
@ -3331,6 +3333,10 @@ invariant() foo();
case shared_: case shared_:
case const_: case const_:
case inout_: case inout_:
if (peekIs(TokenType.lParen))
return invalid;
else
goto case auto_;
case final_: case final_:
case in_: case in_:
case lazy_: case lazy_:
@ -3356,6 +3362,7 @@ invariant() foo();
*/ */
Parameters parseParameters() Parameters parseParameters()
{ {
version (verbose) writeln("parseParameters");
auto node = new Parameters; auto node = new Parameters;
expect(TokenType.lParen); expect(TokenType.lParen);
if (currentIs(TokenType.rParen)) if (currentIs(TokenType.rParen))
@ -3518,10 +3525,11 @@ q{(int a, ...)
* Parses a PrimaryExpression * Parses a PrimaryExpression
* *
* $(GRAMMAR $(RULEDEF primaryExpression): * $(GRAMMAR $(RULEDEF primaryExpression):
* $(RULE symbol) * $(LITERAL Identifier)
* | $(RULE type) $(LITERAL '.') $(LITERAL Identifier) * | $(RULE basicType) $(LITERAL '.') $(LITERAL Identifier)
* | $(RULE typeofExpression) * | $(RULE typeofExpression)
* | $(RULE typeidExpression) * | $(RULE typeidExpression)
* | $(RULE vector)
* | $(RULE arrayLiteral) * | $(RULE arrayLiteral)
* | $(RULE assocArrayLiteral) * | $(RULE assocArrayLiteral)
* | $(LITERAL '$(LPAREN)') $(RULE expression) $(LITERAL '$(RPAREN)') * | $(LITERAL '$(LPAREN)') $(RULE expression) $(LITERAL '$(RPAREN)')
@ -3560,8 +3568,25 @@ q{(int a, ...)
with (TokenType) switch (current().type) with (TokenType) switch (current().type)
{ {
case identifier: case identifier:
// TODO if (peekIs(TokenType.goesTo))
// symbol or type.identifier node.lambdaExpression = parseLambdaExpression();
else
node.identifier = advance();
break;
mixin (BASIC_TYPE_CASE_RANGE);
node.basicType = advance().type;
expect(dot);
auto t = expect(identifier);
if (t !is null)
node.identifier = *t;
break;
case function_:
case delegate_:
case lBrace:
case in_:
case out_:
case body_:
node.functionLiteralExpression = parseFunctionLiteralExpression();
break; break;
case typeof_: case typeof_:
node.typeofExpression = parseTypeofExpression(); node.typeofExpression = parseTypeofExpression();
@ -3569,19 +3594,28 @@ q{(int a, ...)
case typeid_: case typeid_:
node.typeidExpression = parseTypeidExpression(); node.typeidExpression = parseTypeidExpression();
break; break;
case vector:
node.vector = parseVector();
break;
case lBracket: case lBracket:
// TODO: array literal or associative array literal if (isAssociativeArrayLiteral())
node.assocArrayLiteral = parseAssocArrayLiteral();
else
node.arrayLiteral = parseArrayLiteral();
break; break;
case lParen: case lParen:
advance(); if (peekPastParens().type == TokenType.goesTo)
node.expression = parseExpression(); node.lambdaExpression = parseLambdaExpression();
expect(TokenType.rParen); else
{
advance();
node.expression = parseExpression();
expect(TokenType.rParen);
}
break; break;
case is_: case is_:
node.isExpression = parseIsExpression(); node.isExpression = parseIsExpression();
break; break;
// TODO: lambda
// TODO: function literal
case traits: case traits:
node.traitsExpression = parseTraitsExpression(); node.traitsExpression = parseTraitsExpression();
break; break;
@ -3596,8 +3630,8 @@ q{(int a, ...)
case null_: case null_:
case true_: case true_:
case false_: case false_:
case specialDate: .. case specialPrettyFunction: mixin (SPECIAL_CASE_RANGE);
case doubleLiteral: .. case wstringLiteral: mixin (LITERAL_CASE_RANGE);
version(verbose) writeln("special or literal ", index, " ", current()); version(verbose) writeln("special or literal ", index, " ", current());
node.primary = advance(); node.primary = advance();
break; break;
@ -3954,7 +3988,7 @@ q{(int a, ...)
{ {
auto node = new StructDeclaration; auto node = new StructDeclaration;
expect(TokenType.struct_); expect(TokenType.struct_);
node.identifier = *expect(TokenType.identifier); node.name = *expect(TokenType.identifier);
if (currentIs(TokenType.lParen)) if (currentIs(TokenType.lParen))
{ {
node.templateParameters = parseTemplateParameters(); node.templateParameters = parseTemplateParameters();
@ -4308,9 +4342,9 @@ q{(int a, ...)
case null_: case null_:
case this_: case this_:
case identifier: case identifier:
case specialDate: .. case specialTokenSequence: mixin (SPECIAL_CASE_RANGE);
case doubleLiteral: .. case wstringLiteral: mixin (LITERAL_CASE_RANGE);
case bool_: .. case wchar_: mixin (BASIC_TYPE_CASE_RANGE);
node.token = advance(); node.token = advance();
break; break;
default: default:
@ -4339,13 +4373,17 @@ q{(int a, ...)
* Parses an TemplateTupleParameter * Parses an TemplateTupleParameter
* *
* $(GRAMMAR $(RULEDEF templateTupleParameter): * $(GRAMMAR $(RULEDEF templateTupleParameter):
* $(LITERAL Identifier) '...' * $(LITERAL Identifier) $(LITERAL '...')
* ;) * ;)
*/ */
TemplateTupleParameter parseTemplateTupleParameter() TemplateTupleParameter parseTemplateTupleParameter()
{ {
auto node = new TemplateTupleParameter; auto node = new TemplateTupleParameter;
// TODO auto i = expect(TokenType.identifier);
if (i is null)
return null;
node.identifier = *i;
expect(TokenType.vararg);
return node; return node;
} }
@ -4522,19 +4560,21 @@ q{(int a, ...)
break; break;
} }
node.type2 = parseType2(); node.type2 = parseType2();
loop: while (true) if (node.type2 is null)
return null;
loop: while (true) with (TokenType) switch (current.type)
{ {
switch (current.type) case TokenType.star:
{ case TokenType.lBracket:
case TokenType.star: case TokenType.delegate_:
case TokenType.lBracket: case TokenType.function_:
case TokenType.delegate_: auto suffix = parseTypeSuffix();
case TokenType.function_: if (suffix !is null)
node.typeSuffixes ~= parseTypeSuffix(); node.typeSuffixes ~= suffix;
break; else
default: return null;
break loop; default:
} break loop;
} }
return node; return node;
} }
@ -4552,35 +4592,40 @@ q{(int a, ...)
Type2 parseType2() Type2 parseType2()
{ {
auto node = new Type2; auto node = new Type2;
switch (current.type) with (TokenType) switch (current.type)
{ {
case TokenType.identifier: case identifier:
case TokenType.dot: case dot:
node.symbol = parseSymbol(); if ((node.symbol = parseSymbol()) is null)
return null;
break; break;
case TokenType.bool_: .. case TokenType.wchar_: case bool_: .. case wchar_:
node.basicType = parseBasicType(); if ((node.basicType = parseBasicType()) == TokenType.invalid)
return null;
break; break;
case TokenType.typeof_: case typeof_:
node.typeofExpression = parseTypeofExpression(); if ((node.typeofExpression = parseTypeofExpression()) is null)
return null;
if (currentIs(TokenType.dot)) if (currentIs(TokenType.dot))
{ {
advance(); advance();
node.identifierOrTemplateChain = parseIdentifierOrTemplateChain(); node.identifierOrTemplateChain = parseIdentifierOrTemplateChain();
if (node.identifierOrTemplateChain is null)
return null;
} }
break; break;
case TokenType.const_: case const_:
case TokenType.immutable_: case immutable_:
case TokenType.inout_: case inout_:
case TokenType.shared_: case shared_:
node.typeConstructor = parseTypeConstructor(); node.typeConstructor = parseTypeConstructor();
expect(TokenType.lParen); if (expect(TokenType.lParen) is null) return null;
node.type = parseType(); if ((node.type = parseType()) is null) return null;
expect(TokenType.rParen); if (expect(TokenType.rParen) is null) return null;
break; break;
default: default:
error("Basic type, type constructor, symbol, or typeof expected"); error("Basic type, type constructor, symbol, or typeof expected");
break; return null;
} }
return node; return node;
} }
@ -4595,7 +4640,7 @@ q{(int a, ...)
* | $(LITERAL 'shared') * | $(LITERAL 'shared')
* ;) * ;)
*/ */
TokenType parseTypeConstructor(bool validate = false) TokenType parseTypeConstructor(bool validate = true)
{ {
with (TokenType) switch (current().type) with (TokenType) switch (current().type)
{ {
@ -4692,19 +4737,32 @@ q{(int a, ...)
TypeSuffix parseTypeSuffix() TypeSuffix parseTypeSuffix()
{ {
auto node = new TypeSuffix; auto node = new TypeSuffix;
switch(current().type) version (verbose) writeln("parseTypeSuffix");
with (TokenType) switch(current().type)
{ {
case TokenType.star: case star:
node.star = true; node.star = true;
advance(); advance();
return node; return node;
case TokenType.lBracket: case lBracket:
node.array = true;
advance(); advance();
// TODO: magic if (currentIs(rBracket))
goto end;
auto bookmark = setBookmark();
auto type = parseType();
if (type is null)
{
goToBookmark(bookmark);
node.assignExpression = parseAssignExpression();
}
else
node.type = type;
end:
expect(TokenType.rBracket); expect(TokenType.rBracket);
return node; return node;
case TokenType.delegate_: case delegate_:
case TokenType.function_: case function_:
advance(); advance();
node.parameters = parseParameters(); node.parameters = parseParameters();
while (currentIsMemberFunctionAttribute()) while (currentIsMemberFunctionAttribute())
@ -4928,6 +4986,23 @@ q{(int a, ...)
return node; return node;
} }
/**
* Parses a Vector
*
* $(GRAMMAR $(RULEDEF vector):
* $(LITERAL '__vector') $(LITERAL '$(LPAREN)') $(RULE type) $(LITERAL '$(RPAREN)')
* ;)
*/
Vector parseVector()
{
auto node = new Vector;
expect(TokenType.vector);
expect(TokenType.lParen);
node.type = parseType();
expect(TokenType.rParen);
return node;
}
/** /**
* Parses a VersionCondition * Parses a VersionCondition
* *
@ -5027,7 +5102,74 @@ q{(int a, ...)
TokenType.xor)(); TokenType.xor)();
} }
private bool currentIsMemberFunctionAttribute() const private:
bool isAssociativeArrayLiteral()
{
auto i = index;
scope(exit) index = i;
if (!currentIs(TokenType.lBracket))
return false;
advance();
while (moreTokens()) with (TokenType) switch (current().type)
{
case lBrace: skipBraceContent(); break;
case lParen: skipParenContent(); break;
case lBracket: skipBracketContent(); break;
case rBracket: return false;
case colon: return true;
default: break;
}
return false;
}
bool isStatement() const
{
// TODO: Not complete
with (TokenType) switch (current().type)
{
case lBrace:
case if_:
case while_:
case do_:
case for_:
case foreach_:
case foreach_reverse_:
case switch_:
case continue_:
case break_:
case return_:
case goto_:
case with_:
case try_:
case throw_:
case asm_:
case default_:
case case_:
case new_:
mixin (SPECIAL_CASE_RANGE);
mixin (LITERAL_CASE_RANGE);
case true_:
case false_:
return true;
case extern_:
case union_:
case class_:
case interface_:
case function_:
case delegate_:
case typedef_:
case typeof_:
case invariant_:
case alias_:
mixin (BASIC_TYPE_CASE_RANGE);
return false;
default:
return false;
}
}
bool currentIsMemberFunctionAttribute() const
{ {
switch (current.type) switch (current.type)
{ {
@ -5044,7 +5186,7 @@ q{(int a, ...)
} }
} }
private Left parseLeftAssocBinaryExpression(alias Left, alias Right, Operators ...) Left parseLeftAssocBinaryExpression(alias Left, alias Right, Operators ...)
(Right r = null) (Right r = null)
{ {
auto node = new Left; auto node = new Left;
@ -5063,7 +5205,7 @@ q{(int a, ...)
return node; return node;
} }
private ListType parseCommaSeparatedRule(alias ListType, alias ItemType)() ListType parseCommaSeparatedRule(alias ListType, alias ItemType)()
{ {
auto node = new ListType; auto node = new ListType;
while (true) while (true)
@ -5081,12 +5223,15 @@ q{(int a, ...)
{ {
import std.stdio; import std.stdio;
++errorCount; ++errorCount;
if (errorFunction is null) if (!suppressMessages)
stderr.writefln("%s(%d:%d): %s", fileName, tokens[index].line, {
tokens[index].column, message); if (errorFunction is null)
else stderr.writefln("%s(%d:%d): %s", fileName, tokens[index].line,
errorFunction(fileName, tokens[index].line, tokens[index].column, tokens[index].column, message);
message); else
errorFunction(fileName, tokens[index].line, tokens[index].column,
message);
}
while (moreTokens()) while (moreTokens())
{ {
if (currentIsOneOf(TokenType.semicolon, TokenType.rBrace)) if (currentIsOneOf(TokenType.semicolon, TokenType.rBrace))
@ -5257,6 +5402,18 @@ q{(int a, ...)
return index + 1 < tokens.length; return index + 1 < tokens.length;
} }
size_t setBookmark()
{
suppressMessages = true;
return index;
}
void goToBookmark(size_t i)
{
suppressMessages = false;
index = i;
}
version (unittest) static void doNothingErrorFunction(string fileName, version (unittest) static void doNothingErrorFunction(string fileName,
int line, int column, string message) {} int line, int column, string message) {}
@ -5277,4 +5434,8 @@ q{(int a, ...)
size_t index; size_t index;
string fileName; string fileName;
void function(string, int, int, string) errorFunction; void function(string, int, int, string) errorFunction;
immutable string BASIC_TYPE_CASE_RANGE = q{case bool_: .. case wchar_:};
immutable string LITERAL_CASE_RANGE = q{case doubleLiteral: .. case wstringLiteral:};
immutable string SPECIAL_CASE_RANGE = q{case specialDate: .. case specialPrettyFunction:};
bool suppressMessages;
} }

View File

@ -12,6 +12,11 @@ class TestVisitor : ASTVisitor
writeln("class ", classDeclaration.name.value, " on line ", classDeclaration.name.line); writeln("class ", classDeclaration.name.value, " on line ", classDeclaration.name.line);
} }
override void visit(StructDeclaration structDeclaration)
{
writeln("struct ", structDeclaration.name.value, " on line ", structDeclaration.name.line);
}
override void visit(ModuleDeclaration md) override void visit(ModuleDeclaration md)
{ {
writeln("module declaration found"); writeln("module declaration found");
@ -58,7 +63,7 @@ void main(string[] args)
ubyte[] rawSource = f.rawRead(sourceBuffer); ubyte[] rawSource = f.rawRead(sourceBuffer);
LexerConfig config; LexerConfig config;
auto tokens = byToken(rawSource, config).array(); auto tokens = byToken(rawSource, config).array();
Module m = parseModule(tokens); Module m = parseModule(tokens, args[1]);
ASTVisitor visitor = new TestVisitor; ASTVisitor visitor = new TestVisitor;
visitor.visit(m); visitor.visit(m);
} }