mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #4047 from ethereum/refactorToMulti
Refactor to allow implementing multi variable declarations.
This commit is contained in:
		
						commit
						868d449c38
					
				| @ -1083,18 +1083,46 @@ ASTPointer<EmitStatement> Parser::parseEmitStatement(ASTPointer<ASTString> const | ||||
| ASTPointer<Statement> Parser::parseSimpleStatement(ASTPointer<ASTString> const& _docString) | ||||
| { | ||||
| 	RecursionGuard recursionGuard(*this); | ||||
| 	LookAheadInfo statementType; | ||||
| 	IndexAccessedPath iap; | ||||
| 
 | ||||
| 	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; | ||||
| 	} | ||||
| @ -1106,9 +1134,9 @@ ASTPointer<Statement> Parser::parseSimpleStatement(ASTPointer<ASTString> const& | ||||
| 	IndexAccessedPath iap = parseIndexAccessedPath(); | ||||
| 
 | ||||
| 	if (m_scanner->currentToken() == Token::Identifier || Token::isLocationSpecifier(m_scanner->currentToken())) | ||||
| 		return parseVariableDeclarationStatement(_docString, typeNameFromIndexAccessStructure(iap)); | ||||
| 		return make_pair(LookAheadInfo::VariableDeclaration, move(iap)); | ||||
| 	else | ||||
| 		return parseExpressionStatement(_docString, expressionFromIndexAccessStructure(iap)); | ||||
| 		return make_pair(LookAheadInfo::Expression, move(iap)); | ||||
| } | ||||
| 
 | ||||
| ASTPointer<VariableDeclarationStatement> Parser::parseVariableDeclarationStatement( | ||||
| @ -1178,20 +1206,20 @@ 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 = m_scanner->currentToken(); | ||||
| @ -1217,11 +1245,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) | ||||
| @ -1237,14 +1265,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(); | ||||
| @ -1255,7 +1283,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; | ||||
| @ -1266,16 +1294,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); | ||||
| @ -1489,16 +1517,16 @@ 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; | ||||
| } | ||||
| 
 | ||||
| Parser::IndexAccessedPath Parser::parseIndexAccessedPath() | ||||
| @ -1539,7 +1567,9 @@ Parser::IndexAccessedPath Parser::parseIndexAccessedPath() | ||||
| 
 | ||||
| ASTPointer<TypeName> Parser::typeNameFromIndexAccessStructure(Parser::IndexAccessedPath const& _iap) | ||||
| { | ||||
| 	solAssert(!_iap.path.empty(), ""); | ||||
| 	if (_iap.empty()) | ||||
| 		return {}; | ||||
| 
 | ||||
| 	RecursionGuard recursionGuard(*this); | ||||
| 	ASTNodeFactory nodeFactory(*this); | ||||
| 	SourceLocation location = _iap.path.front()->location(); | ||||
| @ -1571,7 +1601,9 @@ ASTPointer<Expression> Parser::expressionFromIndexAccessStructure( | ||||
| 	Parser::IndexAccessedPath const& _iap | ||||
| ) | ||||
| { | ||||
| 	solAssert(!_iap.path.empty(), ""); | ||||
| 	if (_iap.empty()) | ||||
| 		return {}; | ||||
| 
 | ||||
| 	RecursionGuard recursionGuard(*this); | ||||
| 	ASTNodeFactory nodeFactory(*this, _iap.path.front()); | ||||
| 	ASTPointer<Expression> expression(_iap.path.front()); | ||||
|  | ||||
| @ -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,16 +143,18 @@ 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. Path cannot be empty, but indices can be empty.
 | ||||
| 	/// 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.
 | ||||
| @ -160,9 +162,11 @@ private: | ||||
| 	/// @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]".
 | ||||
| 	/// @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]".
 | ||||
| 	/// @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); | ||||
| 
 | ||||
| 	ASTPointer<ASTString> expectIdentifierToken(); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user