aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AST.cpp22
-rw-r--r--AST.h2
-rw-r--r--AST_accept.h6
-rw-r--r--ExpressionCompiler.cpp3
-rw-r--r--Parser.cpp11
-rw-r--r--grammar.txt5
6 files changed, 36 insertions, 13 deletions
diff --git a/AST.cpp b/AST.cpp
index 4e4fe7d5..17946115 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -614,6 +614,8 @@ void IndexAccess::checkTypeRequirements()
case Type::Category::Array:
{
ArrayType const& type = dynamic_cast<ArrayType const&>(*m_base->getType());
+ if (!m_index)
+ BOOST_THROW_EXCEPTION(createTypeError("Index expression cannot be omitted."));
m_index->expectType(IntegerType(256));
m_type = type.getBaseType();
m_isLValue = true;
@@ -622,14 +624,32 @@ void IndexAccess::checkTypeRequirements()
case Type::Category::Mapping:
{
MappingType const& type = dynamic_cast<MappingType const&>(*m_base->getType());
+ if (!m_index)
+ BOOST_THROW_EXCEPTION(createTypeError("Index expression cannot be omitted."));
m_index->expectType(*type.getKeyType());
m_type = type.getValueType();
m_isLValue = true;
break;
}
+ case Type::Category::TypeType:
+ {
+ TypeType const& type = dynamic_cast<TypeType const&>(*m_base->getType());
+ if (!m_index)
+ m_type = make_shared<TypeType>(make_shared<ArrayType>(ArrayType::Location::Memory, type.getActualType()));
+ else
+ {
+ m_index->checkTypeRequirements();
+ auto length = dynamic_cast<IntegerConstantType const*>(m_index->getType().get());
+ if (!length)
+ BOOST_THROW_EXCEPTION(m_index->createTypeError("Integer constant expected."));
+ m_type = make_shared<TypeType>(make_shared<ArrayType>(
+ ArrayType::Location::Memory, type.getActualType(), length->literalValue(nullptr)));
+ }
+ break;
+ }
default:
BOOST_THROW_EXCEPTION(m_base->createTypeError(
- "Indexed expression has to be a mapping or array (is " + m_base->getType()->toString() + ")"));
+ "Indexed expression has to be a type, mapping or array (is " + m_base->getType()->toString() + ")"));
}
}
diff --git a/AST.h b/AST.h
index 594f8f4b..07b405c4 100644
--- a/AST.h
+++ b/AST.h
@@ -1102,7 +1102,7 @@ public:
virtual void checkTypeRequirements() override;
Expression const& getBaseExpression() const { return *m_base; }
- Expression const& getIndexExpression() const { return *m_index; }
+ Expression const* getIndexExpression() const { return m_index.get(); }
private:
ASTPointer<Expression> m_base;
diff --git a/AST_accept.h b/AST_accept.h
index 61b8280d..81ede8fc 100644
--- a/AST_accept.h
+++ b/AST_accept.h
@@ -626,7 +626,8 @@ void IndexAccess::accept(ASTVisitor& _visitor)
if (_visitor.visit(*this))
{
m_base->accept(_visitor);
- m_index->accept(_visitor);
+ if (m_index)
+ m_index->accept(_visitor);
}
_visitor.endVisit(*this);
}
@@ -636,7 +637,8 @@ void IndexAccess::accept(ASTConstVisitor& _visitor) const
if (_visitor.visit(*this))
{
m_base->accept(_visitor);
- m_index->accept(_visitor);
+ if (m_index)
+ m_index->accept(_visitor);
}
_visitor.endVisit(*this);
}
diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp
index cdad4840..94f65b93 100644
--- a/ExpressionCompiler.cpp
+++ b/ExpressionCompiler.cpp
@@ -562,7 +562,8 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
solAssert(baseType.getCategory() == Type::Category::Mapping, "");
Type const& keyType = *dynamic_cast<MappingType const&>(baseType).getKeyType();
m_context << u256(0);
- appendExpressionCopyToMemory(keyType, _indexAccess.getIndexExpression());
+ solAssert(_indexAccess.getIndexExpression(), "Index expression expected.");
+ appendExpressionCopyToMemory(keyType, *_indexAccess.getIndexExpression());
solAssert(baseType.getSizeOnStack() == 1,
"Unexpected: Not exactly one stack slot taken by subscriptable expression.");
m_context << eth::Instruction::SWAP1;
diff --git a/Parser.cpp b/Parser.cpp
index 97506179..def8b9ac 100644
--- a/Parser.cpp
+++ b/Parser.cpp
@@ -645,14 +645,11 @@ ASTPointer<Statement> Parser::parseSimpleStatement()
vector<pair<ASTPointer<Expression>, Location>> indices;
solAssert(m_scanner->getCurrentToken() == Token::LBrack, "");
Location indexLocation = primary->getLocation();
- bool encounteredEmptyBrackets = false;
do
{
expectToken(Token::LBrack);
ASTPointer<Expression> index;
- if (m_scanner->getCurrentToken() == Token::RBrack)
- encounteredEmptyBrackets = true;
- else
+ if (m_scanner->getCurrentToken() != Token::RBrack)
index = parseExpression();
indexLocation.end = getEndPosition();
indices.push_back(make_pair(index, indexLocation));
@@ -660,7 +657,7 @@ ASTPointer<Statement> Parser::parseSimpleStatement()
}
while (m_scanner->getCurrentToken() == Token::LBrack);
- if (m_scanner->getCurrentToken() == Token::Identifier || encounteredEmptyBrackets)
+ if (m_scanner->getCurrentToken() == Token::Identifier)
return parseVariableDeclarationStatement(typeNameFromArrayIndexStructure(primary, indices));
else
return parseExpressionStatement(expressionFromArrayIndexStructure(primary, indices));
@@ -768,7 +765,9 @@ ASTPointer<Expression> Parser::parseLeftHandSideExpression(
case Token::LBrack:
{
m_scanner->next();
- ASTPointer<Expression> index = parseExpression();
+ ASTPointer<Expression> index;
+ if (m_scanner->getCurrentToken() != Token::RBrack)
+ index = parseExpression();
nodeFactory.markEndPosition();
expectToken(Token::RBrack);
expression = nodeFactory.createNode<IndexAccess>(expression, index);
diff --git a/grammar.txt b/grammar.txt
index a3b24687..6503516c 100644
--- a/grammar.txt
+++ b/grammar.txt
@@ -18,8 +18,9 @@ ParameterList = '(' ( VariableDeclaration (',' VariableDeclaration)* )? ')'
// semantic restriction: mappings and structs (recursively) containing mappings
// are not allowed in argument lists
VariableDeclaration = TypeName Identifier
-TypeName = ElementaryTypeName | Identifier | Mapping
+TypeName = ElementaryTypeName | Identifier | Mapping | ArrayTypeName
Mapping = 'mapping' '(' ElementaryTypeName '=>' TypeName ')'
+ArrayTypeName = TypeName '[' (Expression)? ']'
Block = '{' Statement* '}'
Statement = IfStatement | WhileStatement | Block |
@@ -42,5 +43,5 @@ Assignment = Expression (AssignmentOp Expression)
FunctionCall = Expression '(' Expression ( ',' Expression )* ')'
NewExpression = 'new' Identifier
MemberAccess = Expression '.' Identifier
-IndexAccess = Expression '[' Expresison ']'
+IndexAccess = Expression '[' (Expresison)? ']'
PrimaryExpression = Identifier | NumberLiteral | StringLiteral | ElementaryTypeName | '(' Expression ')'