@@ -734,6 +734,9 @@ ASTPointer<Statement> Parser::parseSimpleStatement()
734734 // These two cases are very hard to distinguish:
735735 // x[7 * 20 + 3] a; - x[7 * 20 + 3] = 9;
736736 // In the first case, x is a type name, in the second it is the name of a variable.
737+ // As an extension, we can even have:
738+ // `x.y.z[1][2] a;` and `x.y.z[1][2] = 10;`
739+ // Where in the first, x.y.z leads to a type name where in the second, it accesses structs.
737740 switch (peekStatementType ())
738741 {
739742 case LookAheadInfo::VariableDeclarationStatement:
@@ -744,36 +747,43 @@ ASTPointer<Statement> Parser::parseSimpleStatement()
744747 break ;
745748 }
746749
747- // At this point, we have '(Identifier|ElementaryTypeName) "["'.
748- // We parse '(Identifier|ElementaryTypeName) ( "[" Expression "]" )+' and then decide whether to hand this over
749- // to ExpressionStatement or create a VariableDeclarationStatement out of it.
750- ASTPointer<PrimaryExpression> primary;
750+ // At this point, we have 'Identifier "["' or 'Identifier "." Identifier' or 'ElementoryTypeName "["'.
751+ // We parse '(Identifier ("." Identifier)* |ElementaryTypeName) ( "[" Expression "]" )+'
752+ // until we can decide whether to hand this over to ExpressionStatement or create a
753+ // VariableDeclarationStatement out of it.
754+
755+ vector<ASTPointer<PrimaryExpression>> path;
756+ bool startedWithElementary = false ;
751757 if (m_scanner->currentToken () == Token::Identifier)
752- primary = parseIdentifier ();
758+ path. push_back ( parseIdentifier () );
753759 else
754760 {
755- primary = ASTNodeFactory (*this ).createNode <ElementaryTypeNameExpression>(m_scanner->currentToken ());
761+ startedWithElementary = true ;
762+ path.push_back (ASTNodeFactory (*this ).createNode <ElementaryTypeNameExpression>(m_scanner->currentToken ()));
763+ m_scanner->next ();
764+ }
765+ while (!startedWithElementary && m_scanner->currentToken () == Token::Period)
766+ {
756767 m_scanner->next ();
768+ path.push_back (parseIdentifier ());
757769 }
758770 vector<pair<ASTPointer<Expression>, SourceLocation>> indices;
759- solAssert (m_scanner->currentToken () == Token::LBrack, " " );
760- SourceLocation indexLocation = primary->location ();
761- do
771+ while (m_scanner->currentToken () == Token::LBrack)
762772 {
763773 expectToken (Token::LBrack);
764774 ASTPointer<Expression> index;
765775 if (m_scanner->currentToken () != Token::RBrack)
766776 index = parseExpression ();
777+ SourceLocation indexLocation = path.front ()->location ();
767778 indexLocation.end = endPosition ();
768779 indices.push_back (make_pair (index, indexLocation));
769780 expectToken (Token::RBrack);
770781 }
771- while (m_scanner->currentToken () == Token::LBrack);
772782
773783 if (m_scanner->currentToken () == Token::Identifier || Token::isLocationSpecifier (m_scanner->currentToken ()))
774- return parseVariableDeclarationStatement (typeNameIndexAccessStructure (primary , indices));
784+ return parseVariableDeclarationStatement (typeNameIndexAccessStructure (path , indices));
775785 else
776- return parseExpressionStatement (expressionFromIndexAccessStructure (primary , indices));
786+ return parseExpressionStatement (expressionFromIndexAccessStructure (path , indices));
777787}
778788
779789ASTPointer<VariableDeclarationStatement> Parser::parseVariableDeclarationStatement (
@@ -1090,7 +1100,7 @@ Parser::LookAheadInfo Parser::peekStatementType() const
10901100 // We have a variable declaration if we get a keyword that specifies a type name.
10911101 // If it is an identifier or an elementary type name followed by an identifier, we also have
10921102 // a variable declaration.
1093- // If we get an identifier followed by a "[", it can be both ("type[9] a;" or "arr [9] = 7;").
1103+ // If we get an identifier followed by a "[" or "." , it can be both ("lib. type[9] a;" or "variable.el [9] = 7;").
10941104 // In all other cases, we have an expression statement.
10951105 Token::Value token (m_scanner->currentToken ());
10961106 bool mightBeTypeName = (Token::isElementaryTypeName (token) || token == Token::Identifier);
@@ -1102,25 +1112,36 @@ Parser::LookAheadInfo Parser::peekStatementType() const
11021112 Token::Value next = m_scanner->peekNextToken ();
11031113 if (next == Token::Identifier || Token::isLocationSpecifier (next))
11041114 return LookAheadInfo::VariableDeclarationStatement;
1105- if (m_scanner-> peekNextToken () == Token::LBrack)
1115+ if (next == Token::LBrack || next == Token::Period )
11061116 return LookAheadInfo::IndexAccessStructure;
11071117 }
11081118 return LookAheadInfo::ExpressionStatement;
11091119}
11101120
11111121ASTPointer<TypeName> Parser::typeNameIndexAccessStructure (
1112- ASTPointer<PrimaryExpression> const & _primary ,
1122+ vector< ASTPointer<PrimaryExpression>> const & _path ,
11131123 vector<pair<ASTPointer<Expression>, SourceLocation>> const & _indices
11141124)
11151125{
1116- ASTNodeFactory nodeFactory (*this , _primary);
1126+ solAssert (!_path.empty (), " " );
1127+ ASTNodeFactory nodeFactory (*this );
1128+ SourceLocation location = _path.front ()->location ();
1129+ location.end = _path.back ()->location ().end ;
1130+ nodeFactory.setLocation (location);
1131+
11171132 ASTPointer<TypeName> type;
1118- if (auto identifier = dynamic_cast <Identifier const *>(_primary .get ()))
1119- type = nodeFactory. createNode <UserDefinedTypeName>(vector<ASTString>{identifier-> name ()});
1120- else if ( auto typeName = dynamic_cast <ElementaryTypeNameExpression const *>(_primary. get ()))
1133+ if (auto typeName = dynamic_cast <ElementaryTypeNameExpression const *>(_path. front () .get ()))
1134+ {
1135+ solAssert (_path. size () == 1 , " " );
11211136 type = nodeFactory.createNode <ElementaryTypeName>(typeName->typeToken ());
1137+ }
11221138 else
1123- solAssert (false , " Invalid type name for array look-ahead." );
1139+ {
1140+ vector<ASTString> path;
1141+ for (auto const & el: _path)
1142+ path.push_back (dynamic_cast <Identifier const &>(*el).name ());
1143+ type = nodeFactory.createNode <UserDefinedTypeName>(path);
1144+ }
11241145 for (auto const & lengthExpression: _indices)
11251146 {
11261147 nodeFactory.setLocation (lengthExpression.second );
@@ -1130,12 +1151,24 @@ ASTPointer<TypeName> Parser::typeNameIndexAccessStructure(
11301151}
11311152
11321153ASTPointer<Expression> Parser::expressionFromIndexAccessStructure (
1133- ASTPointer<PrimaryExpression> const & _primary ,
1154+ vector< ASTPointer<PrimaryExpression>> const & _path ,
11341155 vector<pair<ASTPointer<Expression>, SourceLocation>> const & _indices
11351156)
11361157{
1137- ASTNodeFactory nodeFactory (*this , _primary);
1138- ASTPointer<Expression> expression (_primary);
1158+ solAssert (!_path.empty (), " " );
1159+ ASTNodeFactory nodeFactory (*this , _path.front ());
1160+ ASTPointer<Expression> expression (_path.front ());
1161+ for (size_t i = 1 ; i < _path.size (); ++i)
1162+ {
1163+ SourceLocation location (_path.front ()->location ());
1164+ location.end = _path[i]->location ().end ;
1165+ nodeFactory.setLocation (location);
1166+ Identifier const & identifier = dynamic_cast <Identifier const &>(*_path[i]);
1167+ expression = nodeFactory.createNode <MemberAccess>(
1168+ expression,
1169+ make_shared<ASTString>(identifier.name ())
1170+ );
1171+ }
11391172 for (auto const & index: _indices)
11401173 {
11411174 nodeFactory.setLocation (index.second );
0 commit comments