@@ -734,6 +734,9 @@ ASTPointer<Statement> Parser::parseSimpleStatement()
734
734
// These two cases are very hard to distinguish:
735
735
// x[7 * 20 + 3] a; - x[7 * 20 + 3] = 9;
736
736
// 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.
737
740
switch (peekStatementType ())
738
741
{
739
742
case LookAheadInfo::VariableDeclarationStatement:
@@ -744,36 +747,43 @@ ASTPointer<Statement> Parser::parseSimpleStatement()
744
747
break ;
745
748
}
746
749
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 ;
751
757
if (m_scanner->currentToken () == Token::Identifier)
752
- primary = parseIdentifier ();
758
+ path. push_back ( parseIdentifier () );
753
759
else
754
760
{
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
+ {
756
767
m_scanner->next ();
768
+ path.push_back (parseIdentifier ());
757
769
}
758
770
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)
762
772
{
763
773
expectToken (Token::LBrack);
764
774
ASTPointer<Expression> index;
765
775
if (m_scanner->currentToken () != Token::RBrack)
766
776
index = parseExpression ();
777
+ SourceLocation indexLocation = path.front ()->location ();
767
778
indexLocation.end = endPosition ();
768
779
indices.push_back (make_pair (index, indexLocation));
769
780
expectToken (Token::RBrack);
770
781
}
771
- while (m_scanner->currentToken () == Token::LBrack);
772
782
773
783
if (m_scanner->currentToken () == Token::Identifier || Token::isLocationSpecifier (m_scanner->currentToken ()))
774
- return parseVariableDeclarationStatement (typeNameIndexAccessStructure (primary , indices));
784
+ return parseVariableDeclarationStatement (typeNameIndexAccessStructure (path , indices));
775
785
else
776
- return parseExpressionStatement (expressionFromIndexAccessStructure (primary , indices));
786
+ return parseExpressionStatement (expressionFromIndexAccessStructure (path , indices));
777
787
}
778
788
779
789
ASTPointer<VariableDeclarationStatement> Parser::parseVariableDeclarationStatement (
@@ -1090,7 +1100,7 @@ Parser::LookAheadInfo Parser::peekStatementType() const
1090
1100
// We have a variable declaration if we get a keyword that specifies a type name.
1091
1101
// If it is an identifier or an elementary type name followed by an identifier, we also have
1092
1102
// 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;").
1094
1104
// In all other cases, we have an expression statement.
1095
1105
Token::Value token (m_scanner->currentToken ());
1096
1106
bool mightBeTypeName = (Token::isElementaryTypeName (token) || token == Token::Identifier);
@@ -1102,25 +1112,36 @@ Parser::LookAheadInfo Parser::peekStatementType() const
1102
1112
Token::Value next = m_scanner->peekNextToken ();
1103
1113
if (next == Token::Identifier || Token::isLocationSpecifier (next))
1104
1114
return LookAheadInfo::VariableDeclarationStatement;
1105
- if (m_scanner-> peekNextToken () == Token::LBrack)
1115
+ if (next == Token::LBrack || next == Token::Period )
1106
1116
return LookAheadInfo::IndexAccessStructure;
1107
1117
}
1108
1118
return LookAheadInfo::ExpressionStatement;
1109
1119
}
1110
1120
1111
1121
ASTPointer<TypeName> Parser::typeNameIndexAccessStructure (
1112
- ASTPointer<PrimaryExpression> const & _primary ,
1122
+ vector< ASTPointer<PrimaryExpression>> const & _path ,
1113
1123
vector<pair<ASTPointer<Expression>, SourceLocation>> const & _indices
1114
1124
)
1115
1125
{
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
+
1117
1132
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 , " " );
1121
1136
type = nodeFactory.createNode <ElementaryTypeName>(typeName->typeToken ());
1137
+ }
1122
1138
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
+ }
1124
1145
for (auto const & lengthExpression: _indices)
1125
1146
{
1126
1147
nodeFactory.setLocation (lengthExpression.second );
@@ -1130,12 +1151,24 @@ ASTPointer<TypeName> Parser::typeNameIndexAccessStructure(
1130
1151
}
1131
1152
1132
1153
ASTPointer<Expression> Parser::expressionFromIndexAccessStructure (
1133
- ASTPointer<PrimaryExpression> const & _primary ,
1154
+ vector< ASTPointer<PrimaryExpression>> const & _path ,
1134
1155
vector<pair<ASTPointer<Expression>, SourceLocation>> const & _indices
1135
1156
)
1136
1157
{
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
+ }
1139
1172
for (auto const & index: _indices)
1140
1173
{
1141
1174
nodeFactory.setLocation (index.second );
0 commit comments