diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 9601389c7..dece4fa14 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1099,13 +1099,15 @@ ASTPointer Parser::parseStatement() } statement = nodeFactory.createNode(docString, expression); break; - } + } case Token::Throw: - { - statement = ASTNodeFactory(*this).createNode(docString); - m_scanner->next(); - break; - } + { + statement = ASTNodeFactory(*this).createNode(docString); + m_scanner->next(); + break; + } + case Token::Try: + return parseTryStatement(docString); case Token::Assembly: return parseInlineAssembly(docString); case Token::Emit: @@ -1187,6 +1189,62 @@ ASTPointer Parser::parseIfStatement(ASTPointer const& _d return nodeFactory.createNode(_docString, condition, trueBody, falseBody); } +ASTPointer Parser::parseTryStatement(ASTPointer const& _docString) +{ + RecursionGuard recursionGuard(*this); + ASTNodeFactory nodeFactory(*this); + expectToken(Token::Try); + ASTPointer externalCall = parseExpression(); + vector> clauses; + + ASTNodeFactory successClauseFactory(*this); + ASTPointer returnsParameters; + if (m_scanner->currentToken() == Token::Returns) + { + m_scanner->next(); + VarDeclParserOptions options; + options.allowEmptyName = true; + options.allowLocationSpecifier = true; + returnsParameters = parseParameterList(options, false); + } + ASTPointer successBlock = parseBlock(); + successClauseFactory.setEndPositionFromNode(successBlock); + clauses.emplace_back(successClauseFactory.createNode( + make_shared(), returnsParameters, successBlock + )); + + do + { + clauses.emplace_back(parseCatchClause()); + } + while (m_scanner->currentToken() == Token::Catch); + nodeFactory.setEndPositionFromNode(clauses.back()); + return nodeFactory.createNode( + _docString, externalCall, clauses + ); +} + +ASTPointer Parser::parseCatchClause() +{ + RecursionGuard recursionGuard(*this); + ASTNodeFactory nodeFactory(*this); + expectToken(Token::Catch); + ASTPointer errorName = make_shared(); + ASTPointer errorParameters; + if (m_scanner->currentToken() != Token::LBrace) + { + if (m_scanner->currentToken() == Token::Identifier) + errorName = expectIdentifierToken(); + VarDeclParserOptions options; + options.allowEmptyName = true; + options.allowLocationSpecifier = true; + errorParameters = parseParameterList(options, !errorName->empty()); + } + ASTPointer block = parseBlock(); + nodeFactory.setEndPositionFromNode(block); + return nodeFactory.createNode(errorName, errorParameters, block); +} + ASTPointer Parser::parseWhileStatement(ASTPointer const& _docString) { RecursionGuard recursionGuard(*this); diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h index 479306fb0..bd288d34c 100644 --- a/libsolidity/parsing/Parser.h +++ b/libsolidity/parsing/Parser.h @@ -119,6 +119,8 @@ private: ASTPointer parseStatement(); ASTPointer parseInlineAssembly(ASTPointer const& _docString = {}); ASTPointer parseIfStatement(ASTPointer const& _docString); + ASTPointer parseTryStatement(ASTPointer const& _docString); + ASTPointer parseCatchClause(); ASTPointer parseWhileStatement(ASTPointer const& _docString); ASTPointer parseDoWhileStatement(ASTPointer const& _docString); ASTPointer parseForStatement(ASTPointer const& _docString);