aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/parsing
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity/parsing')
-rw-r--r--libsolidity/parsing/DocStringParser.cpp2
-rw-r--r--libsolidity/parsing/Parser.cpp308
-rw-r--r--libsolidity/parsing/Parser.h42
-rw-r--r--libsolidity/parsing/ParserBase.cpp54
-rw-r--r--libsolidity/parsing/ParserBase.h2
-rw-r--r--libsolidity/parsing/Token.h11
6 files changed, 250 insertions, 169 deletions
diff --git a/libsolidity/parsing/DocStringParser.cpp b/libsolidity/parsing/DocStringParser.cpp
index d058d556..d9588e5c 100644
--- a/libsolidity/parsing/DocStringParser.cpp
+++ b/libsolidity/parsing/DocStringParser.cpp
@@ -72,7 +72,7 @@ bool DocStringParser::parse(string const& _docString, ErrorReporter& _errorRepor
auto tagNameEndPos = firstWhitespaceOrNewline(tagPos, end);
if (tagNameEndPos == end)
{
- appendError("End of tag " + string(tagPos, tagNameEndPos) + "not found");
+ appendError("End of tag " + string(tagPos, tagNameEndPos) + " not found");
break;
}
diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp
index 618a0896..e2e1eebc 100644
--- a/libsolidity/parsing/Parser.cpp
+++ b/libsolidity/parsing/Parser.cpp
@@ -54,6 +54,7 @@ public:
template <class NodeType, typename... Args>
ASTPointer<NodeType> createNode(Args&& ... _args)
{
+ solAssert(m_location.sourceName, "");
if (m_location.end < 0)
markEndPosition();
return make_shared<NodeType>(m_location, forward<Args>(_args)...);
@@ -528,7 +529,7 @@ ASTPointer<EnumDefinition> Parser::parseEnumDefinition()
break;
expectToken(Token::Comma);
if (m_scanner->currentToken() != Token::Identifier)
- fatalParserError(string("Expected Identifier after ','"));
+ fatalParserError(string("Expected identifier after ','"));
}
if (members.size() == 0)
parserError({"enum with no members is not allowed."});
@@ -1057,16 +1058,16 @@ ASTPointer<EmitStatement> Parser::parseEmitStatement(ASTPointer<ASTString> const
if (m_scanner->currentToken() != Token::Identifier)
fatalParserError("Expected event name or path.");
- vector<ASTPointer<PrimaryExpression>> path;
+ IndexAccessedPath iap;
while (true)
{
- path.push_back(parseIdentifier());
+ iap.path.push_back(parseIdentifier());
if (m_scanner->currentToken() != Token::Period)
break;
m_scanner->next();
};
- auto eventName = expressionFromIndexAccessStructure(path, {});
+ auto eventName = expressionFromIndexAccessStructure(iap);
expectToken(Token::LParen);
vector<ASTPointer<Expression>> arguments;
@@ -1083,61 +1084,124 @@ ASTPointer<EmitStatement> Parser::parseEmitStatement(ASTPointer<ASTString> const
ASTPointer<Statement> Parser::parseSimpleStatement(ASTPointer<ASTString> const& _docString)
{
RecursionGuard recursionGuard(*this);
+ LookAheadInfo statementType;
+ IndexAccessedPath iap;
+
+ if (m_scanner->currentToken() == Token::LParen)
+ {
+ ASTNodeFactory nodeFactory(*this);
+ size_t emptyComponents = 0;
+ // First consume all empty components.
+ expectToken(Token::LParen);
+ while (m_scanner->currentToken() == Token::Comma)
+ {
+ m_scanner->next();
+ emptyComponents++;
+ }
+
+ // Now see whether we have a variable declaration or an expression.
+ tie(statementType, iap) = tryParseIndexAccessedPath();
+ switch (statementType)
+ {
+ case LookAheadInfo::VariableDeclaration:
+ {
+ vector<ASTPointer<VariableDeclaration>> variables;
+ ASTPointer<Expression> value;
+ // We have already parsed something like `(,,,,a.b.c[2][3]`
+ VarDeclParserOptions options;
+ options.allowLocationSpecifier = true;
+ variables = vector<ASTPointer<VariableDeclaration>>(emptyComponents, nullptr);
+ variables.push_back(parseVariableDeclaration(options, typeNameFromIndexAccessStructure(iap)));
+
+ while (m_scanner->currentToken() != Token::RParen)
+ {
+ expectToken(Token::Comma);
+ if (m_scanner->currentToken() == Token::Comma || m_scanner->currentToken() == Token::RParen)
+ variables.push_back(nullptr);
+ else
+ variables.push_back(parseVariableDeclaration(options));
+ }
+ expectToken(Token::RParen);
+ expectToken(Token::Assign);
+ value = parseExpression();
+ nodeFactory.setEndPositionFromNode(value);
+ return nodeFactory.createNode<VariableDeclarationStatement>(_docString, variables, value);
+ }
+ case LookAheadInfo::Expression:
+ {
+ // Complete parsing the expression in the current component.
+ vector<ASTPointer<Expression>> components(emptyComponents, nullptr);
+ components.push_back(parseExpression(expressionFromIndexAccessStructure(iap)));
+ while (m_scanner->currentToken() != Token::RParen)
+ {
+ expectToken(Token::Comma);
+ if (m_scanner->currentToken() == Token::Comma || m_scanner->currentToken() == Token::RParen)
+ components.push_back(ASTPointer<Expression>());
+ else
+ components.push_back(parseExpression());
+ }
+ nodeFactory.markEndPosition();
+ expectToken(Token::RParen);
+ return parseExpressionStatement(_docString, nodeFactory.createNode<TupleExpression>(components, false));
+ }
+ default:
+ solAssert(false, "");
+ }
+ }
+ else
+ {
+ tie(statementType, iap) = tryParseIndexAccessedPath();
+ switch (statementType)
+ {
+ case LookAheadInfo::VariableDeclaration:
+ return parseVariableDeclarationStatement(_docString, typeNameFromIndexAccessStructure(iap));
+ case LookAheadInfo::Expression:
+ return parseExpressionStatement(_docString, expressionFromIndexAccessStructure(iap));
+ default:
+ solAssert(false, "");
+ }
+ }
+}
+
+bool Parser::IndexAccessedPath::empty() const
+{
+ if (!indices.empty())
+ {
+ solAssert(!path.empty(), "");
+ }
+ return path.empty() && indices.empty();
+}
+
+
+pair<Parser::LookAheadInfo, Parser::IndexAccessedPath> Parser::tryParseIndexAccessedPath()
+{
// These two cases are very hard to distinguish:
- // x[7 * 20 + 3] a; - x[7 * 20 + 3] = 9;
+ // x[7 * 20 + 3] a; and x[7 * 20 + 3] = 9;
// In the first case, x is a type name, in the second it is the name of a variable.
// As an extension, we can even have:
// `x.y.z[1][2] a;` and `x.y.z[1][2] = 10;`
// Where in the first, x.y.z leads to a type name where in the second, it accesses structs.
- switch (peekStatementType())
+
+ auto statementType = peekStatementType();
+ switch (statementType)
{
- case LookAheadInfo::VariableDeclarationStatement:
- return parseVariableDeclarationStatement(_docString);
- case LookAheadInfo::ExpressionStatement:
- return parseExpressionStatement(_docString);
+ case LookAheadInfo::VariableDeclaration:
+ case LookAheadInfo::Expression:
+ return make_pair(statementType, IndexAccessedPath());
default:
break;
}
+
// At this point, we have 'Identifier "["' or 'Identifier "." Identifier' or 'ElementoryTypeName "["'.
- // We parse '(Identifier ("." Identifier)* |ElementaryTypeName) ( "[" Expression "]" )+'
+ // We parse '(Identifier ("." Identifier)* |ElementaryTypeName) ( "[" Expression "]" )*'
// until we can decide whether to hand this over to ExpressionStatement or create a
// VariableDeclarationStatement out of it.
- vector<ASTPointer<PrimaryExpression>> path;
- bool startedWithElementary = false;
- if (m_scanner->currentToken() == Token::Identifier)
- path.push_back(parseIdentifier());
- else
- {
- startedWithElementary = true;
- unsigned firstNum;
- unsigned secondNum;
- tie(firstNum, secondNum) = m_scanner->currentTokenInfo();
- ElementaryTypeNameToken elemToken(m_scanner->currentToken(), firstNum, secondNum);
- path.push_back(ASTNodeFactory(*this).createNode<ElementaryTypeNameExpression>(elemToken));
- m_scanner->next();
- }
- while (!startedWithElementary && m_scanner->currentToken() == Token::Period)
- {
- m_scanner->next();
- path.push_back(parseIdentifier());
- }
- vector<pair<ASTPointer<Expression>, SourceLocation>> indices;
- while (m_scanner->currentToken() == Token::LBrack)
- {
- expectToken(Token::LBrack);
- ASTPointer<Expression> index;
- if (m_scanner->currentToken() != Token::RBrack)
- index = parseExpression();
- SourceLocation indexLocation = path.front()->location();
- indexLocation.end = endPosition();
- indices.push_back(make_pair(index, indexLocation));
- expectToken(Token::RBrack);
- }
+ IndexAccessedPath iap = parseIndexAccessedPath();
if (m_scanner->currentToken() == Token::Identifier || Token::isLocationSpecifier(m_scanner->currentToken()))
- return parseVariableDeclarationStatement(_docString, typeNameIndexAccessStructure(path, indices));
+ return make_pair(LookAheadInfo::VariableDeclaration, move(iap));
else
- return parseExpressionStatement(_docString, expressionFromIndexAccessStructure(path, indices));
+ return make_pair(LookAheadInfo::Expression, move(iap));
}
ASTPointer<VariableDeclarationStatement> Parser::parseVariableDeclarationStatement(
@@ -1145,6 +1209,9 @@ ASTPointer<VariableDeclarationStatement> Parser::parseVariableDeclarationStateme
ASTPointer<TypeName> const& _lookAheadArrayType
)
{
+ // This does not parse multi variable declaration statements starting directly with
+ // `(`, they are parsed in parseSimpleStatement, because they are hard to distinguish
+ // from tuple expressions.
RecursionGuard recursionGuard(*this);
ASTNodeFactory nodeFactory(*this);
if (_lookAheadArrayType)
@@ -1207,23 +1274,24 @@ ASTPointer<VariableDeclarationStatement> Parser::parseVariableDeclarationStateme
ASTPointer<ExpressionStatement> Parser::parseExpressionStatement(
ASTPointer<ASTString> const& _docString,
- ASTPointer<Expression> const& _lookAheadIndexAccessStructure
+ ASTPointer<Expression> const& _partialParserResult
)
{
RecursionGuard recursionGuard(*this);
- ASTPointer<Expression> expression = parseExpression(_lookAheadIndexAccessStructure);
+ ASTPointer<Expression> expression = parseExpression(_partialParserResult);
return ASTNodeFactory(*this, expression).createNode<ExpressionStatement>(_docString, expression);
}
ASTPointer<Expression> Parser::parseExpression(
- ASTPointer<Expression> const& _lookAheadIndexAccessStructure
+ ASTPointer<Expression> const& _partiallyParsedExpression
)
{
RecursionGuard recursionGuard(*this);
- ASTPointer<Expression> expression = parseBinaryExpression(4, _lookAheadIndexAccessStructure);
+ ASTPointer<Expression> expression = parseBinaryExpression(4, _partiallyParsedExpression);
if (Token::isAssignmentOp(m_scanner->currentToken()))
{
- Token::Value assignmentOperator = expectAssignmentOperator();
+ Token::Value assignmentOperator = m_scanner->currentToken();
+ m_scanner->next();
ASTPointer<Expression> rightHandSide = parseExpression();
ASTNodeFactory nodeFactory(*this, expression);
nodeFactory.setEndPositionFromNode(rightHandSide);
@@ -1245,11 +1313,11 @@ ASTPointer<Expression> Parser::parseExpression(
ASTPointer<Expression> Parser::parseBinaryExpression(
int _minPrecedence,
- ASTPointer<Expression> const& _lookAheadIndexAccessStructure
+ ASTPointer<Expression> const& _partiallyParsedExpression
)
{
RecursionGuard recursionGuard(*this);
- ASTPointer<Expression> expression = parseUnaryExpression(_lookAheadIndexAccessStructure);
+ ASTPointer<Expression> expression = parseUnaryExpression(_partiallyParsedExpression);
ASTNodeFactory nodeFactory(*this, expression);
int precedence = Token::precedence(m_scanner->currentToken());
for (; precedence >= _minPrecedence; --precedence)
@@ -1265,14 +1333,14 @@ ASTPointer<Expression> Parser::parseBinaryExpression(
}
ASTPointer<Expression> Parser::parseUnaryExpression(
- ASTPointer<Expression> const& _lookAheadIndexAccessStructure
+ ASTPointer<Expression> const& _partiallyParsedExpression
)
{
RecursionGuard recursionGuard(*this);
- ASTNodeFactory nodeFactory = _lookAheadIndexAccessStructure ?
- ASTNodeFactory(*this, _lookAheadIndexAccessStructure) : ASTNodeFactory(*this);
+ ASTNodeFactory nodeFactory = _partiallyParsedExpression ?
+ ASTNodeFactory(*this, _partiallyParsedExpression) : ASTNodeFactory(*this);
Token::Value token = m_scanner->currentToken();
- if (!_lookAheadIndexAccessStructure && (Token::isUnaryOp(token) || Token::isCountOp(token)))
+ if (!_partiallyParsedExpression && (Token::isUnaryOp(token) || Token::isCountOp(token)))
{
// prefix expression
m_scanner->next();
@@ -1283,7 +1351,7 @@ ASTPointer<Expression> Parser::parseUnaryExpression(
else
{
// potential postfix expression
- ASTPointer<Expression> subExpression = parseLeftHandSideExpression(_lookAheadIndexAccessStructure);
+ ASTPointer<Expression> subExpression = parseLeftHandSideExpression(_partiallyParsedExpression);
token = m_scanner->currentToken();
if (!Token::isCountOp(token))
return subExpression;
@@ -1294,16 +1362,16 @@ ASTPointer<Expression> Parser::parseUnaryExpression(
}
ASTPointer<Expression> Parser::parseLeftHandSideExpression(
- ASTPointer<Expression> const& _lookAheadIndexAccessStructure
+ ASTPointer<Expression> const& _partiallyParsedExpression
)
{
RecursionGuard recursionGuard(*this);
- ASTNodeFactory nodeFactory = _lookAheadIndexAccessStructure ?
- ASTNodeFactory(*this, _lookAheadIndexAccessStructure) : ASTNodeFactory(*this);
+ ASTNodeFactory nodeFactory = _partiallyParsedExpression ?
+ ASTNodeFactory(*this, _partiallyParsedExpression) : ASTNodeFactory(*this);
ASTPointer<Expression> expression;
- if (_lookAheadIndexAccessStructure)
- expression = _lookAheadIndexAccessStructure;
+ if (_partiallyParsedExpression)
+ expression = _partiallyParsedExpression;
else if (m_scanner->currentToken() == Token::New)
{
expectToken(Token::New);
@@ -1517,44 +1585,79 @@ Parser::LookAheadInfo Parser::peekStatementType() const
bool mightBeTypeName = (Token::isElementaryTypeName(token) || token == Token::Identifier);
if (token == Token::Mapping || token == Token::Function || token == Token::Var)
- return LookAheadInfo::VariableDeclarationStatement;
+ return LookAheadInfo::VariableDeclaration;
if (mightBeTypeName)
{
Token::Value next = m_scanner->peekNextToken();
if (next == Token::Identifier || Token::isLocationSpecifier(next))
- return LookAheadInfo::VariableDeclarationStatement;
+ return LookAheadInfo::VariableDeclaration;
if (next == Token::LBrack || next == Token::Period)
return LookAheadInfo::IndexAccessStructure;
}
- return LookAheadInfo::ExpressionStatement;
+ return LookAheadInfo::Expression;
}
-ASTPointer<TypeName> Parser::typeNameIndexAccessStructure(
- vector<ASTPointer<PrimaryExpression>> const& _path,
- vector<pair<ASTPointer<Expression>, SourceLocation>> const& _indices
-)
+Parser::IndexAccessedPath Parser::parseIndexAccessedPath()
{
- solAssert(!_path.empty(), "");
+ IndexAccessedPath iap;
+ if (m_scanner->currentToken() == Token::Identifier)
+ {
+ iap.path.push_back(parseIdentifier());
+ while (m_scanner->currentToken() == Token::Period)
+ {
+ m_scanner->next();
+ iap.path.push_back(parseIdentifier());
+ }
+ }
+ else
+ {
+ unsigned firstNum;
+ unsigned secondNum;
+ tie(firstNum, secondNum) = m_scanner->currentTokenInfo();
+ ElementaryTypeNameToken elemToken(m_scanner->currentToken(), firstNum, secondNum);
+ iap.path.push_back(ASTNodeFactory(*this).createNode<ElementaryTypeNameExpression>(elemToken));
+ m_scanner->next();
+ }
+ while (m_scanner->currentToken() == Token::LBrack)
+ {
+ expectToken(Token::LBrack);
+ ASTPointer<Expression> index;
+ if (m_scanner->currentToken() != Token::RBrack)
+ index = parseExpression();
+ SourceLocation indexLocation = iap.path.front()->location();
+ indexLocation.end = endPosition();
+ iap.indices.push_back(make_pair(index, indexLocation));
+ expectToken(Token::RBrack);
+ }
+
+ return iap;
+}
+
+ASTPointer<TypeName> Parser::typeNameFromIndexAccessStructure(Parser::IndexAccessedPath const& _iap)
+{
+ if (_iap.empty())
+ return {};
+
RecursionGuard recursionGuard(*this);
ASTNodeFactory nodeFactory(*this);
- SourceLocation location = _path.front()->location();
- location.end = _path.back()->location().end;
+ SourceLocation location = _iap.path.front()->location();
+ location.end = _iap.path.back()->location().end;
nodeFactory.setLocation(location);
ASTPointer<TypeName> type;
- if (auto typeName = dynamic_cast<ElementaryTypeNameExpression const*>(_path.front().get()))
+ if (auto typeName = dynamic_cast<ElementaryTypeNameExpression const*>(_iap.path.front().get()))
{
- solAssert(_path.size() == 1, "");
+ solAssert(_iap.path.size() == 1, "");
type = nodeFactory.createNode<ElementaryTypeName>(typeName->typeName());
}
else
{
vector<ASTString> path;
- for (auto const& el: _path)
+ for (auto const& el: _iap.path)
path.push_back(dynamic_cast<Identifier const&>(*el).name());
type = nodeFactory.createNode<UserDefinedTypeName>(path);
}
- for (auto const& lengthExpression: _indices)
+ for (auto const& lengthExpression: _iap.indices)
{
nodeFactory.setLocation(lengthExpression.second);
type = nodeFactory.createNode<ArrayTypeName>(type, lengthExpression.first);
@@ -1563,26 +1666,27 @@ ASTPointer<TypeName> Parser::typeNameIndexAccessStructure(
}
ASTPointer<Expression> Parser::expressionFromIndexAccessStructure(
- vector<ASTPointer<PrimaryExpression>> const& _path,
- vector<pair<ASTPointer<Expression>, SourceLocation>> const& _indices
+ Parser::IndexAccessedPath const& _iap
)
{
- solAssert(!_path.empty(), "");
+ if (_iap.empty())
+ return {};
+
RecursionGuard recursionGuard(*this);
- ASTNodeFactory nodeFactory(*this, _path.front());
- ASTPointer<Expression> expression(_path.front());
- for (size_t i = 1; i < _path.size(); ++i)
+ ASTNodeFactory nodeFactory(*this, _iap.path.front());
+ ASTPointer<Expression> expression(_iap.path.front());
+ for (size_t i = 1; i < _iap.path.size(); ++i)
{
- SourceLocation location(_path.front()->location());
- location.end = _path[i]->location().end;
+ SourceLocation location(_iap.path.front()->location());
+ location.end = _iap.path[i]->location().end;
nodeFactory.setLocation(location);
- Identifier const& identifier = dynamic_cast<Identifier const&>(*_path[i]);
+ Identifier const& identifier = dynamic_cast<Identifier const&>(*_iap.path[i]);
expression = nodeFactory.createNode<MemberAccess>(
expression,
make_shared<ASTString>(identifier.name())
);
}
- for (auto const& index: _indices)
+ for (auto const& index: _iap.indices)
{
nodeFactory.setLocation(index.second);
expression = nodeFactory.createNode<IndexAccess>(expression, index.first);
@@ -1598,40 +1702,10 @@ ASTPointer<ParameterList> Parser::createEmptyParameterList()
return nodeFactory.createNode<ParameterList>(vector<ASTPointer<VariableDeclaration>>());
}
-string Parser::currentTokenName()
-{
- Token::Value token = m_scanner->currentToken();
- if (Token::isElementaryTypeName(token)) //for the sake of accuracy in reporting
- {
- ElementaryTypeNameToken elemTypeName = m_scanner->currentElementaryTypeNameToken();
- return elemTypeName.toString();
- }
- else
- return Token::name(token);
-}
-
-Token::Value Parser::expectAssignmentOperator()
-{
- Token::Value op = m_scanner->currentToken();
- if (!Token::isAssignmentOp(op))
- fatalParserError(
- string("Expected assignment operator, got '") +
- currentTokenName() +
- string("'")
- );
- m_scanner->next();
- return op;
-}
-
ASTPointer<ASTString> Parser::expectIdentifierToken()
{
- Token::Value id = m_scanner->currentToken();
- if (id != Token::Identifier)
- fatalParserError(
- string("Expected identifier, got '") +
- currentTokenName() +
- string("'")
- );
+ // do not advance on success
+ expectToken(Token::Identifier, false);
return getLiteralAndAdvance();
}
diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h
index eb120a61..08653364 100644
--- a/libsolidity/parsing/Parser.h
+++ b/libsolidity/parsing/Parser.h
@@ -118,19 +118,19 @@ private:
);
ASTPointer<ExpressionStatement> parseExpressionStatement(
ASTPointer<ASTString> const& _docString,
- ASTPointer<Expression> const& _lookAheadIndexAccessStructure = ASTPointer<Expression>()
+ ASTPointer<Expression> const& _partiallyParsedExpression = ASTPointer<Expression>()
);
ASTPointer<Expression> parseExpression(
- ASTPointer<Expression> const& _lookAheadIndexAccessStructure = ASTPointer<Expression>()
+ ASTPointer<Expression> const& _partiallyParsedExpression = ASTPointer<Expression>()
);
ASTPointer<Expression> parseBinaryExpression(int _minPrecedence = 4,
- ASTPointer<Expression> const& _lookAheadIndexAccessStructure = ASTPointer<Expression>()
+ ASTPointer<Expression> const& _partiallyParsedExpression = ASTPointer<Expression>()
);
ASTPointer<Expression> parseUnaryExpression(
- ASTPointer<Expression> const& _lookAheadIndexAccessStructure = ASTPointer<Expression>()
+ ASTPointer<Expression> const& _partiallyParsedExpression = ASTPointer<Expression>()
);
ASTPointer<Expression> parseLeftHandSideExpression(
- ASTPointer<Expression> const& _lookAheadIndexAccessStructure = ASTPointer<Expression>()
+ ASTPointer<Expression> const& _partiallyParsedExpression = ASTPointer<Expression>()
);
ASTPointer<Expression> parsePrimaryExpression();
std::vector<ASTPointer<Expression>> parseFunctionCallListArguments();
@@ -143,26 +143,32 @@ private:
/// Used as return value of @see peekStatementType.
enum class LookAheadInfo
{
- IndexAccessStructure, VariableDeclarationStatement, ExpressionStatement
+ IndexAccessStructure, VariableDeclaration, Expression
+ };
+ /// Structure that represents a.b.c[x][y][z]. Can be converted either to an expression
+ /// or to a type name. For this to be valid, path cannot be empty, but indices can be empty.
+ struct IndexAccessedPath
+ {
+ std::vector<ASTPointer<PrimaryExpression>> path;
+ std::vector<std::pair<ASTPointer<Expression>, SourceLocation>> indices;
+ bool empty() const;
};
+ std::pair<LookAheadInfo, IndexAccessedPath> tryParseIndexAccessedPath();
/// Performs limited look-ahead to distinguish between variable declaration and expression statement.
/// For source code of the form "a[][8]" ("IndexAccessStructure"), this is not possible to
/// decide with constant look-ahead.
LookAheadInfo peekStatementType() const;
- /// @returns a typename parsed in look-ahead fashion from something like "a.b[8][2**70]".
- ASTPointer<TypeName> typeNameIndexAccessStructure(
- std::vector<ASTPointer<PrimaryExpression>> const& _path,
- std::vector<std::pair<ASTPointer<Expression>, SourceLocation>> const& _indices
- );
- /// @returns an expression parsed in look-ahead fashion from something like "a.b[8][2**70]".
- ASTPointer<Expression> expressionFromIndexAccessStructure(
- std::vector<ASTPointer<PrimaryExpression>> const& _path,
- std::vector<std::pair<ASTPointer<Expression>, SourceLocation>> const& _indices
- );
+ /// @returns an IndexAccessedPath as a prestage to parsing a variable declaration (type name)
+ /// or an expression;
+ IndexAccessedPath parseIndexAccessedPath();
+ /// @returns a typename parsed in look-ahead fashion from something like "a.b[8][2**70]",
+ /// or an empty pointer if an empty @a _pathAndIncides has been supplied.
+ ASTPointer<TypeName> typeNameFromIndexAccessStructure(IndexAccessedPath const& _pathAndIndices);
+ /// @returns an expression parsed in look-ahead fashion from something like "a.b[8][2**70]",
+ /// or an empty pointer if an empty @a _pathAndIncides has been supplied.
+ ASTPointer<Expression> expressionFromIndexAccessStructure(IndexAccessedPath const& _pathAndIndices);
- std::string currentTokenName();
- Token::Value expectAssignmentOperator();
ASTPointer<ASTString> expectIdentifierToken();
ASTPointer<ASTString> getLiteralAndAdvance();
///@}
diff --git a/libsolidity/parsing/ParserBase.cpp b/libsolidity/parsing/ParserBase.cpp
index 5b83c5bd..71133746 100644
--- a/libsolidity/parsing/ParserBase.cpp
+++ b/libsolidity/parsing/ParserBase.cpp
@@ -63,42 +63,32 @@ Token::Value ParserBase::advance()
return m_scanner->next();
}
-void ParserBase::expectToken(Token::Value _value)
+void ParserBase::expectToken(Token::Value _value, bool _advance)
{
Token::Value tok = m_scanner->currentToken();
if (tok != _value)
{
- if (Token::isReservedKeyword(tok))
+ auto tokenName = [this](Token::Value _token)
{
- fatalParserError(
- string("Expected token ") +
- string(Token::name(_value)) +
- string(" got reserved keyword '") +
- string(Token::name(tok)) +
- string("'")
- );
- }
- else if (Token::isElementaryTypeName(tok)) //for the sake of accuracy in reporting
- {
- ElementaryTypeNameToken elemTypeName = m_scanner->currentElementaryTypeNameToken();
- fatalParserError(
- string("Expected token ") +
- string(Token::name(_value)) +
- string(" got '") +
- elemTypeName.toString() +
- string("'")
- );
- }
- else
- fatalParserError(
- string("Expected token ") +
- string(Token::name(_value)) +
- string(" got '") +
- string(Token::name(m_scanner->currentToken())) +
- string("'")
- );
+ if (_token == Token::Identifier)
+ return string("identifier");
+ else if (_token == Token::EOS)
+ return string("end of source");
+ else if (Token::isReservedKeyword(_token))
+ return string("reserved keyword '") + Token::friendlyName(_token) + "'";
+ else if (Token::isElementaryTypeName(_token)) //for the sake of accuracy in reporting
+ {
+ ElementaryTypeNameToken elemTypeName = m_scanner->currentElementaryTypeNameToken();
+ return string("'") + elemTypeName.toString() + "'";
+ }
+ else
+ return string("'") + Token::friendlyName(_token) + "'";
+ };
+
+ fatalParserError(string("Expected ") + tokenName(_value) + string(" but got ") + tokenName(tok));
}
- m_scanner->next();
+ if (_advance)
+ m_scanner->next();
}
void ParserBase::increaseRecursionDepth()
@@ -116,10 +106,10 @@ void ParserBase::decreaseRecursionDepth()
void ParserBase::parserError(string const& _description)
{
- m_errorReporter.parserError(SourceLocation(position(), position(), sourceName()), _description);
+ m_errorReporter.parserError(SourceLocation(position(), endPosition(), sourceName()), _description);
}
void ParserBase::fatalParserError(string const& _description)
{
- m_errorReporter.fatalParserError(SourceLocation(position(), position(), sourceName()), _description);
+ m_errorReporter.fatalParserError(SourceLocation(position(), endPosition(), sourceName()), _description);
}
diff --git a/libsolidity/parsing/ParserBase.h b/libsolidity/parsing/ParserBase.h
index fd0de0d1..b28e1b1b 100644
--- a/libsolidity/parsing/ParserBase.h
+++ b/libsolidity/parsing/ParserBase.h
@@ -63,7 +63,7 @@ protected:
///@{
///@name Helper functions
/// If current token value is not _value, throw exception otherwise advance token.
- void expectToken(Token::Value _value);
+ void expectToken(Token::Value _value, bool _advance = true);
Token::Value currentToken() const;
Token::Value peekNextToken() const;
std::string currentLiteral() const;
diff --git a/libsolidity/parsing/Token.h b/libsolidity/parsing/Token.h
index 805fbf5d..4d7a7bc6 100644
--- a/libsolidity/parsing/Token.h
+++ b/libsolidity/parsing/Token.h
@@ -304,6 +304,17 @@ public:
return m_string[tok];
}
+ static std::string friendlyName(Value tok)
+ {
+ char const* ret = toString(tok);
+ if (ret == nullptr)
+ {
+ ret = name(tok);
+ solAssert(ret != nullptr, "");
+ }
+ return std::string(ret);
+ }
+
// @returns the precedence > 0 for binary and compare
// operators; returns 0 otherwise.
static int precedence(Value tok)