Coverage Report

Created: 2026-07-13 07:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/solidity/libsolidity/parsing/Parser.cpp
Line
Count
Source
1
/*
2
  This file is part of solidity.
3
4
  solidity is free software: you can redistribute it and/or modify
5
  it under the terms of the GNU General Public License as published by
6
  the Free Software Foundation, either version 3 of the License, or
7
  (at your option) any later version.
8
9
  solidity is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
14
  You should have received a copy of the GNU General Public License
15
  along with solidity.  If not, see <http://www.gnu.org/licenses/>.
16
*/
17
// SPDX-License-Identifier: GPL-3.0
18
/**
19
 * @author Christian <c@ethdev.com>
20
 * @date 2014
21
 * Solidity parser.
22
 */
23
24
#include <libsolidity/parsing/Parser.h>
25
26
#include <libsolidity/ast/UserDefinableOperators.h>
27
#include <libsolidity/interface/Version.h>
28
#include <libyul/AST.h>
29
#include <libyul/AsmParser.h>
30
#include <libyul/backends/evm/EVMDialect.h>
31
#include <liblangutil/ErrorReporter.h>
32
#include <liblangutil/Scanner.h>
33
#include <liblangutil/SemVerHandler.h>
34
#include <liblangutil/SourceLocation.h>
35
#include <libyul/backends/evm/EVMDialect.h>
36
#include <boost/algorithm/string/trim.hpp>
37
#include <boost/algorithm/string/replace.hpp>
38
#include <boost/algorithm/string/predicate.hpp>
39
40
#include <cctype>
41
#include <memory>
42
#include <regex>
43
#include <tuple>
44
#include <vector>
45
46
using namespace solidity::langutil;
47
using namespace std::string_literals;
48
49
namespace solidity::frontend
50
{
51
52
/// AST node factory that also tracks the begin and end position of an AST node
53
/// while it is being parsed
54
class Parser::ASTNodeFactory
55
{
56
public:
57
  explicit ASTNodeFactory(Parser& _parser):
58
2.62M
    m_parser(_parser), m_location{
59
2.62M
      _parser.currentLocation().start,
60
2.62M
      -1,
61
2.62M
      _parser.currentLocation().sourceName
62
2.62M
    }
63
2.62M
  {}
64
  ASTNodeFactory(Parser& _parser, ASTPointer<ASTNode> const& _childNode):
65
697k
    m_parser(_parser), m_location{_childNode->location()} {}
66
67
1.29M
  void markEndPosition() { m_location.end = m_parser.currentLocation().end; }
68
82.7k
  void setLocation(SourceLocation const& _location) { m_location = _location; }
69
23.0k
  void setLocationEmpty() { m_location.end = m_location.start; }
70
  /// Set the end position to the one of the given node.
71
464k
  void setEndPositionFromNode(ASTPointer<ASTNode> const& _node) { m_location.end = _node->location().end; }
72
73
  template <class NodeType, typename... Args>
74
  ASTPointer<NodeType> createNode(Args&& ... _args)
75
1.78M
  {
76
1.78M
    solAssert(m_location.sourceName, "");
77
1.78M
    if (m_location.end < 0)
78
46.7k
      markEndPosition();
79
1.78M
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
1.78M
  }
std::__1::shared_ptr<solidity::frontend::SourceUnit> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::SourceUnit, std::__1::optional<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::vector<std::__1::shared_ptr<solidity::frontend::ASTNode>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::ASTNode> > >&, bool&>(std::__1::optional<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&&, std::__1::vector<std::__1::shared_ptr<solidity::frontend::ASTNode>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::ASTNode> > >&, bool&)
Line
Count
Source
75
27.9k
  {
76
27.9k
    solAssert(m_location.sourceName, "");
77
27.9k
    if (m_location.end < 0)
78
27.9k
      markEndPosition();
79
27.9k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
27.9k
  }
std::__1::shared_ptr<solidity::frontend::StructuredDocumentation> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::StructuredDocumentation, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&&)
Line
Count
Source
75
2.37k
  {
76
2.37k
    solAssert(m_location.sourceName, "");
77
2.37k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
2.37k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
2.37k
  }
std::__1::shared_ptr<solidity::frontend::PragmaDirective> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::PragmaDirective, std::__1::vector<solidity::langutil::Token, std::__1::allocator<solidity::langutil::Token> >&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&>(std::__1::vector<solidity::langutil::Token, std::__1::allocator<solidity::langutil::Token> >&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&)
Line
Count
Source
75
33.2k
  {
76
33.2k
    solAssert(m_location.sourceName, "");
77
33.2k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
33.2k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
33.2k
  }
std::__1::shared_ptr<solidity::frontend::ImportDirective> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::ImportDirective, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation&, std::__1::vector<solidity::frontend::ImportDirective::SymbolAlias, std::__1::allocator<solidity::frontend::ImportDirective::SymbolAlias> > >(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation&, std::__1::vector<solidity::frontend::ImportDirective::SymbolAlias, std::__1::allocator<solidity::frontend::ImportDirective::SymbolAlias> >&&)
Line
Count
Source
75
1.76k
  {
76
1.76k
    solAssert(m_location.sourceName, "");
77
1.76k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
1.76k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
1.76k
  }
std::__1::shared_ptr<solidity::frontend::StorageLayoutSpecifier> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::StorageLayoutSpecifier, std::__1::shared_ptr<solidity::frontend::Expression>&>(std::__1::shared_ptr<solidity::frontend::Expression>&)
Line
Count
Source
75
55
  {
76
55
    solAssert(m_location.sourceName, "");
77
55
    if (m_location.end < 0)
78
0
      markEndPosition();
79
55
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
55
  }
std::__1::shared_ptr<solidity::frontend::ContractDefinition> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::ContractDefinition, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation&, std::__1::shared_ptr<solidity::frontend::StructuredDocumentation>&, std::__1::vector<std::__1::shared_ptr<solidity::frontend::InheritanceSpecifier>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::InheritanceSpecifier> > >&, std::__1::vector<std::__1::shared_ptr<solidity::frontend::ASTNode>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::ASTNode> > >&, solidity::frontend::ContractKind&, bool&, std::__1::shared_ptr<solidity::frontend::StorageLayoutSpecifier>&>(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation&, std::__1::shared_ptr<solidity::frontend::StructuredDocumentation>&, std::__1::vector<std::__1::shared_ptr<solidity::frontend::InheritanceSpecifier>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::InheritanceSpecifier> > >&, std::__1::vector<std::__1::shared_ptr<solidity::frontend::ASTNode>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::ASTNode> > >&, solidity::frontend::ContractKind&, bool&, std::__1::shared_ptr<solidity::frontend::StorageLayoutSpecifier>&)
Line
Count
Source
75
27.9k
  {
76
27.9k
    solAssert(m_location.sourceName, "");
77
27.9k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
27.9k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
27.9k
  }
std::__1::shared_ptr<solidity::frontend::InheritanceSpecifier> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::InheritanceSpecifier, std::__1::shared_ptr<solidity::frontend::IdentifierPath>&, std::__1::unique_ptr<std::__1::vector<std::__1::shared_ptr<solidity::frontend::Expression>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::Expression> > >, std::__1::default_delete<std::__1::vector<std::__1::shared_ptr<solidity::frontend::Expression>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::Expression> > > > > >(std::__1::shared_ptr<solidity::frontend::IdentifierPath>&, std::__1::unique_ptr<std::__1::vector<std::__1::shared_ptr<solidity::frontend::Expression>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::Expression> > >, std::__1::default_delete<std::__1::vector<std::__1::shared_ptr<solidity::frontend::Expression>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::Expression> > > > >&&)
Line
Count
Source
75
5.37k
  {
76
5.37k
    solAssert(m_location.sourceName, "");
77
5.37k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
5.37k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
5.37k
  }
std::__1::shared_ptr<solidity::frontend::OverrideSpecifier> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::OverrideSpecifier, std::__1::vector<std::__1::shared_ptr<solidity::frontend::IdentifierPath>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::IdentifierPath> > > >(std::__1::vector<std::__1::shared_ptr<solidity::frontend::IdentifierPath>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::IdentifierPath> > >&&)
Line
Count
Source
75
1.17k
  {
76
1.17k
    solAssert(m_location.sourceName, "");
77
1.17k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
1.17k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
1.17k
  }
std::__1::shared_ptr<solidity::frontend::ForAllQuantifier> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::ForAllQuantifier, std::__1::shared_ptr<solidity::frontend::ParameterList>, std::__1::shared_ptr<solidity::frontend::FunctionDefinition> >(std::__1::shared_ptr<solidity::frontend::ParameterList>&&, std::__1::shared_ptr<solidity::frontend::FunctionDefinition>&&)
Line
Count
Source
75
14
  {
76
14
    solAssert(m_location.sourceName, "");
77
14
    if (m_location.end < 0)
78
0
      markEndPosition();
79
14
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
14
  }
std::__1::shared_ptr<solidity::frontend::FunctionDefinition> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::FunctionDefinition, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation&, solidity::frontend::Visibility&, solidity::frontend::StateMutability&, bool&, solidity::langutil::Token&, bool&, std::__1::shared_ptr<solidity::frontend::OverrideSpecifier>&, std::__1::shared_ptr<solidity::frontend::StructuredDocumentation>&, std::__1::shared_ptr<solidity::frontend::ParameterList>&, std::__1::vector<std::__1::shared_ptr<solidity::frontend::ModifierInvocation>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::ModifierInvocation> > >&, std::__1::shared_ptr<solidity::frontend::ParameterList>&, std::__1::shared_ptr<solidity::frontend::Block>&, std::__1::shared_ptr<solidity::frontend::Expression>&>(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation&, solidity::frontend::Visibility&, solidity::frontend::StateMutability&, bool&, solidity::langutil::Token&, bool&, std::__1::shared_ptr<solidity::frontend::OverrideSpecifier>&, std::__1::shared_ptr<solidity::frontend::StructuredDocumentation>&, std::__1::shared_ptr<solidity::frontend::ParameterList>&, std::__1::vector<std::__1::shared_ptr<solidity::frontend::ModifierInvocation>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::ModifierInvocation> > >&, std::__1::shared_ptr<solidity::frontend::ParameterList>&, std::__1::shared_ptr<solidity::frontend::Block>&, std::__1::shared_ptr<solidity::frontend::Expression>&)
Line
Count
Source
75
29.4k
  {
76
29.4k
    solAssert(m_location.sourceName, "");
77
29.4k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
29.4k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
29.4k
  }
std::__1::shared_ptr<solidity::frontend::StructDefinition> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::StructDefinition, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, solidity::langutil::SourceLocation, std::__1::vector<std::__1::shared_ptr<solidity::frontend::VariableDeclaration>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::VariableDeclaration> > >, std::__1::shared_ptr<solidity::frontend::StructuredDocumentation> >(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&&, solidity::langutil::SourceLocation&&, std::__1::vector<std::__1::shared_ptr<solidity::frontend::VariableDeclaration>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::VariableDeclaration> > >&&, std::__1::shared_ptr<solidity::frontend::StructuredDocumentation>&&)
Line
Count
Source
75
9.75k
  {
76
9.75k
    solAssert(m_location.sourceName, "");
77
9.75k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
9.75k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
9.75k
  }
std::__1::shared_ptr<solidity::frontend::EnumValue> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::EnumValue, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::shared_ptr<solidity::frontend::StructuredDocumentation>&>(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&&, std::__1::shared_ptr<solidity::frontend::StructuredDocumentation>&)
Line
Count
Source
75
2.69k
  {
76
2.69k
    solAssert(m_location.sourceName, "");
77
2.69k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
2.69k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
2.69k
  }
std::__1::shared_ptr<solidity::frontend::EnumDefinition> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::EnumDefinition, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation&, std::__1::vector<std::__1::shared_ptr<solidity::frontend::EnumValue>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::EnumValue> > >&, std::__1::shared_ptr<solidity::frontend::StructuredDocumentation>&>(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation&, std::__1::vector<std::__1::shared_ptr<solidity::frontend::EnumValue>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::EnumValue> > >&, std::__1::shared_ptr<solidity::frontend::StructuredDocumentation>&)
Line
Count
Source
75
632
  {
76
632
    solAssert(m_location.sourceName, "");
77
632
    if (m_location.end < 0)
78
0
      markEndPosition();
79
632
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
632
  }
std::__1::shared_ptr<solidity::frontend::VariableDeclaration> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::VariableDeclaration, std::__1::shared_ptr<solidity::frontend::TypeName>&, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation&, std::__1::shared_ptr<solidity::frontend::Expression>&, solidity::frontend::Visibility&, std::__1::shared_ptr<solidity::frontend::StructuredDocumentation> const&, bool&, solidity::frontend::VariableDeclaration::Mutability&, std::__1::shared_ptr<solidity::frontend::OverrideSpecifier>&, solidity::frontend::VariableDeclaration::Location&>(std::__1::shared_ptr<solidity::frontend::TypeName>&, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation&, std::__1::shared_ptr<solidity::frontend::Expression>&, solidity::frontend::Visibility&, std::__1::shared_ptr<solidity::frontend::StructuredDocumentation> const&, bool&, solidity::frontend::VariableDeclaration::Mutability&, std::__1::shared_ptr<solidity::frontend::OverrideSpecifier>&, solidity::frontend::VariableDeclaration::Location&)
Line
Count
Source
75
96.0k
  {
76
96.0k
    solAssert(m_location.sourceName, "");
77
96.0k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
96.0k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
96.0k
  }
std::__1::shared_ptr<solidity::frontend::ModifierDefinition> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::ModifierDefinition, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation&, std::__1::shared_ptr<solidity::frontend::StructuredDocumentation>&, std::__1::shared_ptr<solidity::frontend::ParameterList>&, bool&, std::__1::shared_ptr<solidity::frontend::OverrideSpecifier>&, std::__1::shared_ptr<solidity::frontend::Block>&>(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation&, std::__1::shared_ptr<solidity::frontend::StructuredDocumentation>&, std::__1::shared_ptr<solidity::frontend::ParameterList>&, bool&, std::__1::shared_ptr<solidity::frontend::OverrideSpecifier>&, std::__1::shared_ptr<solidity::frontend::Block>&)
Line
Count
Source
75
3.39k
  {
76
3.39k
    solAssert(m_location.sourceName, "");
77
3.39k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
3.39k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
3.39k
  }
std::__1::shared_ptr<solidity::frontend::EventDefinition> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::EventDefinition, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation&, std::__1::shared_ptr<solidity::frontend::StructuredDocumentation>&, std::__1::shared_ptr<solidity::frontend::ParameterList>&, bool&>(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation&, std::__1::shared_ptr<solidity::frontend::StructuredDocumentation>&, std::__1::shared_ptr<solidity::frontend::ParameterList>&, bool&)
Line
Count
Source
75
3.83k
  {
76
3.83k
    solAssert(m_location.sourceName, "");
77
3.83k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
3.83k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
3.83k
  }
std::__1::shared_ptr<solidity::frontend::ErrorDefinition> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::ErrorDefinition, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation, std::__1::shared_ptr<solidity::frontend::StructuredDocumentation>&, std::__1::shared_ptr<solidity::frontend::ParameterList>&>(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation&&, std::__1::shared_ptr<solidity::frontend::StructuredDocumentation>&, std::__1::shared_ptr<solidity::frontend::ParameterList>&)
Line
Count
Source
75
1.07k
  {
76
1.07k
    solAssert(m_location.sourceName, "");
77
1.07k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
1.07k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
1.07k
  }
std::__1::shared_ptr<solidity::frontend::UsingForDirective> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::UsingForDirective, std::__1::vector<std::__1::shared_ptr<solidity::frontend::IdentifierPath>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::IdentifierPath> > >, std::__1::vector<std::__1::optional<solidity::langutil::Token>, std::__1::allocator<std::__1::optional<solidity::langutil::Token> > >, bool const&, std::__1::shared_ptr<solidity::frontend::TypeName>&, bool&>(std::__1::vector<std::__1::shared_ptr<solidity::frontend::IdentifierPath>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::IdentifierPath> > >&&, std::__1::vector<std::__1::optional<solidity::langutil::Token>, std::__1::allocator<std::__1::optional<solidity::langutil::Token> > >&&, bool const&, std::__1::shared_ptr<solidity::frontend::TypeName>&, bool&)
Line
Count
Source
75
825
  {
76
825
    solAssert(m_location.sourceName, "");
77
825
    if (m_location.end < 0)
78
0
      markEndPosition();
79
825
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
825
  }
std::__1::shared_ptr<solidity::frontend::ModifierInvocation> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::ModifierInvocation, std::__1::shared_ptr<solidity::frontend::IdentifierPath>&, std::__1::unique_ptr<std::__1::vector<std::__1::shared_ptr<solidity::frontend::Expression>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::Expression> > >, std::__1::default_delete<std::__1::vector<std::__1::shared_ptr<solidity::frontend::Expression>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::Expression> > > > > >(std::__1::shared_ptr<solidity::frontend::IdentifierPath>&, std::__1::unique_ptr<std::__1::vector<std::__1::shared_ptr<solidity::frontend::Expression>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::Expression> > >, std::__1::default_delete<std::__1::vector<std::__1::shared_ptr<solidity::frontend::Expression>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::Expression> > > > >&&)
Line
Count
Source
75
4.19k
  {
76
4.19k
    solAssert(m_location.sourceName, "");
77
4.19k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
4.19k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
4.19k
  }
std::__1::shared_ptr<solidity::frontend::Identifier> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::Identifier, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&&)
Line
Count
Source
75
206k
  {
76
206k
    solAssert(m_location.sourceName, "");
77
206k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
206k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
206k
  }
std::__1::shared_ptr<solidity::frontend::UserDefinedTypeName> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::UserDefinedTypeName, std::__1::shared_ptr<solidity::frontend::IdentifierPath>&>(std::__1::shared_ptr<solidity::frontend::IdentifierPath>&)
Line
Count
Source
75
26.1k
  {
76
26.1k
    solAssert(m_location.sourceName, "");
77
26.1k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
26.1k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
26.1k
  }
std::__1::shared_ptr<solidity::frontend::UserDefinedValueTypeDefinition> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::UserDefinedValueTypeDefinition, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation, std::__1::shared_ptr<solidity::frontend::TypeName>&>(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation&&, std::__1::shared_ptr<solidity::frontend::TypeName>&)
Line
Count
Source
75
735
  {
76
735
    solAssert(m_location.sourceName, "");
77
735
    if (m_location.end < 0)
78
0
      markEndPosition();
79
735
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
735
  }
std::__1::shared_ptr<solidity::frontend::IdentifierPath> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::IdentifierPath, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&, std::__1::vector<solidity::langutil::SourceLocation, std::__1::allocator<solidity::langutil::SourceLocation> >&>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&, std::__1::vector<solidity::langutil::SourceLocation, std::__1::allocator<solidity::langutil::SourceLocation> >&)
Line
Count
Source
75
39.9k
  {
76
39.9k
    solAssert(m_location.sourceName, "");
77
39.9k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
39.9k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
39.9k
  }
std::__1::shared_ptr<solidity::frontend::ArrayTypeName> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::ArrayTypeName, std::__1::shared_ptr<solidity::frontend::TypeName>&, std::__1::shared_ptr<solidity::frontend::Expression>&>(std::__1::shared_ptr<solidity::frontend::TypeName>&, std::__1::shared_ptr<solidity::frontend::Expression>&)
Line
Count
Source
75
24.0k
  {
76
24.0k
    solAssert(m_location.sourceName, "");
77
24.0k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
24.0k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
24.0k
  }
std::__1::shared_ptr<solidity::frontend::ElementaryTypeName> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::ElementaryTypeName, solidity::langutil::ElementaryTypeNameToken&, std::__1::optional<solidity::frontend::StateMutability>&>(solidity::langutil::ElementaryTypeNameToken&, std::__1::optional<solidity::frontend::StateMutability>&)
Line
Count
Source
75
72.6k
  {
76
72.6k
    solAssert(m_location.sourceName, "");
77
72.6k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
72.6k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
72.6k
  }
std::__1::shared_ptr<solidity::frontend::FunctionTypeName> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::FunctionTypeName, std::__1::shared_ptr<solidity::frontend::ParameterList>&, std::__1::shared_ptr<solidity::frontend::ParameterList>&, solidity::frontend::Visibility&, solidity::frontend::StateMutability&>(std::__1::shared_ptr<solidity::frontend::ParameterList>&, std::__1::shared_ptr<solidity::frontend::ParameterList>&, solidity::frontend::Visibility&, solidity::frontend::StateMutability&)
Line
Count
Source
75
1.32k
  {
76
1.32k
    solAssert(m_location.sourceName, "");
77
1.32k
    if (m_location.end < 0)
78
1.32k
      markEndPosition();
79
1.32k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
1.32k
  }
std::__1::shared_ptr<solidity::frontend::ElementaryTypeName> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::ElementaryTypeName, solidity::langutil::ElementaryTypeNameToken>(solidity::langutil::ElementaryTypeNameToken&&)
Line
Count
Source
75
13.9k
  {
76
13.9k
    solAssert(m_location.sourceName, "");
77
13.9k
    if (m_location.end < 0)
78
13.9k
      markEndPosition();
79
13.9k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
13.9k
  }
std::__1::shared_ptr<solidity::frontend::Mapping> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::Mapping, std::__1::shared_ptr<solidity::frontend::TypeName>&, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation&, std::__1::shared_ptr<solidity::frontend::TypeName>&, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation&>(std::__1::shared_ptr<solidity::frontend::TypeName>&, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation&, std::__1::shared_ptr<solidity::frontend::TypeName>&, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation&)
Line
Count
Source
75
1.15k
  {
76
1.15k
    solAssert(m_location.sourceName, "");
77
1.15k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
1.15k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
1.15k
  }
std::__1::shared_ptr<solidity::frontend::ParameterList> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::ParameterList, std::__1::vector<std::__1::shared_ptr<solidity::frontend::VariableDeclaration>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::VariableDeclaration> > >&>(std::__1::vector<std::__1::shared_ptr<solidity::frontend::VariableDeclaration>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::VariableDeclaration> > >&)
Line
Count
Source
75
49.5k
  {
76
49.5k
    solAssert(m_location.sourceName, "");
77
49.5k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
49.5k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
49.5k
  }
std::__1::shared_ptr<solidity::frontend::Block> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::Block, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&, bool const&, std::__1::vector<std::__1::shared_ptr<solidity::frontend::Statement>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::Statement> > >&>(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&, bool const&, std::__1::vector<std::__1::shared_ptr<solidity::frontend::Statement>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::Statement> > >&)
Line
Count
Source
75
30.2k
  {
76
30.2k
    solAssert(m_location.sourceName, "");
77
30.2k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
30.2k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
30.2k
  }
std::__1::shared_ptr<solidity::frontend::Continue> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::Continue, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&>(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&)
Line
Count
Source
75
105
  {
76
105
    solAssert(m_location.sourceName, "");
77
105
    if (m_location.end < 0)
78
105
      markEndPosition();
79
105
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
105
  }
std::__1::shared_ptr<solidity::frontend::Break> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::Break, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&>(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&)
Line
Count
Source
75
123
  {
76
123
    solAssert(m_location.sourceName, "");
77
123
    if (m_location.end < 0)
78
123
      markEndPosition();
79
123
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
123
  }
std::__1::shared_ptr<solidity::frontend::Return> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::Return, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, std::__1::shared_ptr<solidity::frontend::Expression>&>(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, std::__1::shared_ptr<solidity::frontend::Expression>&)
Line
Count
Source
75
46.9k
  {
76
46.9k
    solAssert(m_location.sourceName, "");
77
46.9k
    if (m_location.end < 0)
78
407
      markEndPosition();
79
46.9k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
46.9k
  }
std::__1::shared_ptr<solidity::frontend::Throw> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::Throw, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&>(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&)
Line
Count
Source
75
4
  {
76
4
    solAssert(m_location.sourceName, "");
77
4
    if (m_location.end < 0)
78
4
      markEndPosition();
79
4
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
4
  }
std::__1::shared_ptr<solidity::frontend::PlaceholderStatement> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::PlaceholderStatement, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&>(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&)
Line
Count
Source
75
1.00k
  {
76
1.00k
    solAssert(m_location.sourceName, "");
77
1.00k
    if (m_location.end < 0)
78
1.00k
      markEndPosition();
79
1.00k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
1.00k
  }
std::__1::shared_ptr<solidity::frontend::IfStatement> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::IfStatement, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&, std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::shared_ptr<solidity::frontend::Statement>&, std::__1::shared_ptr<solidity::frontend::Statement>&>(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&, std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::shared_ptr<solidity::frontend::Statement>&, std::__1::shared_ptr<solidity::frontend::Statement>&)
Line
Count
Source
75
38.9k
  {
76
38.9k
    solAssert(m_location.sourceName, "");
77
38.9k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
38.9k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
38.9k
  }
std::__1::shared_ptr<solidity::frontend::TryCatchClause> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::TryCatchClause, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::shared_ptr<solidity::frontend::ParameterList>&, std::__1::shared_ptr<solidity::frontend::Block>&>(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&&, std::__1::shared_ptr<solidity::frontend::ParameterList>&, std::__1::shared_ptr<solidity::frontend::Block>&)
Line
Count
Source
75
411
  {
76
411
    solAssert(m_location.sourceName, "");
77
411
    if (m_location.end < 0)
78
0
      markEndPosition();
79
411
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
411
  }
std::__1::shared_ptr<solidity::frontend::TryStatement> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::TryStatement, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&, std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::vector<std::__1::shared_ptr<solidity::frontend::TryCatchClause>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::TryCatchClause> > >&>(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&, std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::vector<std::__1::shared_ptr<solidity::frontend::TryCatchClause>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::TryCatchClause> > >&)
Line
Count
Source
75
311
  {
76
311
    solAssert(m_location.sourceName, "");
77
311
    if (m_location.end < 0)
78
0
      markEndPosition();
79
311
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
311
  }
std::__1::shared_ptr<solidity::frontend::TryCatchClause> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::TryCatchClause, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, std::__1::shared_ptr<solidity::frontend::ParameterList>&, std::__1::shared_ptr<solidity::frontend::Block>&>(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, std::__1::shared_ptr<solidity::frontend::ParameterList>&, std::__1::shared_ptr<solidity::frontend::Block>&)
Line
Count
Source
75
587
  {
76
587
    solAssert(m_location.sourceName, "");
77
587
    if (m_location.end < 0)
78
0
      markEndPosition();
79
587
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
587
  }
std::__1::shared_ptr<solidity::frontend::WhileStatement> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::WhileStatement, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&, std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::shared_ptr<solidity::frontend::Statement>&, bool>(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&, std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::shared_ptr<solidity::frontend::Statement>&, bool&&)
Line
Count
Source
75
271
  {
76
271
    solAssert(m_location.sourceName, "");
77
271
    if (m_location.end < 0)
78
0
      markEndPosition();
79
271
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
271
  }
std::__1::shared_ptr<solidity::frontend::ForStatement> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::ForStatement, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&, std::__1::shared_ptr<solidity::frontend::Statement>&, std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::shared_ptr<solidity::frontend::ExpressionStatement>&, std::__1::shared_ptr<solidity::frontend::Statement>&>(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&, std::__1::shared_ptr<solidity::frontend::Statement>&, std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::shared_ptr<solidity::frontend::ExpressionStatement>&, std::__1::shared_ptr<solidity::frontend::Statement>&)
Line
Count
Source
75
3.23k
  {
76
3.23k
    solAssert(m_location.sourceName, "");
77
3.23k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
3.23k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
3.23k
  }
std::__1::shared_ptr<solidity::frontend::FunctionCall> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::FunctionCall, std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::vector<std::__1::shared_ptr<solidity::frontend::Expression>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::Expression> > >&, std::__1::vector<std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >&, std::__1::vector<solidity::langutil::SourceLocation, std::__1::allocator<solidity::langutil::SourceLocation> >&>(std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::vector<std::__1::shared_ptr<solidity::frontend::Expression>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::Expression> > >&, std::__1::vector<std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >&, std::__1::vector<solidity::langutil::SourceLocation, std::__1::allocator<solidity::langutil::SourceLocation> >&)
Line
Count
Source
75
39.7k
  {
76
39.7k
    solAssert(m_location.sourceName, "");
77
39.7k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
39.7k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
39.7k
  }
std::__1::shared_ptr<solidity::frontend::EmitStatement> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::EmitStatement, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&, std::__1::shared_ptr<solidity::frontend::FunctionCall>&>(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&, std::__1::shared_ptr<solidity::frontend::FunctionCall>&)
Line
Count
Source
75
1.57k
  {
76
1.57k
    solAssert(m_location.sourceName, "");
77
1.57k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
1.57k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
1.57k
  }
std::__1::shared_ptr<solidity::frontend::RevertStatement> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::RevertStatement, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&, std::__1::shared_ptr<solidity::frontend::FunctionCall>&>(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&, std::__1::shared_ptr<solidity::frontend::FunctionCall>&)
Line
Count
Source
75
87
  {
76
87
    solAssert(m_location.sourceName, "");
77
87
    if (m_location.end < 0)
78
0
      markEndPosition();
79
87
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
87
  }
std::__1::shared_ptr<solidity::frontend::VariableDeclarationStatement> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::VariableDeclarationStatement, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&, std::__1::vector<std::__1::shared_ptr<solidity::frontend::VariableDeclaration>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::VariableDeclaration> > >&, std::__1::shared_ptr<solidity::frontend::Expression>&>(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&, std::__1::vector<std::__1::shared_ptr<solidity::frontend::VariableDeclaration>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::VariableDeclaration> > >&, std::__1::shared_ptr<solidity::frontend::Expression>&)
Line
Count
Source
75
12.5k
  {
76
12.5k
    solAssert(m_location.sourceName, "");
77
12.5k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
12.5k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
12.5k
  }
std::__1::shared_ptr<solidity::frontend::VariableDeclaration> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::VariableDeclaration, decltype(nullptr), std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation&, decltype(nullptr), solidity::frontend::Visibility, std::__1::shared_ptr<solidity::frontend::StructuredDocumentation> const&, bool, solidity::frontend::VariableDeclaration::Mutability, decltype(nullptr), solidity::frontend::VariableDeclaration::Location, std::__1::shared_ptr<solidity::frontend::Expression>&>(decltype(nullptr)&&, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation&, decltype(nullptr)&&, solidity::frontend::Visibility&&, std::__1::shared_ptr<solidity::frontend::StructuredDocumentation> const&, bool&&, solidity::frontend::VariableDeclaration::Mutability&&, decltype(nullptr)&&, solidity::frontend::VariableDeclaration::Location&&, std::__1::shared_ptr<solidity::frontend::Expression>&)
Line
Count
Source
75
260
  {
76
260
    solAssert(m_location.sourceName, "");
77
260
    if (m_location.end < 0)
78
0
      markEndPosition();
79
260
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
260
  }
std::__1::shared_ptr<solidity::frontend::VariableDeclaration> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::VariableDeclaration, decltype(nullptr), std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation&, decltype(nullptr), solidity::frontend::Visibility, decltype(nullptr)>(decltype(nullptr)&&, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation&, decltype(nullptr)&&, solidity::frontend::Visibility&&, decltype(nullptr)&&)
Line
Count
Source
75
60
  {
76
60
    solAssert(m_location.sourceName, "");
77
60
    if (m_location.end < 0)
78
0
      markEndPosition();
79
60
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
60
  }
std::__1::shared_ptr<solidity::frontend::TypeClassDefinition> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::TypeClassDefinition, std::__1::shared_ptr<solidity::frontend::VariableDeclaration>&, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation&, std::__1::shared_ptr<solidity::frontend::StructuredDocumentation> const&, std::__1::vector<std::__1::shared_ptr<solidity::frontend::ASTNode>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::ASTNode> > >&>(std::__1::shared_ptr<solidity::frontend::VariableDeclaration>&, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, solidity::langutil::SourceLocation&, std::__1::shared_ptr<solidity::frontend::StructuredDocumentation> const&, std::__1::vector<std::__1::shared_ptr<solidity::frontend::ASTNode>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::ASTNode> > >&)
Line
Count
Source
75
48
  {
76
48
    solAssert(m_location.sourceName, "");
77
48
    if (m_location.end < 0)
78
0
      markEndPosition();
79
48
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
48
  }
std::__1::shared_ptr<solidity::frontend::TypeClassName> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::TypeClassName, std::__1::variant<solidity::langutil::Token, std::__1::shared_ptr<solidity::frontend::IdentifierPath> >&>(std::__1::variant<solidity::langutil::Token, std::__1::shared_ptr<solidity::frontend::IdentifierPath> >&)
Line
Count
Source
75
54
  {
76
54
    solAssert(m_location.sourceName, "");
77
54
    if (m_location.end < 0)
78
0
      markEndPosition();
79
54
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
54
  }
std::__1::shared_ptr<solidity::frontend::TypeClassInstantiation> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::TypeClassInstantiation, std::__1::shared_ptr<solidity::frontend::TypeName>&, std::__1::shared_ptr<solidity::frontend::ParameterList>&, std::__1::shared_ptr<solidity::frontend::TypeClassName>&, std::__1::vector<std::__1::shared_ptr<solidity::frontend::ASTNode>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::ASTNode> > >&>(std::__1::shared_ptr<solidity::frontend::TypeName>&, std::__1::shared_ptr<solidity::frontend::ParameterList>&, std::__1::shared_ptr<solidity::frontend::TypeClassName>&, std::__1::vector<std::__1::shared_ptr<solidity::frontend::ASTNode>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::ASTNode> > >&)
Line
Count
Source
75
38
  {
76
38
    solAssert(m_location.sourceName, "");
77
38
    if (m_location.end < 0)
78
0
      markEndPosition();
79
38
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
38
  }
std::__1::shared_ptr<solidity::frontend::Builtin> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::Builtin, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, solidity::langutil::SourceLocation>(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&&, solidity::langutil::SourceLocation&&)
Line
Count
Source
75
26
  {
76
26
    solAssert(m_location.sourceName, "");
77
26
    if (m_location.end < 0)
78
26
      markEndPosition();
79
26
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
26
  }
std::__1::shared_ptr<solidity::frontend::TypeDefinition> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::TypeDefinition, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, solidity::langutil::SourceLocation, std::__1::shared_ptr<solidity::frontend::ParameterList>, std::__1::shared_ptr<solidity::frontend::Expression> >(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&&, solidity::langutil::SourceLocation&&, std::__1::shared_ptr<solidity::frontend::ParameterList>&&, std::__1::shared_ptr<solidity::frontend::Expression>&&)
Line
Count
Source
75
195
  {
76
195
    solAssert(m_location.sourceName, "");
77
195
    if (m_location.end < 0)
78
0
      markEndPosition();
79
195
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
195
  }
std::__1::shared_ptr<solidity::frontend::TupleExpression> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::TupleExpression, std::__1::vector<std::__1::shared_ptr<solidity::frontend::Expression>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::Expression> > >&, bool>(std::__1::vector<std::__1::shared_ptr<solidity::frontend::Expression>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::Expression> > >&, bool&&)
Line
Count
Source
75
1.86k
  {
76
1.86k
    solAssert(m_location.sourceName, "");
77
1.86k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
1.86k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
1.86k
  }
std::__1::shared_ptr<solidity::frontend::ExpressionStatement> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::ExpressionStatement, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&, std::__1::shared_ptr<solidity::frontend::Expression>&>(std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&, std::__1::shared_ptr<solidity::frontend::Expression>&)
Line
Count
Source
75
55.0k
  {
76
55.0k
    solAssert(m_location.sourceName, "");
77
55.0k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
55.0k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
55.0k
  }
std::__1::shared_ptr<solidity::frontend::Assignment> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::Assignment, std::__1::shared_ptr<solidity::frontend::Expression>&, solidity::langutil::Token&, std::__1::shared_ptr<solidity::frontend::Expression>&>(std::__1::shared_ptr<solidity::frontend::Expression>&, solidity::langutil::Token&, std::__1::shared_ptr<solidity::frontend::Expression>&)
Line
Count
Source
75
38.3k
  {
76
38.3k
    solAssert(m_location.sourceName, "");
77
38.3k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
38.3k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
38.3k
  }
std::__1::shared_ptr<solidity::frontend::Conditional> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::Conditional, std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::shared_ptr<solidity::frontend::Expression>&>(std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::shared_ptr<solidity::frontend::Expression>&)
Line
Count
Source
75
1.36k
  {
76
1.36k
    solAssert(m_location.sourceName, "");
77
1.36k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
1.36k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
1.36k
  }
std::__1::shared_ptr<solidity::frontend::BinaryOperation> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::BinaryOperation, std::__1::shared_ptr<solidity::frontend::Expression>&, solidity::langutil::Token&, std::__1::shared_ptr<solidity::frontend::Expression>&>(std::__1::shared_ptr<solidity::frontend::Expression>&, solidity::langutil::Token&, std::__1::shared_ptr<solidity::frontend::Expression>&)
Line
Count
Source
75
102k
  {
76
102k
    solAssert(m_location.sourceName, "");
77
102k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
102k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
102k
  }
std::__1::shared_ptr<solidity::frontend::UnaryOperation> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::UnaryOperation, solidity::langutil::Token&, std::__1::shared_ptr<solidity::frontend::Expression>&, bool>(solidity::langutil::Token&, std::__1::shared_ptr<solidity::frontend::Expression>&, bool&&)
Line
Count
Source
75
47.2k
  {
76
47.2k
    solAssert(m_location.sourceName, "");
77
47.2k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
47.2k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
47.2k
  }
std::__1::shared_ptr<solidity::frontend::NewExpression> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::NewExpression, std::__1::shared_ptr<solidity::frontend::TypeName>&>(std::__1::shared_ptr<solidity::frontend::TypeName>&)
Line
Count
Source
75
3.26k
  {
76
3.26k
    solAssert(m_location.sourceName, "");
77
3.26k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
3.26k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
3.26k
  }
std::__1::shared_ptr<solidity::frontend::ElementaryTypeName> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::ElementaryTypeName, solidity::langutil::ElementaryTypeNameToken, std::__1::optional<solidity::frontend::StateMutability> >(solidity::langutil::ElementaryTypeNameToken&&, std::__1::optional<solidity::frontend::StateMutability>&&)
Line
Count
Source
75
275
  {
76
275
    solAssert(m_location.sourceName, "");
77
275
    if (m_location.end < 0)
78
0
      markEndPosition();
79
275
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
275
  }
std::__1::shared_ptr<solidity::frontend::ElementaryTypeNameExpression> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::ElementaryTypeNameExpression, std::__1::shared_ptr<solidity::frontend::ElementaryTypeName>&>(std::__1::shared_ptr<solidity::frontend::ElementaryTypeName>&)
Line
Count
Source
75
13.1k
  {
76
13.1k
    solAssert(m_location.sourceName, "");
77
13.1k
    if (m_location.end < 0)
78
1.76k
      markEndPosition();
79
13.1k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
13.1k
  }
std::__1::shared_ptr<solidity::frontend::IndexRangeAccess> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::IndexRangeAccess, std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::shared_ptr<solidity::frontend::Expression>&>(std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::shared_ptr<solidity::frontend::Expression>&)
Line
Count
Source
75
750
  {
76
750
    solAssert(m_location.sourceName, "");
77
750
    if (m_location.end < 0)
78
0
      markEndPosition();
79
750
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
750
  }
std::__1::shared_ptr<solidity::frontend::IndexAccess> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::IndexAccess, std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::shared_ptr<solidity::frontend::Expression>&>(std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::shared_ptr<solidity::frontend::Expression>&)
Line
Count
Source
75
97.1k
  {
76
97.1k
    solAssert(m_location.sourceName, "");
77
97.1k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
97.1k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
97.1k
  }
std::__1::shared_ptr<solidity::frontend::MemberAccess> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::MemberAccess, std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, solidity::langutil::SourceLocation>(std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&&, solidity::langutil::SourceLocation&&)
Line
Count
Source
75
127k
  {
76
127k
    solAssert(m_location.sourceName, "");
77
127k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
127k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
127k
  }
std::__1::shared_ptr<solidity::frontend::FunctionCallOptions> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::FunctionCallOptions, std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::vector<std::__1::shared_ptr<solidity::frontend::Expression>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::Expression> > >&, std::__1::vector<std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >&>(std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::vector<std::__1::shared_ptr<solidity::frontend::Expression>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::Expression> > >&, std::__1::vector<std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >&)
Line
Count
Source
75
412
  {
76
412
    solAssert(m_location.sourceName, "");
77
412
    if (m_location.end < 0)
78
0
      markEndPosition();
79
412
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
412
  }
std::__1::shared_ptr<solidity::frontend::Literal> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::Literal, solidity::langutil::Token&, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, solidity::frontend::Literal::SubDenomination&>(solidity::langutil::Token&, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&&, solidity::frontend::Literal::SubDenomination&)
Line
Count
Source
75
475
  {
76
475
    solAssert(m_location.sourceName, "");
77
475
    if (m_location.end < 0)
78
0
      markEndPosition();
79
475
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
475
  }
std::__1::shared_ptr<solidity::frontend::Literal> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::Literal, solidity::langutil::Token&, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, solidity::frontend::Literal::SubDenomination>(solidity::langutil::Token&, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&&, solidity::frontend::Literal::SubDenomination&&)
Line
Count
Source
75
323k
  {
76
323k
    solAssert(m_location.sourceName, "");
77
323k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
323k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
323k
  }
std::__1::shared_ptr<solidity::frontend::TupleExpression> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::TupleExpression, std::__1::vector<std::__1::shared_ptr<solidity::frontend::Expression>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::Expression> > >&, bool&>(std::__1::vector<std::__1::shared_ptr<solidity::frontend::Expression>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::Expression> > >&, bool&)
Line
Count
Source
75
9.29k
  {
76
9.29k
    solAssert(m_location.sourceName, "");
77
9.29k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
9.29k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
9.29k
  }
std::__1::shared_ptr<solidity::frontend::ElementaryTypeName> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::ElementaryTypeName, solidity::langutil::ElementaryTypeNameToken const&>(solidity::langutil::ElementaryTypeNameToken const&)
Line
Count
Source
75
1.66k
  {
76
1.66k
    solAssert(m_location.sourceName, "");
77
1.66k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
1.66k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
1.66k
  }
std::__1::shared_ptr<solidity::frontend::UserDefinedTypeName> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::UserDefinedTypeName, std::__1::shared_ptr<solidity::frontend::IdentifierPath> >(std::__1::shared_ptr<solidity::frontend::IdentifierPath>&&)
Line
Count
Source
75
290
  {
76
290
    solAssert(m_location.sourceName, "");
77
290
    if (m_location.end < 0)
78
0
      markEndPosition();
79
290
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
290
  }
std::__1::shared_ptr<solidity::frontend::ArrayTypeName> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::ArrayTypeName, std::__1::shared_ptr<solidity::frontend::TypeName>&, std::__1::shared_ptr<solidity::frontend::Expression> const&>(std::__1::shared_ptr<solidity::frontend::TypeName>&, std::__1::shared_ptr<solidity::frontend::Expression> const&)
Line
Count
Source
75
3.38k
  {
76
3.38k
    solAssert(m_location.sourceName, "");
77
3.38k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
3.38k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
3.38k
  }
std::__1::shared_ptr<solidity::frontend::MemberAccess> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::MemberAccess, std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, solidity::langutil::SourceLocation const&>(std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::shared_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&&, solidity::langutil::SourceLocation const&)
Line
Count
Source
75
40.2k
  {
76
40.2k
    solAssert(m_location.sourceName, "");
77
40.2k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
40.2k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
40.2k
  }
std::__1::shared_ptr<solidity::frontend::IndexRangeAccess> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::IndexRangeAccess, std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::shared_ptr<solidity::frontend::Expression> const&, std::__1::shared_ptr<solidity::frontend::Expression> const&>(std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::shared_ptr<solidity::frontend::Expression> const&, std::__1::shared_ptr<solidity::frontend::Expression> const&)
Line
Count
Source
75
881
  {
76
881
    solAssert(m_location.sourceName, "");
77
881
    if (m_location.end < 0)
78
0
      markEndPosition();
79
881
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
881
  }
std::__1::shared_ptr<solidity::frontend::IndexAccess> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::IndexAccess, std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::shared_ptr<solidity::frontend::Expression> const&>(std::__1::shared_ptr<solidity::frontend::Expression>&, std::__1::shared_ptr<solidity::frontend::Expression> const&)
Line
Count
Source
75
31.9k
  {
76
31.9k
    solAssert(m_location.sourceName, "");
77
31.9k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
31.9k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
31.9k
  }
std::__1::shared_ptr<solidity::frontend::ParameterList> solidity::frontend::Parser::ASTNodeFactory::createNode<solidity::frontend::ParameterList, std::__1::vector<std::__1::shared_ptr<solidity::frontend::VariableDeclaration>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::VariableDeclaration> > > >(std::__1::vector<std::__1::shared_ptr<solidity::frontend::VariableDeclaration>, std::__1::allocator<std::__1::shared_ptr<solidity::frontend::VariableDeclaration> > >&&)
Line
Count
Source
75
23.0k
  {
76
23.0k
    solAssert(m_location.sourceName, "");
77
23.0k
    if (m_location.end < 0)
78
0
      markEndPosition();
79
23.0k
    return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
80
23.0k
  }
81
82
2.14k
  SourceLocation const& location() const noexcept { return m_location; }
83
84
private:
85
  Parser& m_parser;
86
  SourceLocation m_location;
87
};
88
89
ASTPointer<SourceUnit> Parser::parse(CharStream& _charStream)
90
32.8k
{
91
32.8k
  solAssert(!m_insideModifier, "");
92
32.8k
  try
93
32.8k
  {
94
32.8k
    m_recursionDepth = 0;
95
32.8k
    m_scanner = std::make_shared<Scanner>(_charStream);
96
32.8k
    ASTNodeFactory nodeFactory(*this);
97
32.8k
    m_experimentalSolidityEnabledInCurrentSourceUnit = false;
98
99
32.8k
    std::vector<ASTPointer<ASTNode>> nodes;
100
40.8k
    while (m_scanner->currentToken() == Token::Pragma)
101
7.95k
      nodes.push_back(parsePragmaDirective(false));
102
103
32.8k
    if (m_experimentalSolidityEnabledInCurrentSourceUnit)
104
186
      m_scanner->setScannerMode(ScannerKind::ExperimentalSolidity);
105
106
105k
    while (m_scanner->currentToken() != Token::EOS)
107
77.0k
    {
108
77.0k
      switch (m_scanner->currentToken())
109
77.0k
      {
110
25.5k
      case Token::Pragma:
111
25.5k
        nodes.push_back(parsePragmaDirective(true));
112
25.5k
        break;
113
1.87k
      case Token::Import:
114
1.87k
        nodes.push_back(parseImportDirective());
115
1.87k
        break;
116
835
      case Token::Abstract:
117
1.62k
      case Token::Interface:
118
28.1k
      case Token::Contract:
119
29.5k
      case Token::Library:
120
29.5k
        nodes.push_back(parseContractDefinition());
121
29.5k
        break;
122
501
      case Token::Struct:
123
501
        nodes.push_back(parseStructDefinition());
124
501
        break;
125
426
      case Token::Enum:
126
426
        nodes.push_back(parseEnumDefinition());
127
426
        break;
128
809
      case Token::Type:
129
809
        if (m_experimentalSolidityEnabledInCurrentSourceUnit)
130
205
          nodes.push_back(parseTypeDefinition());
131
604
        else
132
604
          nodes.push_back(parseUserDefinedValueTypeDefinition());
133
809
        break;
134
523
      case Token::Using:
135
523
        nodes.push_back(parseUsingDirective());
136
523
        break;
137
3.51k
      case Token::Function:
138
3.51k
        nodes.push_back(parseFunctionDefinition(true));
139
3.51k
        break;
140
22
      case Token::ForAll:
141
22
        nodes.push_back(parseQuantifiedFunctionDefinition());
142
22
        break;
143
740
      case Token::Event:
144
740
        nodes.push_back(parseEventDefinition());
145
740
        break;
146
61
      case Token::Class:
147
61
        solAssert(m_experimentalSolidityEnabledInCurrentSourceUnit);
148
61
        nodes.push_back(parseTypeClassDefinition());
149
61
        break;
150
59
      case Token::Instantiation:
151
59
        solAssert(m_experimentalSolidityEnabledInCurrentSourceUnit);
152
59
        nodes.push_back(parseTypeClassInstantiation());
153
59
        break;
154
13.3k
      default:
155
13.3k
        if (
156
          // Workaround because `error` is not a keyword.
157
13.3k
          m_scanner->currentToken() == Token::Identifier &&
158
7.19k
          currentLiteral() == "error" &&
159
742
          m_scanner->peekNextToken() == Token::Identifier &&
160
739
          m_scanner->peekNextNextToken() == Token::LParen
161
13.3k
        )
162
703
          nodes.push_back(parseErrorDefinition());
163
        // Constant variable.
164
12.6k
        else if (variableDeclarationStart() && m_scanner->peekNextToken() != Token::EOS)
165
11.6k
        {
166
11.6k
          VarDeclParserOptions options;
167
11.6k
          options.kind = VarDeclKind::FileLevel;
168
11.6k
          options.allowInitialValue = true;
169
11.6k
          nodes.push_back(parseVariableDeclaration(options));
170
11.6k
          expectToken(Token::Semicolon);
171
11.6k
        }
172
1.02k
        else
173
1.02k
          fatalParserError(7858_error, "Expected pragma, import directive or contract/interface/library/user-defined type/constant/function/error/event definition.");
174
77.0k
      }
175
77.0k
    }
176
28.2k
    solAssert(m_recursionDepth == 0, "");
177
28.2k
    return nodeFactory.createNode<SourceUnit>(findLicenseString(nodes), nodes, m_experimentalSolidityEnabledInCurrentSourceUnit);
178
32.8k
  }
179
32.8k
  catch (FatalError const&)
180
32.8k
  {
181
4.87k
    if (!m_errorReporter.hasErrors())
182
0
    {
183
0
      std::cerr << "Unreported fatal error:" << std::endl;
184
0
      std::cerr << boost::current_exception_diagnostic_information() << std::endl;
185
0
      solAssert(false, "Unreported fatal error.");
186
0
    }
187
4.87k
    return nullptr;
188
4.87k
  }
189
32.8k
}
190
191
void Parser::parsePragmaVersion(SourceLocation const& _location, std::vector<Token> const& _tokens, std::vector<std::string> const& _literals)
192
2.14k
{
193
2.14k
  SemVerMatchExpressionParser parser(_tokens, _literals);
194
2.14k
  try
195
2.14k
  {
196
2.14k
    SemVerMatchExpression matchExpression = parser.parse();
197
2.14k
    static SemVerVersion const currentVersion{std::string(VersionString)};
198
    // FIXME: only match for major version incompatibility
199
2.14k
    if (!matchExpression.matches(currentVersion))
200
50
      m_errorReporter.fatalParserError(
201
50
        5333_error,
202
50
        _location,
203
50
        "Source file requires different compiler version (current compiler is " +
204
50
        std::string(VersionString) + ") - note that nightly builds are considered to be "
205
50
        "strictly less than the released version"
206
50
      );
207
2.14k
  }
208
2.14k
  catch (SemVerError const& matchError)
209
2.14k
  {
210
206
    m_errorReporter.fatalParserError(
211
206
      1684_error,
212
206
      _location,
213
206
      "Invalid version pragma. "s + matchError.what()
214
206
    );
215
206
  }
216
2.14k
}
217
218
ASTPointer<StructuredDocumentation> Parser::parseStructuredDocumentation()
219
179k
{
220
179k
  if (!m_scanner->currentCommentLiteral().empty())
221
2.37k
  {
222
2.37k
    ASTNodeFactory nodeFactory{*this};
223
2.37k
    nodeFactory.setLocation(m_scanner->currentCommentLocation());
224
2.37k
    return nodeFactory.createNode<StructuredDocumentation>(
225
2.37k
      std::make_shared<ASTString>(m_scanner->currentCommentLiteral())
226
2.37k
    );
227
2.37k
  }
228
177k
  return nullptr;
229
179k
}
230
231
ASTPointer<PragmaDirective> Parser::parsePragmaDirective(bool const _finishedParsingTopLevelPragmas)
232
33.5k
{
233
33.5k
  RecursionGuard recursionGuard(*this);
234
  // pragma anything* ;
235
  // Currently supported:
236
  // pragma solidity ^0.4.0 || ^0.3.0;
237
33.5k
  ASTNodeFactory nodeFactory(*this);
238
33.5k
  expectToken(Token::Pragma);
239
33.5k
  std::vector<std::string> literals;
240
33.5k
  std::vector<Token> tokens;
241
242
33.5k
  do
243
125k
  {
244
125k
    Token token = m_scanner->currentToken();
245
125k
    if (token == Token::Illegal)
246
26.6k
      parserError(6281_error, "Token incompatible with Solidity parser as part of pragma directive.");
247
98.9k
    else
248
98.9k
    {
249
98.9k
      std::string literal = m_scanner->currentLiteral();
250
98.9k
      if (literal.empty() && TokenTraits::toString(token))
251
19.9k
        literal = TokenTraits::toString(token);
252
98.9k
      literals.push_back(literal);
253
98.9k
      tokens.push_back(token);
254
98.9k
    }
255
125k
    advance();
256
125k
  }
257
125k
  while (m_scanner->currentToken() != Token::Semicolon && m_scanner->currentToken() != Token::EOS);
258
33.5k
  nodeFactory.markEndPosition();
259
33.5k
  expectToken(Token::Semicolon);
260
261
33.5k
  if (literals.size() >= 1 && literals[0] == "solidity")
262
2.14k
  {
263
2.14k
    parsePragmaVersion(
264
2.14k
      nodeFactory.location(),
265
2.14k
      std::vector<Token>(tokens.begin() + 1, tokens.end()),
266
2.14k
      std::vector<std::string>(literals.begin() + 1, literals.end())
267
2.14k
    );
268
2.14k
  }
269
270
33.5k
  if (literals.size() >= 2 && literals[0] == "experimental" && literals[1] == "solidity")
271
219
  {
272
219
    if (m_evmVersion < EVMVersion::constantinople())
273
7
      fatalParserError(7637_error, "Experimental solidity requires Constantinople EVM version at the minimum.");
274
219
    if (_finishedParsingTopLevelPragmas)
275
2
      fatalParserError(8185_error, "Experimental pragma \"solidity\" can only be set at the beginning of the source unit.");
276
219
    m_experimentalSolidityEnabledInCurrentSourceUnit = true;
277
219
  }
278
279
33.5k
  return nodeFactory.createNode<PragmaDirective>(tokens, literals);
280
33.5k
}
281
282
ASTPointer<ImportDirective> Parser::parseImportDirective()
283
1.87k
{
284
1.87k
  RecursionGuard recursionGuard(*this);
285
  // import "abc" [as x];
286
  // import * as x from "abc";
287
  // import {a as b, c} from "abc";
288
1.87k
  ASTNodeFactory nodeFactory(*this);
289
1.87k
  expectToken(Token::Import);
290
1.87k
  ASTPointer<ASTString> path;
291
1.87k
  ASTPointer<ASTString> unitAlias = std::make_shared<std::string>();
292
1.87k
  SourceLocation unitAliasLocation{};
293
1.87k
  ImportDirective::SymbolAliasList symbolAliases;
294
295
1.87k
  if (isQuotedPath() || isStdlibPath())
296
1.29k
  {
297
1.29k
    path = isQuotedPath() ? getLiteralAndAdvance() : getStdlibImportPathAndAdvance();
298
1.29k
    if (m_scanner->currentToken() == Token::As)
299
176
    {
300
176
      advance();
301
176
      tie(unitAlias, unitAliasLocation) = expectIdentifierWithLocation();
302
176
    }
303
1.29k
  }
304
574
  else
305
574
  {
306
574
    if (m_scanner->currentToken() == Token::LBrace)
307
456
    {
308
456
      advance();
309
1.45k
      while (true)
310
1.43k
      {
311
1.43k
        ASTPointer<ASTString> alias;
312
1.43k
        SourceLocation aliasLocation = currentLocation();
313
1.43k
        ASTPointer<Identifier> id = parseIdentifier();
314
1.43k
        if (m_scanner->currentToken() == Token::As)
315
286
        {
316
286
          expectToken(Token::As);
317
286
          tie(alias, aliasLocation) = expectIdentifierWithLocation();
318
286
        }
319
1.43k
        symbolAliases.emplace_back(ImportDirective::SymbolAlias{std::move(id), std::move(alias), aliasLocation});
320
1.43k
        if (m_scanner->currentToken() != Token::Comma)
321
437
          break;
322
996
        advance();
323
996
      }
324
456
      expectToken(Token::RBrace);
325
456
    }
326
118
    else if (m_scanner->currentToken() == Token::Mul)
327
91
    {
328
91
      advance();
329
91
      expectToken(Token::As);
330
91
      tie(unitAlias, unitAliasLocation) = expectIdentifierWithLocation();
331
91
    }
332
27
    else
333
27
      fatalParserError(9478_error, "Expected string literal (path), \"*\" or alias list.");
334
    // "from" is not a keyword but parsed as an identifier because of backwards
335
    // compatibility and because it is a really common word.
336
574
    if (m_scanner->currentToken() != Token::Identifier || m_scanner->currentLiteral() != "from")
337
24
      fatalParserError(8208_error, "Expected \"from\".");
338
574
    advance();
339
574
    if (!isQuotedPath() && !isStdlibPath())
340
12
      fatalParserError(6845_error, "Expected import path.");
341
574
    path = isQuotedPath() ? getLiteralAndAdvance() : getStdlibImportPathAndAdvance();
342
574
  }
343
1.87k
  if (path->empty())
344
1
    fatalParserError(6326_error, "Import path cannot be empty.");
345
1.87k
  nodeFactory.markEndPosition();
346
1.87k
  expectToken(Token::Semicolon);
347
1.87k
  return nodeFactory.createNode<ImportDirective>(path, unitAlias, unitAliasLocation, std::move(symbolAliases));
348
1.87k
}
349
350
std::pair<ContractKind, bool> Parser::parseContractKind()
351
29.5k
{
352
29.5k
  ContractKind kind;
353
29.5k
  bool abstract = false;
354
29.5k
  if (m_scanner->currentToken() == Token::Abstract)
355
835
  {
356
835
    abstract = true;
357
835
    advance();
358
835
  }
359
29.5k
  switch (m_scanner->currentToken())
360
29.5k
  {
361
801
  case Token::Interface:
362
801
    kind = ContractKind::Interface;
363
801
    break;
364
27.3k
  case Token::Contract:
365
27.3k
    kind = ContractKind::Contract;
366
27.3k
    break;
367
1.38k
  case Token::Library:
368
1.38k
    kind = ContractKind::Library;
369
1.38k
    break;
370
18
  default:
371
18
    parserError(3515_error, "Expected keyword \"contract\", \"interface\" or \"library\".");
372
18
    return std::make_pair(ContractKind::Contract, abstract);
373
29.5k
  }
374
29.5k
  advance();
375
29.5k
  return std::make_pair(kind, abstract);
376
29.5k
}
377
378
ASTPointer<StorageLayoutSpecifier> Parser::parseStorageLayoutSpecifier()
379
62
{
380
62
  RecursionGuard recursionGuard(*this);
381
62
  ASTNodeFactory nodeFactory(*this);
382
62
  ASTPointer<ASTString> layoutIdentifier = expectIdentifierToken();
383
62
  solAssert(layoutIdentifier && *layoutIdentifier == "layout");
384
62
  if (
385
62
    m_scanner->currentToken() != Token::Identifier ||
386
59
    m_scanner->currentLiteral() != "at"
387
62
  )
388
62
    m_errorReporter.parserError(
389
62
      1994_error,
390
62
      m_scanner->currentLocation(),
391
62
      "Expected \'at\' but got " + tokenName(m_scanner->currentToken())
392
62
    );
393
394
62
  advance();
395
62
  ASTPointer<Expression> baseSlotExpression = parseExpression();
396
62
  solAssert(baseSlotExpression);
397
62
  nodeFactory.setEndPositionFromNode(baseSlotExpression);
398
62
  return nodeFactory.createNode<StorageLayoutSpecifier>(
399
62
    baseSlotExpression
400
62
  );
401
62
}
402
403
ASTPointer<ContractDefinition> Parser::parseContractDefinition()
404
29.5k
{
405
29.5k
  RecursionGuard recursionGuard(*this);
406
29.5k
  ASTNodeFactory nodeFactory(*this);
407
29.5k
  ASTPointer<ASTString> name =  nullptr;
408
29.5k
  SourceLocation nameLocation{};
409
29.5k
  ASTPointer<StructuredDocumentation> documentation;
410
29.5k
  std::vector<ASTPointer<InheritanceSpecifier>> baseContracts;
411
29.5k
  std::vector<ASTPointer<ASTNode>> subNodes;
412
29.5k
  std::pair<ContractKind, bool> contractKind{};
413
29.5k
  ASTPointer<StorageLayoutSpecifier> storageLayoutSpecifier;
414
29.5k
  documentation = parseStructuredDocumentation();
415
29.5k
  contractKind = parseContractKind();
416
29.5k
  std::tie(name, nameLocation) = expectIdentifierWithLocation();
417
33.6k
  while (true)
418
33.6k
  {
419
33.6k
    if (m_scanner->currentToken() == Token::Is)
420
4.06k
    {
421
4.06k
      if (baseContracts.size() != 0)
422
15
        m_errorReporter.parserError(
423
15
          6668_error,
424
15
          m_scanner->currentLocation(),
425
15
          SecondarySourceLocation().append("Previous list:", baseContracts[0]->location()),
426
15
          "More than one inheritance list."
427
15
        );
428
4.06k
      do
429
5.39k
      {
430
5.39k
        advance();
431
5.39k
        baseContracts.push_back(parseInheritanceSpecifier());
432
5.39k
      }
433
5.39k
      while (m_scanner->currentToken() == Token::Comma);
434
4.06k
    }
435
29.5k
    else if (
436
29.5k
      m_scanner->currentToken() == Token::Identifier &&
437
75
      m_scanner->currentLiteral() == "layout" &&
438
62
      contractKind.first == ContractKind::Contract
439
29.5k
    )
440
62
    {
441
62
      if (storageLayoutSpecifier)
442
50
        m_errorReporter.parserError(
443
50
          8714_error,
444
50
          m_scanner->currentLocation(),
445
50
          SecondarySourceLocation().append("Previous definition:", storageLayoutSpecifier->location()),
446
50
          "More than one storage layout definition."
447
50
        );
448
449
62
      storageLayoutSpecifier = parseStorageLayoutSpecifier();
450
62
    }
451
29.5k
    else
452
29.5k
      break;
453
33.6k
  }
454
455
29.5k
  if (storageLayoutSpecifier && baseContracts.size() > 0)
456
0
  {
457
0
    solAssert(!storageLayoutSpecifier->location().intersects(baseContracts[0]->location()));
458
0
    solAssert(!baseContracts[0]->location().intersects(storageLayoutSpecifier->location()));
459
0
  }
460
461
29.5k
  expectToken(Token::LBrace);
462
87.6k
  while (true)
463
86.0k
  {
464
86.0k
    Token currentTokenValue = m_scanner->currentToken();
465
86.0k
    if (currentTokenValue == Token::RBrace)
466
27.9k
      break;
467
58.1k
    else if (
468
58.1k
      (currentTokenValue == Token::Function && m_scanner->peekNextToken() != Token::LParen) ||
469
34.2k
      currentTokenValue == Token::Constructor ||
470
31.7k
      currentTokenValue == Token::Receive ||
471
31.5k
      currentTokenValue == Token::Fallback
472
58.1k
    )
473
27.0k
      subNodes.push_back(parseFunctionDefinition());
474
31.0k
    else if (currentTokenValue == Token::Struct)
475
9.34k
      subNodes.push_back(parseStructDefinition());
476
21.6k
    else if (currentTokenValue == Token::Enum)
477
255
      subNodes.push_back(parseEnumDefinition());
478
21.4k
    else if (currentTokenValue == Token::Type)
479
176
      subNodes.push_back(parseUserDefinedValueTypeDefinition());
480
21.2k
    else if (
481
      // Workaround because `error` is not a keyword.
482
21.2k
      currentTokenValue == Token::Identifier &&
483
2.07k
      currentLiteral() == "error" &&
484
456
      m_scanner->peekNextToken() == Token::Identifier &&
485
454
      m_scanner->peekNextNextToken() == Token::LParen
486
21.2k
    )
487
417
      subNodes.push_back(parseErrorDefinition());
488
20.8k
    else if (variableDeclarationStart())
489
13.7k
    {
490
13.7k
      VarDeclParserOptions options;
491
13.7k
      options.kind = VarDeclKind::State;
492
13.7k
      options.allowInitialValue = true;
493
13.7k
      subNodes.push_back(parseVariableDeclaration(options));
494
13.7k
      expectToken(Token::Semicolon);
495
13.7k
    }
496
7.13k
    else if (currentTokenValue == Token::Modifier)
497
3.47k
      subNodes.push_back(parseModifierDefinition());
498
3.66k
    else if (currentTokenValue == Token::Event)
499
3.14k
      subNodes.push_back(parseEventDefinition());
500
518
    else if (currentTokenValue == Token::Using)
501
390
      subNodes.push_back(parseUsingDirective());
502
128
    else
503
128
      fatalParserError(9182_error, "Function, variable, struct or modifier declaration expected.");
504
86.0k
  }
505
29.5k
  nodeFactory.markEndPosition();
506
29.5k
  expectToken(Token::RBrace);
507
29.5k
  return nodeFactory.createNode<ContractDefinition>(
508
29.5k
    name,
509
29.5k
    nameLocation,
510
29.5k
    documentation,
511
29.5k
    baseContracts,
512
29.5k
    subNodes,
513
29.5k
    contractKind.first,
514
29.5k
    contractKind.second,
515
29.5k
    storageLayoutSpecifier
516
29.5k
  );
517
29.5k
}
518
519
ASTPointer<InheritanceSpecifier> Parser::parseInheritanceSpecifier()
520
5.39k
{
521
5.39k
  RecursionGuard recursionGuard(*this);
522
5.39k
  ASTNodeFactory nodeFactory(*this);
523
5.39k
  ASTPointer<IdentifierPath> name(parseIdentifierPath());
524
5.39k
  std::unique_ptr<std::vector<ASTPointer<Expression>>> arguments;
525
5.39k
  if (m_scanner->currentToken() == Token::LParen)
526
193
  {
527
193
    advance();
528
193
    arguments = std::make_unique<std::vector<ASTPointer<Expression>>>(parseFunctionCallListArguments());
529
193
    nodeFactory.markEndPosition();
530
193
    expectToken(Token::RParen);
531
193
  }
532
5.19k
  else
533
5.19k
    nodeFactory.setEndPositionFromNode(name);
534
5.39k
  return nodeFactory.createNode<InheritanceSpecifier>(name, std::move(arguments));
535
5.39k
}
536
537
Visibility Parser::parseVisibilitySpecifier()
538
28.7k
{
539
28.7k
  Visibility visibility(Visibility::Default);
540
28.7k
  Token token = m_scanner->currentToken();
541
28.7k
  switch (token)
542
28.7k
  {
543
19.5k
    case Token::Public:
544
19.5k
      visibility = Visibility::Public;
545
19.5k
      break;
546
2.75k
    case Token::Internal:
547
2.75k
      visibility = Visibility::Internal;
548
2.75k
      break;
549
159
    case Token::Private:
550
159
      visibility = Visibility::Private;
551
159
      break;
552
6.35k
    case Token::External:
553
6.35k
      visibility = Visibility::External;
554
6.35k
      break;
555
0
    default:
556
0
      solAssert(false, "Invalid visibility specifier.");
557
28.7k
  }
558
28.7k
  advance();
559
28.7k
  return visibility;
560
28.7k
}
561
562
ASTPointer<OverrideSpecifier> Parser::parseOverrideSpecifier()
563
1.19k
{
564
1.19k
  solAssert(m_scanner->currentToken() == Token::Override, "");
565
566
1.19k
  ASTNodeFactory nodeFactory(*this);
567
1.19k
  std::vector<ASTPointer<IdentifierPath>> overrides;
568
569
1.19k
  nodeFactory.markEndPosition();
570
1.19k
  advance();
571
572
1.19k
  if (m_scanner->currentToken() == Token::LParen)
573
503
  {
574
503
    advance();
575
2.43k
    while (true)
576
2.41k
    {
577
2.41k
      overrides.push_back(parseIdentifierPath());
578
579
2.41k
      if (m_scanner->currentToken() == Token::RParen)
580
488
        break;
581
582
1.93k
      expectToken(Token::Comma);
583
1.93k
    }
584
585
503
    nodeFactory.markEndPosition();
586
503
    expectToken(Token::RParen);
587
503
  }
588
589
1.19k
  return nodeFactory.createNode<OverrideSpecifier>(std::move(overrides));
590
1.19k
}
591
592
StateMutability Parser::parseStateMutability()
593
10.3k
{
594
10.3k
  StateMutability stateMutability(StateMutability::NonPayable);
595
10.3k
  Token token = m_scanner->currentToken();
596
10.3k
  switch (token)
597
10.3k
  {
598
1.60k
    case Token::Payable:
599
1.60k
      stateMutability = StateMutability::Payable;
600
1.60k
      break;
601
2.36k
    case Token::View:
602
2.36k
      stateMutability = StateMutability::View;
603
2.36k
      break;
604
6.33k
    case Token::Pure:
605
6.33k
      stateMutability = StateMutability::Pure;
606
6.33k
      break;
607
0
    default:
608
0
      solAssert(false, "Invalid state mutability specifier.");
609
10.3k
  }
610
10.3k
  advance();
611
10.3k
  return stateMutability;
612
10.3k
}
613
614
Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _isStateVariable)
615
32.0k
{
616
32.0k
  RecursionGuard recursionGuard(*this);
617
32.0k
  FunctionHeaderParserResult result;
618
619
32.0k
  VarDeclParserOptions options;
620
32.0k
  options.allowLocationSpecifier = true;
621
32.0k
  result.parameters = parseParameterList(options);
622
72.1k
  while (true)
623
71.9k
  {
624
71.9k
    Token token = m_scanner->currentToken();
625
71.9k
    if (!_isStateVariable && token == Token::Identifier)
626
4.21k
      result.modifiers.push_back(parseModifierInvocation());
627
67.7k
    else if (TokenTraits::isVisibilitySpecifier(token))
628
24.4k
    {
629
24.4k
      if (result.visibility != Visibility::Default)
630
207
      {
631
        // There is the special case of a public state variable of function type.
632
        // Detect this and return early.
633
207
        if (_isStateVariable && (result.visibility == Visibility::External || result.visibility == Visibility::Internal))
634
67
          break;
635
140
        parserError(
636
140
          9439_error,
637
140
          "Visibility already specified as \"" +
638
140
          Declaration::visibilityToString(result.visibility) +
639
140
          "\"."
640
140
        );
641
140
        advance();
642
140
      }
643
24.1k
      else
644
24.1k
        result.visibility = parseVisibilitySpecifier();
645
24.4k
    }
646
43.3k
    else if (TokenTraits::isStateMutabilitySpecifier(token))
647
9.85k
    {
648
9.85k
      if (result.stateMutability != StateMutability::NonPayable)
649
37
      {
650
37
        parserError(
651
37
          9680_error,
652
37
          "State mutability already specified as \"" +
653
37
          stateMutabilityToString(result.stateMutability) +
654
37
          "\"."
655
37
        );
656
37
        advance();
657
37
      }
658
9.81k
      else
659
9.81k
        result.stateMutability = parseStateMutability();
660
9.85k
    }
661
33.5k
    else if (!_isStateVariable && token == Token::Override)
662
707
    {
663
707
      if (result.overrides)
664
33
        parserError(1827_error, "Override already specified.");
665
666
707
      result.overrides = parseOverrideSpecifier();
667
707
    }
668
32.8k
    else if (!_isStateVariable && token == Token::Virtual)
669
914
    {
670
914
      if (result.isVirtual)
671
125
        parserError(6879_error, "Virtual already specified.");
672
673
914
      result.isVirtual = true;
674
914
      advance();
675
914
    }
676
31.8k
    else
677
31.8k
      break;
678
71.9k
  }
679
32.0k
  if (m_experimentalSolidityEnabledInCurrentSourceUnit)
680
212
  {
681
212
    if (m_scanner->currentToken() == Token::RightArrow)
682
10
    {
683
10
      advance();
684
10
      result.experimentalReturnExpression = parseBinaryExpression();
685
10
    }
686
212
  }
687
31.8k
  else
688
31.8k
  {
689
31.8k
    if (m_scanner->currentToken() == Token::Returns)
690
11.4k
    {
691
11.4k
      bool const permitEmptyParameterList = m_experimentalSolidityEnabledInCurrentSourceUnit;
692
11.4k
      advance();
693
11.4k
      result.returnParameters = parseParameterList(options, permitEmptyParameterList);
694
11.4k
    }
695
20.4k
    else
696
20.4k
      result.returnParameters = createEmptyParameterList();
697
31.8k
  }
698
32.0k
  return result;
699
32.0k
}
700
701
ASTPointer<ForAllQuantifier> Parser::parseQuantifiedFunctionDefinition()
702
22
{
703
22
  solAssert(m_experimentalSolidityEnabledInCurrentSourceUnit);
704
22
  RecursionGuard recursionGuard(*this);
705
22
  ASTNodeFactory nodeFactory(*this);
706
707
22
  expectToken(Token::ForAll);
708
22
  ASTPointer<ParameterList> typeVariableDeclarations = parseParameterList();
709
22
  nodeFactory.markEndPosition();
710
711
22
  if (m_scanner->currentToken() != Token::Function)
712
4
    fatalParserError(5709_error, "Expected a function definition.");
713
714
22
  ASTPointer<FunctionDefinition> quantifiedFunction = parseFunctionDefinition(true /* _freeFunction */, true /* _allowBody */);
715
716
22
  return nodeFactory.createNode<ForAllQuantifier>(
717
22
    std::move(typeVariableDeclarations),
718
22
    std::move(quantifiedFunction)
719
22
  );
720
22
}
721
722
ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(bool _freeFunction, bool _allowBody)
723
30.7k
{
724
30.7k
  RecursionGuard recursionGuard(*this);
725
30.7k
  ASTNodeFactory nodeFactory(*this);
726
30.7k
  ASTPointer<StructuredDocumentation> documentation = parseStructuredDocumentation();
727
728
30.7k
  Token kind = m_scanner->currentToken();
729
30.7k
  ASTPointer<ASTString> name;
730
30.7k
  SourceLocation nameLocation;
731
30.7k
  if (kind == Token::Function)
732
27.5k
  {
733
27.5k
    advance();
734
27.5k
    if (
735
27.5k
      m_scanner->currentToken() == Token::Constructor ||
736
27.5k
      m_scanner->currentToken() == Token::Fallback ||
737
27.4k
      m_scanner->currentToken() == Token::Receive
738
27.5k
    )
739
39
    {
740
39
      std::string expected = std::map<Token, std::string>{
741
39
        {Token::Constructor, "constructor"},
742
39
        {Token::Fallback, "fallback function"},
743
39
        {Token::Receive, "receive function"},
744
39
      }.at(m_scanner->currentToken());
745
39
      nameLocation = currentLocation();
746
39
      name = std::make_shared<ASTString>(TokenTraits::toString(m_scanner->currentToken()));
747
39
      std::string message{
748
39
        "This function is named \"" + *name + "\" but is not the " + expected + " of the contract. "
749
39
        "If you intend this to be a " + expected + ", use \"" + *name + "(...) { ... }\" without "
750
39
        "the \"function\" keyword to define it."
751
39
      };
752
39
      if (m_scanner->currentToken() == Token::Constructor)
753
6
        parserError(3323_error, message);
754
33
      else
755
33
        parserWarning(3445_error, message);
756
39
      advance();
757
39
    }
758
27.4k
    else
759
27.4k
      tie(name, nameLocation) = expectIdentifierWithLocation();
760
27.5k
  }
761
3.20k
  else
762
3.20k
  {
763
3.20k
    solAssert(kind == Token::Constructor || kind == Token::Fallback || kind == Token::Receive, "");
764
3.20k
    advance();
765
3.20k
    name = std::make_shared<ASTString>();
766
3.20k
  }
767
768
30.7k
  FunctionHeaderParserResult header = parseFunctionHeader(false);
769
770
30.7k
  if (m_experimentalSolidityEnabledInCurrentSourceUnit)
771
30.7k
    solAssert(!header.returnParameters);
772
30.5k
  else
773
30.7k
    solAssert(!header.experimentalReturnExpression);
774
775
30.7k
  ASTPointer<Block> block;
776
30.7k
  nodeFactory.markEndPosition();
777
30.7k
  if (!_allowBody)
778
32
    expectToken(Token::Semicolon);
779
30.6k
  else if (m_scanner->currentToken() == Token::Semicolon)
780
2.40k
    advance();
781
28.2k
  else
782
28.2k
  {
783
28.2k
    block = parseBlock();
784
28.2k
    nodeFactory.setEndPositionFromNode(block);
785
28.2k
  }
786
30.7k
  return nodeFactory.createNode<FunctionDefinition>(
787
30.7k
    name,
788
30.7k
    nameLocation,
789
30.7k
    header.visibility,
790
30.7k
    header.stateMutability,
791
30.7k
    _freeFunction,
792
30.7k
    kind,
793
30.7k
    header.isVirtual,
794
30.7k
    header.overrides,
795
30.7k
    documentation,
796
30.7k
    header.parameters,
797
30.7k
    header.modifiers,
798
30.7k
    header.returnParameters,
799
30.7k
    block,
800
30.7k
    header.experimentalReturnExpression
801
30.7k
  );
802
30.7k
}
803
804
ASTPointer<StructDefinition> Parser::parseStructDefinition()
805
9.84k
{
806
9.84k
  RecursionGuard recursionGuard(*this);
807
9.84k
  ASTNodeFactory nodeFactory(*this);
808
9.84k
  ASTPointer<StructuredDocumentation> documentation = parseStructuredDocumentation();
809
9.84k
  expectToken(Token::Struct);
810
9.84k
  auto [name, nameLocation] = expectIdentifierWithLocation();
811
9.84k
  std::vector<ASTPointer<VariableDeclaration>> members;
812
9.84k
  expectToken(Token::LBrace);
813
30.7k
  while (m_scanner->currentToken() != Token::RBrace)
814
20.8k
  {
815
20.8k
    members.push_back(parseVariableDeclaration());
816
20.8k
    expectToken(Token::Semicolon);
817
20.8k
  }
818
9.84k
  nodeFactory.markEndPosition();
819
9.84k
  expectToken(Token::RBrace);
820
9.84k
  return nodeFactory.createNode<StructDefinition>(std::move(name), std::move(nameLocation), std::move(members), std::move(documentation));
821
9.84k
}
822
823
ASTPointer<EnumValue> Parser::parseEnumValue()
824
2.69k
{
825
2.69k
  RecursionGuard recursionGuard(*this);
826
2.69k
  ASTNodeFactory nodeFactory(*this);
827
2.69k
  ASTPointer<StructuredDocumentation> documentation = parseStructuredDocumentation();
828
2.69k
  nodeFactory.markEndPosition();
829
2.69k
  return nodeFactory.createNode<EnumValue>(expectIdentifierToken(), documentation);
830
2.69k
}
831
832
ASTPointer<EnumDefinition> Parser::parseEnumDefinition()
833
681
{
834
681
  RecursionGuard recursionGuard(*this);
835
681
  ASTNodeFactory nodeFactory(*this);
836
681
  ASTPointer<StructuredDocumentation> documentation = parseStructuredDocumentation();
837
681
  expectToken(Token::Enum);
838
681
  auto [name, nameLocation] = expectIdentifierWithLocation();
839
681
  std::vector<ASTPointer<EnumValue>> members;
840
681
  expectToken(Token::LBrace);
841
842
2.83k
  while (m_scanner->currentToken() != Token::RBrace)
843
2.69k
  {
844
2.69k
    members.push_back(parseEnumValue());
845
2.69k
    if (m_scanner->currentToken() == Token::RBrace)
846
543
      break;
847
2.15k
    expectToken(Token::Comma);
848
2.15k
    if (m_scanner->currentToken() != Token::Identifier)
849
6
      fatalParserError(1612_error, "Expected identifier after ','");
850
2.15k
  }
851
681
  if (members.empty())
852
89
    parserError(3147_error, "Enum with no members is not allowed.");
853
854
681
  nodeFactory.markEndPosition();
855
681
  expectToken(Token::RBrace);
856
681
  return nodeFactory.createNode<EnumDefinition>(name, nameLocation, members, documentation);
857
681
}
858
859
ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
860
  VarDeclParserOptions const& _options,
861
  ASTPointer<TypeName> const& _lookAheadArrayType
862
)
863
97.4k
{
864
97.4k
  RecursionGuard recursionGuard(*this);
865
97.4k
  ASTNodeFactory nodeFactory = _lookAheadArrayType ?
866
95.4k
    ASTNodeFactory(*this, _lookAheadArrayType) : ASTNodeFactory(*this);
867
868
97.4k
  ASTPointer<StructuredDocumentation> const documentation = parseStructuredDocumentation();
869
97.4k
  ASTPointer<TypeName> type = _lookAheadArrayType ? _lookAheadArrayType : parseTypeName();
870
97.4k
  nodeFactory.setEndPositionFromNode(type);
871
872
97.4k
  if (dynamic_cast<FunctionTypeName*>(type.get()) && _options.kind == VarDeclKind::State && m_scanner->currentToken() == Token::LBrace)
873
1
    fatalParserError(
874
1
      2915_error,
875
1
      "Expected a state variable declaration. If you intended this as a fallback function "
876
1
      "or a function to handle plain ether transactions, use the \"fallback\" keyword "
877
1
      "or the \"receive\" keyword instead."
878
1
    );
879
880
97.4k
  bool isIndexed = false;
881
97.4k
  VariableDeclaration::Mutability mutability = VariableDeclaration::Mutability::Mutable;
882
97.4k
  ASTPointer<OverrideSpecifier> overrides = nullptr;
883
97.4k
  Visibility visibility(Visibility::Default);
884
97.4k
  VariableDeclaration::Location location = VariableDeclaration::Location::Unspecified;
885
97.4k
  ASTPointer<ASTString> identifier;
886
97.4k
  SourceLocation nameLocation{};
887
888
117k
  while (true)
889
117k
  {
890
117k
    Token token = m_scanner->currentToken();
891
117k
    if (_options.kind == VarDeclKind::State && TokenTraits::isVariableVisibilitySpecifier(token))
892
4.60k
    {
893
4.60k
      nodeFactory.markEndPosition();
894
4.60k
      if (visibility != Visibility::Default)
895
7
      {
896
7
        parserError(
897
7
          4110_error,
898
7
          "Visibility already specified as \"" +
899
7
          Declaration::visibilityToString(visibility) +
900
7
          "\"."
901
7
        );
902
7
        advance();
903
7
      }
904
4.59k
      else
905
4.59k
        visibility = parseVisibilitySpecifier();
906
4.60k
    }
907
112k
    else if (_options.kind == VarDeclKind::State && token == Token::Override)
908
217
    {
909
217
      if (overrides)
910
13
        parserError(9125_error, "Override already specified.");
911
912
217
      overrides = parseOverrideSpecifier();
913
217
    }
914
112k
    else
915
112k
    {
916
112k
      if (_options.allowIndexed && token == Token::Indexed)
917
240
      {
918
240
        if (isIndexed)
919
16
          parserError(5399_error, "Indexed already specified.");
920
921
240
        isIndexed = true;
922
240
      }
923
112k
      else if (token == Token::Constant || token == Token::Immutable)
924
3.22k
      {
925
3.22k
        if (mutability != VariableDeclaration::Mutability::Mutable)
926
39
          parserError(
927
39
            3109_error,
928
39
            std::string("Mutability already set to ") +
929
39
            (mutability == VariableDeclaration::Mutability::Constant ? "\"constant\"" : "\"immutable\"")
930
39
          );
931
3.18k
        else if (token == Token::Constant)
932
2.67k
          mutability = VariableDeclaration::Mutability::Constant;
933
514
        else if (token == Token::Immutable)
934
514
          mutability = VariableDeclaration::Mutability::Immutable;
935
3.22k
      }
936
108k
      else if (_options.allowLocationSpecifier && TokenTraits::isLocationSpecifier(token))
937
12.2k
      {
938
12.2k
        if (location != VariableDeclaration::Location::Unspecified)
939
2
          parserError(3548_error, "Location already specified.");
940
12.2k
        else
941
12.2k
        {
942
12.2k
          switch (token)
943
12.2k
          {
944
698
          case Token::Storage:
945
698
            location = VariableDeclaration::Location::Storage;
946
698
            break;
947
9.74k
          case Token::Memory:
948
9.74k
            location = VariableDeclaration::Location::Memory;
949
9.74k
            break;
950
1.80k
          case Token::CallData:
951
1.80k
            location = VariableDeclaration::Location::CallData;
952
1.80k
            break;
953
0
          default:
954
0
            solAssert(false, "Unknown data location.");
955
12.2k
          }
956
12.2k
        }
957
12.2k
      }
958
96.7k
      else if (
959
96.7k
        _options.kind == VarDeclKind::State &&
960
13.6k
        token == Token::Identifier &&
961
13.5k
        m_scanner->currentLiteral() == "transient" &&
962
1
        m_scanner->peekNextToken() != Token::Assign &&
963
1
        m_scanner->peekNextToken() != Token::Semicolon
964
96.7k
      )
965
0
      {
966
0
        if (location != VariableDeclaration::Location::Unspecified)
967
0
          parserError(ErrorId{3548}, "Location already specified.");
968
0
        else
969
0
          location = VariableDeclaration::Location::Transient;
970
0
      }
971
96.7k
      else
972
96.7k
        break;
973
15.7k
      nodeFactory.markEndPosition();
974
15.7k
      advance();
975
15.7k
    }
976
117k
  }
977
978
97.4k
  if (_options.allowEmptyName && m_scanner->currentToken() != Token::Identifier)
979
18.3k
    identifier = std::make_shared<ASTString>("");
980
79.1k
  else
981
79.1k
  {
982
79.1k
    nodeFactory.markEndPosition();
983
79.1k
    tie(identifier, nameLocation) = expectIdentifierWithLocation();
984
79.1k
  }
985
97.4k
  ASTPointer<Expression> value;
986
97.4k
  if (_options.allowInitialValue)
987
24.1k
  {
988
24.1k
    if (m_scanner->currentToken() == Token::Assign)
989
5.88k
    {
990
5.88k
      advance();
991
5.88k
      value = parseExpression();
992
5.88k
      nodeFactory.setEndPositionFromNode(value);
993
5.88k
    }
994
24.1k
  }
995
97.4k
  return nodeFactory.createNode<VariableDeclaration>(
996
97.4k
    type,
997
97.4k
    identifier,
998
97.4k
    nameLocation,
999
97.4k
    value,
1000
97.4k
    visibility,
1001
97.4k
    documentation,
1002
97.4k
    isIndexed,
1003
97.4k
    mutability,
1004
97.4k
    overrides,
1005
97.4k
    location
1006
97.4k
  );
1007
97.4k
}
1008
1009
ASTPointer<ModifierDefinition> Parser::parseModifierDefinition()
1010
3.47k
{
1011
3.47k
  RecursionGuard recursionGuard(*this);
1012
3.47k
  ScopeGuard resetModifierFlag([this]() { m_insideModifier = false; });
1013
3.47k
  m_insideModifier = true;
1014
1015
3.47k
  ASTNodeFactory nodeFactory(*this);
1016
3.47k
  ASTPointer<StructuredDocumentation> documentation = parseStructuredDocumentation();
1017
1018
3.47k
  expectToken(Token::Modifier);
1019
3.47k
  auto [name, nameLocation] = expectIdentifierWithLocation();
1020
3.47k
  ASTPointer<ParameterList> parameters;
1021
3.47k
  if (m_scanner->currentToken() == Token::LParen)
1022
693
  {
1023
693
    VarDeclParserOptions options;
1024
693
    options.allowLocationSpecifier = true;
1025
693
    parameters = parseParameterList(options);
1026
693
  }
1027
2.77k
  else
1028
2.77k
    parameters = createEmptyParameterList();
1029
1030
3.47k
  ASTPointer<OverrideSpecifier> overrides;
1031
3.47k
  bool isVirtual = false;
1032
1033
3.99k
  while (true)
1034
3.96k
  {
1035
3.96k
    if (m_scanner->currentToken() == Token::Override)
1036
268
    {
1037
268
      if (overrides)
1038
6
        parserError(9102_error, "Override already specified.");
1039
268
      overrides = parseOverrideSpecifier();
1040
268
    }
1041
3.69k
    else if (m_scanner->currentToken() == Token::Virtual)
1042
255
    {
1043
255
      if (isVirtual)
1044
10
        parserError(2662_error, "Virtual already specified.");
1045
1046
255
      isVirtual = true;
1047
255
      advance();
1048
255
    }
1049
3.44k
    else
1050
3.44k
      break;
1051
3.96k
  }
1052
1053
3.47k
  ASTPointer<Block> block;
1054
3.47k
  nodeFactory.markEndPosition();
1055
3.47k
  if (m_scanner->currentToken() != Token::Semicolon)
1056
1.00k
  {
1057
1.00k
    block = parseBlock();
1058
1.00k
    nodeFactory.setEndPositionFromNode(block);
1059
1.00k
  }
1060
2.47k
  else
1061
2.47k
    advance(); // just consume the ';'
1062
1063
3.47k
  return nodeFactory.createNode<ModifierDefinition>(name, nameLocation, documentation, parameters, isVirtual, overrides, block);
1064
3.47k
}
1065
1066
std::pair<ASTPointer<ASTString>, SourceLocation> Parser::expectIdentifierWithLocation()
1067
200k
{
1068
200k
  SourceLocation nameLocation = currentLocation();
1069
200k
  ASTPointer<ASTString> name = expectIdentifierToken();
1070
1071
200k
  return {std::move(name), std::move(nameLocation)};
1072
200k
}
1073
1074
ASTPointer<EventDefinition> Parser::parseEventDefinition()
1075
3.88k
{
1076
3.88k
  RecursionGuard recursionGuard(*this);
1077
3.88k
  ASTNodeFactory nodeFactory(*this);
1078
3.88k
  ASTPointer<StructuredDocumentation> documentation = parseStructuredDocumentation();
1079
1080
3.88k
  expectToken(Token::Event);
1081
3.88k
  auto [name, nameLocation] = expectIdentifierWithLocation();
1082
1083
3.88k
  VarDeclParserOptions options;
1084
3.88k
  options.allowIndexed = true;
1085
3.88k
  ASTPointer<ParameterList> parameters = parseParameterList(options);
1086
1087
3.88k
  bool anonymous = false;
1088
3.88k
  if (m_scanner->currentToken() == Token::Anonymous)
1089
106
  {
1090
106
    anonymous = true;
1091
106
    advance();
1092
106
  }
1093
3.88k
  nodeFactory.markEndPosition();
1094
3.88k
  expectToken(Token::Semicolon);
1095
3.88k
  return nodeFactory.createNode<EventDefinition>(name, nameLocation, documentation, parameters, anonymous);
1096
3.88k
}
1097
1098
ASTPointer<ErrorDefinition> Parser::parseErrorDefinition()
1099
1.12k
{
1100
1.12k
  RecursionGuard recursionGuard(*this);
1101
1.12k
  ASTNodeFactory nodeFactory(*this);
1102
1.12k
  ASTPointer<StructuredDocumentation> documentation = parseStructuredDocumentation();
1103
1104
1.12k
  solAssert(*expectIdentifierToken() == "error", "");
1105
1.12k
  auto&& [name, nameLocation] = expectIdentifierWithLocation();
1106
1107
1.12k
  ASTPointer<ParameterList> parameters = parseParameterList({});
1108
1.12k
  nodeFactory.markEndPosition();
1109
1.12k
  expectToken(Token::Semicolon);
1110
1.12k
  return nodeFactory.createNode<ErrorDefinition>(name, std::move(nameLocation), documentation, parameters);
1111
1.12k
}
1112
1113
ASTPointer<UsingForDirective> Parser::parseUsingDirective()
1114
913
{
1115
913
  RecursionGuard recursionGuard(*this);
1116
913
  ASTNodeFactory nodeFactory(*this);
1117
1118
913
  expectToken(Token::Using);
1119
1120
913
  std::vector<ASTPointer<IdentifierPath>> functions;
1121
913
  std::vector<std::optional<Token>> operators;
1122
913
  bool const usesBraces = m_scanner->currentToken() == Token::LBrace;
1123
913
  if (usesBraces)
1124
465
  {
1125
465
    do
1126
962
    {
1127
962
      advance();
1128
962
      functions.emplace_back(parseIdentifierPath());
1129
962
      if (m_scanner->currentToken() == Token::As)
1130
462
      {
1131
462
        advance();
1132
462
        Token operator_ = m_scanner->currentToken();
1133
462
        if (!util::contains(userDefinableOperators, operator_))
1134
114
        {
1135
114
          std::string operatorName;
1136
114
          if (!m_scanner->currentLiteral().empty())
1137
80
            operatorName = m_scanner->currentLiteral();
1138
34
          else if (char const* tokenString = TokenTraits::toString(operator_))
1139
11
            operatorName = std::string(tokenString);
1140
1141
114
          parserError(
1142
114
            4403_error,
1143
114
            fmt::format(
1144
114
              "Not a user-definable operator: {}. Only the following operators can be user-defined: {}",
1145
114
              operatorName,
1146
1.71k
              util::joinHumanReadable(userDefinableOperators | ranges::views::transform([](Token _t) { return std::string{TokenTraits::toString(_t)}; }))
1147
114
            )
1148
114
          );
1149
114
        }
1150
462
        operators.emplace_back(operator_);
1151
462
        advance();
1152
462
      }
1153
500
      else
1154
500
        operators.emplace_back(std::nullopt);
1155
962
    }
1156
962
    while (m_scanner->currentToken() == Token::Comma);
1157
465
    expectToken(Token::RBrace);
1158
465
  }
1159
448
  else
1160
448
  {
1161
448
    functions.emplace_back(parseIdentifierPath());
1162
448
    operators.emplace_back(std::nullopt);
1163
448
  }
1164
1165
913
  ASTPointer<TypeName> typeName;
1166
913
  expectToken(Token::For);
1167
913
  if (m_scanner->currentToken() == Token::Mul)
1168
152
    advance();
1169
761
  else
1170
761
    typeName = parseTypeName();
1171
913
  bool global = false;
1172
913
  if (m_scanner->currentToken() == Token::Identifier && currentLiteral() == "global")
1173
287
  {
1174
287
    global = true;
1175
287
    advance();
1176
287
  }
1177
913
  nodeFactory.markEndPosition();
1178
913
  expectToken(Token::Semicolon);
1179
913
  return nodeFactory.createNode<UsingForDirective>(std::move(functions), std::move(operators), usesBraces, typeName, global);
1180
913
}
1181
1182
ASTPointer<ModifierInvocation> Parser::parseModifierInvocation()
1183
4.21k
{
1184
4.21k
  RecursionGuard recursionGuard(*this);
1185
4.21k
  ASTNodeFactory nodeFactory(*this);
1186
4.21k
  ASTPointer<IdentifierPath> name(parseIdentifierPath());
1187
4.21k
  std::unique_ptr<std::vector<ASTPointer<Expression>>> arguments;
1188
4.21k
  if (m_scanner->currentToken() == Token::LParen)
1189
1.32k
  {
1190
1.32k
    advance();
1191
1.32k
    arguments = std::make_unique<std::vector<ASTPointer<Expression>>>(parseFunctionCallListArguments());
1192
1.32k
    nodeFactory.markEndPosition();
1193
1.32k
    expectToken(Token::RParen);
1194
1.32k
  }
1195
2.89k
  else
1196
2.89k
    nodeFactory.setEndPositionFromNode(name);
1197
4.21k
  return nodeFactory.createNode<ModifierInvocation>(name, std::move(arguments));
1198
4.21k
}
1199
1200
ASTPointer<Identifier> Parser::parseIdentifier()
1201
32.5k
{
1202
32.5k
  RecursionGuard recursionGuard(*this);
1203
32.5k
  ASTNodeFactory nodeFactory(*this);
1204
32.5k
  nodeFactory.markEndPosition();
1205
32.5k
  return nodeFactory.createNode<Identifier>(expectIdentifierToken());
1206
32.5k
}
1207
1208
ASTPointer<Identifier> Parser::parseIdentifierOrAddress()
1209
40.4k
{
1210
40.4k
  RecursionGuard recursionGuard(*this);
1211
40.4k
  ASTNodeFactory nodeFactory(*this);
1212
40.4k
  nodeFactory.markEndPosition();
1213
40.4k
  return nodeFactory.createNode<Identifier>(expectIdentifierTokenOrAddress());
1214
40.4k
}
1215
1216
ASTPointer<UserDefinedTypeName> Parser::parseUserDefinedTypeName()
1217
26.2k
{
1218
26.2k
  ASTNodeFactory nodeFactory(*this);
1219
26.2k
  ASTPointer<IdentifierPath> identifierPath = parseIdentifierPath();
1220
26.2k
  nodeFactory.setEndPositionFromNode(identifierPath);
1221
26.2k
  return nodeFactory.createNode<UserDefinedTypeName>(identifierPath);
1222
26.2k
}
1223
1224
ASTPointer<UserDefinedValueTypeDefinition> Parser::parseUserDefinedValueTypeDefinition()
1225
780
{
1226
780
  ASTNodeFactory nodeFactory(*this);
1227
780
  expectToken(Token::Type);
1228
780
  auto&& [name, nameLocation] = expectIdentifierWithLocation();
1229
780
  expectToken(Token::Is);
1230
780
  ASTPointer<TypeName> typeName = parseTypeName();
1231
780
  nodeFactory.markEndPosition();
1232
780
  expectToken(Token::Semicolon);
1233
780
  return nodeFactory.createNode<UserDefinedValueTypeDefinition>(
1234
780
    name,
1235
780
    std::move(nameLocation),
1236
780
    typeName
1237
780
  );
1238
780
}
1239
1240
ASTPointer<IdentifierPath> Parser::parseIdentifierPath()
1241
39.6k
{
1242
39.6k
  RecursionGuard recursionGuard(*this);
1243
39.6k
  ASTNodeFactory nodeFactory(*this);
1244
39.6k
  nodeFactory.markEndPosition();
1245
1246
39.6k
  auto [name, nameLocation] = expectIdentifierWithLocation();
1247
1248
39.6k
  std::vector<ASTString> identifierPath{*name};
1249
39.6k
  std::vector<SourceLocation> identifierPathLocations{nameLocation};
1250
1251
41.9k
  while (m_scanner->currentToken() == Token::Period)
1252
2.28k
  {
1253
2.28k
    advance();
1254
1255
2.28k
    nodeFactory.markEndPosition();
1256
1257
2.28k
    tie(name, nameLocation) = expectIdentifierWithLocation();
1258
1259
2.28k
    identifierPath.push_back(*name);
1260
2.28k
    identifierPathLocations.push_back(nameLocation);
1261
2.28k
  }
1262
39.6k
  return nodeFactory.createNode<IdentifierPath>(identifierPath, identifierPathLocations);
1263
39.6k
}
1264
1265
ASTPointer<TypeName> Parser::parseTypeNameSuffix(ASTPointer<TypeName> type, ASTNodeFactory& nodeFactory)
1266
101k
{
1267
101k
  RecursionGuard recursionGuard(*this);
1268
125k
  while (m_scanner->currentToken() == Token::LBrack)
1269
24.5k
  {
1270
24.5k
    advance();
1271
24.5k
    ASTPointer<Expression> length;
1272
24.5k
    if (m_scanner->currentToken() != Token::RBrack)
1273
9.69k
      length = parseExpression();
1274
24.5k
    nodeFactory.markEndPosition();
1275
24.5k
    expectToken(Token::RBrack);
1276
24.5k
    type = nodeFactory.createNode<ArrayTypeName>(type, length);
1277
24.5k
  }
1278
101k
  return type;
1279
101k
}
1280
1281
ASTPointer<TypeName> Parser::parseTypeName()
1282
101k
{
1283
101k
  RecursionGuard recursionGuard(*this);
1284
101k
  ASTNodeFactory nodeFactory(*this);
1285
101k
  ASTPointer<TypeName> type;
1286
101k
  Token token = m_scanner->currentToken();
1287
101k
  if (TokenTraits::isElementaryTypeName(token))
1288
72.6k
  {
1289
72.6k
    unsigned firstSize;
1290
72.6k
    unsigned secondSize;
1291
72.6k
    std::tie(firstSize, secondSize) = m_scanner->currentTokenInfo();
1292
72.6k
    ElementaryTypeNameToken elemTypeName(token, firstSize, secondSize);
1293
72.6k
    ASTNodeFactory nodeFactory(*this);
1294
72.6k
    nodeFactory.markEndPosition();
1295
72.6k
    advance();
1296
72.6k
    auto stateMutability = elemTypeName.token() == Token::Address
1297
72.6k
      ? std::optional<StateMutability>{StateMutability::NonPayable}
1298
72.6k
      : std::nullopt;
1299
72.6k
    if (TokenTraits::isStateMutabilitySpecifier(m_scanner->currentToken()))
1300
490
    {
1301
490
      if (elemTypeName.token() == Token::Address)
1302
485
      {
1303
485
        nodeFactory.markEndPosition();
1304
485
        stateMutability = parseStateMutability();
1305
485
      }
1306
5
      else
1307
5
      {
1308
5
        parserError(9106_error, "State mutability can only be specified for address types.");
1309
5
        advance();
1310
5
      }
1311
490
    }
1312
72.6k
    type = nodeFactory.createNode<ElementaryTypeName>(elemTypeName, stateMutability);
1313
72.6k
  }
1314
28.8k
  else if (token == Token::Function)
1315
1.39k
    type = parseFunctionType();
1316
27.4k
  else if (token == Token::Mapping)
1317
1.25k
    type = parseMapping();
1318
26.1k
  else if (token == Token::Identifier)
1319
26.1k
    type = parseUserDefinedTypeName();
1320
83
  else
1321
83
    fatalParserError(3546_error, "Expected type name");
1322
1323
101k
  solAssert(type, "");
1324
  // Parse "[...]" postfixes for arrays.
1325
101k
  type = parseTypeNameSuffix(type, nodeFactory);
1326
1327
101k
  return type;
1328
101k
}
1329
1330
ASTPointer<FunctionTypeName> Parser::parseFunctionType()
1331
1.39k
{
1332
1.39k
  solAssert(!m_experimentalSolidityEnabledInCurrentSourceUnit);
1333
1.39k
  RecursionGuard recursionGuard(*this);
1334
1.39k
  ASTNodeFactory nodeFactory(*this);
1335
1.39k
  expectToken(Token::Function);
1336
1.39k
  FunctionHeaderParserResult header = parseFunctionHeader(true);
1337
1.39k
  solAssert(!header.experimentalReturnExpression);
1338
1.39k
  return nodeFactory.createNode<FunctionTypeName>(
1339
1.39k
    header.parameters,
1340
1.39k
    header.returnParameters,
1341
1.39k
    header.visibility,
1342
1.39k
    header.stateMutability
1343
1.39k
  );
1344
1.39k
}
1345
1346
ASTPointer<Mapping> Parser::parseMapping()
1347
1.25k
{
1348
1.25k
  RecursionGuard recursionGuard(*this);
1349
1.25k
  ASTNodeFactory nodeFactory(*this);
1350
1.25k
  expectToken(Token::Mapping);
1351
1.25k
  expectToken(Token::LParen);
1352
1.25k
  ASTPointer<TypeName> keyType;
1353
1.25k
  Token token = m_scanner->currentToken();
1354
1.25k
  unsigned firstSize;
1355
1.25k
  unsigned secondSize;
1356
1.25k
  std::tie(firstSize, secondSize) = m_scanner->currentTokenInfo();
1357
1.25k
  if (token == Token::Identifier)
1358
95
    keyType = parseUserDefinedTypeName();
1359
1.16k
  else if (TokenTraits::isElementaryTypeName(token))
1360
1.15k
  {
1361
1.15k
    keyType = ASTNodeFactory(*this).createNode<ElementaryTypeName>(
1362
1.15k
      ElementaryTypeNameToken{token, firstSize, secondSize}
1363
1.15k
    );
1364
1.15k
    advance();
1365
1.15k
  }
1366
8
  else
1367
8
    fatalParserError(1005_error, "Expected elementary type name or identifier for mapping key type");
1368
1.25k
  ASTPointer<ASTString> keyName = std::make_shared<ASTString>("");
1369
1.25k
  SourceLocation keyNameLocation{};
1370
1.25k
  if (m_scanner->currentToken() == Token::Identifier)
1371
214
    tie(keyName, keyNameLocation) = expectIdentifierWithLocation();
1372
1.25k
  expectToken(Token::DoubleArrow);
1373
1.25k
  ASTPointer<TypeName> valueType = parseTypeName();
1374
1.25k
  ASTPointer<ASTString> valueName = std::make_shared<ASTString>("");
1375
1.25k
  SourceLocation valueNameLocation{};
1376
1.25k
  if (m_scanner->currentToken() == Token::Identifier)
1377
152
    tie(valueName, valueNameLocation) = expectIdentifierWithLocation();
1378
1.25k
  nodeFactory.markEndPosition();
1379
1.25k
  expectToken(Token::RParen);
1380
1.25k
  return nodeFactory.createNode<Mapping>(keyType, keyName, keyNameLocation, valueType, valueName, valueNameLocation);
1381
1.25k
}
1382
1383
ASTPointer<ParameterList> Parser::parseParameterList(
1384
  VarDeclParserOptions const& _options,
1385
  bool _allowEmpty
1386
)
1387
49.8k
{
1388
49.8k
  RecursionGuard recursionGuard(*this);
1389
49.8k
  ASTNodeFactory nodeFactory(*this);
1390
49.8k
  std::vector<ASTPointer<VariableDeclaration>> parameters;
1391
49.8k
  VarDeclParserOptions options(_options);
1392
49.8k
  options.allowEmptyName = true;
1393
49.8k
  if (m_experimentalSolidityEnabledInCurrentSourceUnit && m_scanner->currentToken() == Token::Identifier)
1394
24
  {
1395
    // Parses unary parameter lists without parentheses. TODO: is this a good idea in all cases? Including arguments?
1396
24
    parameters = {parsePostfixVariableDeclaration()};
1397
24
    nodeFactory.setEndPositionFromNode(parameters.front());
1398
24
    return nodeFactory.createNode<ParameterList>(parameters);
1399
24
  }
1400
49.8k
  expectToken(Token::LParen);
1401
49.8k
  auto parseSingleVariableDeclaration = [&]() {
1402
37.9k
    if (m_experimentalSolidityEnabledInCurrentSourceUnit)
1403
214
      return parsePostfixVariableDeclaration();
1404
37.7k
    else
1405
37.7k
      return parseVariableDeclaration(options);
1406
37.9k
  };
1407
49.8k
  if (!_allowEmpty || m_scanner->currentToken() != Token::RParen)
1408
26.5k
  {
1409
26.5k
    parameters.push_back(parseSingleVariableDeclaration());
1410
38.0k
    while (m_scanner->currentToken() != Token::RParen)
1411
11.5k
    {
1412
11.5k
      if (m_scanner->currentToken() == Token::Comma && m_scanner->peekNextToken() == Token::RParen)
1413
2
        fatalParserError(7591_error, "Unexpected trailing comma in parameter list.");
1414
11.5k
      expectToken(Token::Comma);
1415
11.5k
      parameters.push_back(parseSingleVariableDeclaration());
1416
11.5k
    }
1417
26.5k
  }
1418
49.8k
  nodeFactory.markEndPosition();
1419
49.8k
  advance();
1420
49.8k
  return nodeFactory.createNode<ParameterList>(parameters);
1421
49.8k
}
1422
1423
ASTPointer<Block> Parser::parseBlock(bool _allowUnchecked, ASTPointer<ASTString> const& _docString)
1424
32.2k
{
1425
32.2k
  RecursionGuard recursionGuard(*this);
1426
32.2k
  ASTNodeFactory nodeFactory(*this);
1427
32.2k
  bool const unchecked = m_scanner->currentToken() == Token::Unchecked;
1428
32.2k
  if (unchecked)
1429
196
  {
1430
196
    if (!_allowUnchecked)
1431
1
      parserError(5296_error, "\"unchecked\" blocks can only be used inside regular blocks.");
1432
196
    advance();
1433
196
  }
1434
32.2k
  expectToken(Token::LBrace);
1435
32.2k
  std::vector<ASTPointer<Statement>> statements;
1436
149k
  while (m_scanner->currentToken() != Token::RBrace)
1437
117k
    statements.push_back(parseStatement(true));
1438
32.2k
  nodeFactory.markEndPosition();
1439
32.2k
  expectToken(Token::RBrace);
1440
32.2k
  return nodeFactory.createNode<Block>(_docString, unchecked, statements);
1441
32.2k
}
1442
1443
ASTPointer<Statement> Parser::parseStatement(bool _allowUnchecked)
1444
160k
{
1445
160k
  RecursionGuard recursionGuard(*this);
1446
160k
  ASTPointer<ASTString> docString;
1447
160k
  ASTPointer<Statement> statement;
1448
160k
  if (!m_scanner->currentCommentLiteral().empty())
1449
550
    docString = std::make_shared<ASTString>(m_scanner->currentCommentLiteral());
1450
160k
  switch (m_scanner->currentToken())
1451
160k
  {
1452
38.9k
  case Token::If:
1453
38.9k
    return parseIfStatement(docString);
1454
275
  case Token::While:
1455
275
    return parseWhileStatement(docString);
1456
94
  case Token::Do:
1457
94
    return parseDoWhileStatement(docString);
1458
3.38k
  case Token::For:
1459
3.38k
    return parseForStatement(docString);
1460
195
  case Token::Unchecked:
1461
1.92k
  case Token::LBrace:
1462
1.92k
    return parseBlock(_allowUnchecked, docString);
1463
105
  case Token::Continue:
1464
105
    statement = ASTNodeFactory(*this).createNode<Continue>(docString);
1465
105
    advance();
1466
105
    break;
1467
123
  case Token::Break:
1468
123
    statement = ASTNodeFactory(*this).createNode<Break>(docString);
1469
123
    advance();
1470
123
    break;
1471
46.9k
  case Token::Return:
1472
46.9k
  {
1473
46.9k
    ASTNodeFactory nodeFactory(*this);
1474
46.9k
    ASTPointer<Expression> expression;
1475
46.9k
    if (advance() != Token::Semicolon)
1476
46.5k
      {
1477
46.5k
        expression = parseExpression();
1478
46.5k
        nodeFactory.setEndPositionFromNode(expression);
1479
46.5k
      }
1480
46.9k
    statement = nodeFactory.createNode<Return>(docString, expression);
1481
46.9k
      break;
1482
195
  }
1483
4
  case Token::Throw:
1484
4
  {
1485
4
    statement = ASTNodeFactory(*this).createNode<Throw>(docString);
1486
4
    advance();
1487
4
    break;
1488
195
  }
1489
505
  case Token::Try:
1490
505
    return parseTryStatement(docString);
1491
3.92k
  case Token::Assembly:
1492
3.92k
    return parseInlineAssembly(docString);
1493
1.58k
  case Token::Emit:
1494
1.58k
    statement = parseEmitStatement(docString);
1495
1.58k
    break;
1496
48.6k
  case Token::Identifier:
1497
48.6k
    if (m_scanner->currentLiteral() == "revert" && m_scanner->peekNextToken() == Token::Identifier)
1498
90
      statement = parseRevertStatement(docString);
1499
48.5k
    else if (m_insideModifier && m_scanner->currentLiteral() == "_")
1500
1.00k
    {
1501
1.00k
      statement = ASTNodeFactory(*this).createNode<PlaceholderStatement>(docString);
1502
1.00k
      advance();
1503
1.00k
    }
1504
47.5k
    else
1505
47.5k
      statement = parseSimpleStatement(docString);
1506
48.6k
    break;
1507
14.2k
  default:
1508
14.2k
    statement = parseSimpleStatement(docString);
1509
14.2k
    break;
1510
160k
  }
1511
111k
  expectToken(Token::Semicolon);
1512
111k
  return statement;
1513
160k
}
1514
1515
ASTPointer<InlineAssembly> Parser::parseInlineAssembly(ASTPointer<ASTString> const& _docString)
1516
3.92k
{
1517
3.92k
  RecursionGuard recursionGuard(*this);
1518
3.92k
  SourceLocation location = currentLocation();
1519
1520
3.92k
  expectToken(Token::Assembly);
1521
3.92k
  yul::Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion);
1522
3.92k
  if (m_scanner->currentToken() == Token::StringLiteral)
1523
19
  {
1524
19
    if (m_scanner->currentLiteral() != "evmasm")
1525
3
      fatalParserError(4531_error, "Only \"evmasm\" supported.");
1526
    // This can be used in the future to set the dialect.
1527
19
    advance();
1528
19
  }
1529
1530
3.92k
  ASTPointer<std::vector<ASTPointer<ASTString>>> flags;
1531
3.92k
  if (m_scanner->currentToken() == Token::LParen)
1532
51
  {
1533
51
    flags = std::make_shared<std::vector<ASTPointer<ASTString>>>();
1534
51
    do
1535
131
    {
1536
131
      advance();
1537
131
      expectToken(Token::StringLiteral, false);
1538
131
      flags->emplace_back(std::make_shared<ASTString>(m_scanner->currentLiteral()));
1539
131
      advance();
1540
131
    }
1541
131
    while (m_scanner->currentToken() == Token::Comma);
1542
51
    expectToken(Token::RParen);
1543
51
  }
1544
1545
3.92k
  yul::Parser asmParser(m_errorReporter, dialect);
1546
3.92k
  std::shared_ptr<yul::AST> ast = asmParser.parseInline(m_scanner);
1547
3.92k
  if (ast == nullptr)
1548
350
    solThrow(FatalError, "Failed to parse inline assembly.");
1549
1550
3.92k
  location.end = nativeLocationOf(ast->root()).end;
1551
3.92k
  return std::make_shared<InlineAssembly>(nextID(), location, _docString, dialect, std::move(flags), ast);
1552
3.92k
}
1553
1554
ASTPointer<IfStatement> Parser::parseIfStatement(ASTPointer<ASTString> const& _docString)
1555
38.9k
{
1556
38.9k
  RecursionGuard recursionGuard(*this);
1557
38.9k
  ASTNodeFactory nodeFactory(*this);
1558
38.9k
  expectToken(Token::If);
1559
38.9k
  expectToken(Token::LParen);
1560
38.9k
  ASTPointer<Expression> condition = parseExpression();
1561
38.9k
  expectToken(Token::RParen);
1562
38.9k
  ASTPointer<Statement> trueBody = parseStatement();
1563
38.9k
  ASTPointer<Statement> falseBody;
1564
38.9k
  if (m_scanner->currentToken() == Token::Else)
1565
393
  {
1566
393
    advance();
1567
393
    falseBody = parseStatement();
1568
393
    nodeFactory.setEndPositionFromNode(falseBody);
1569
393
  }
1570
38.6k
  else
1571
38.6k
    nodeFactory.setEndPositionFromNode(trueBody);
1572
38.9k
  return nodeFactory.createNode<IfStatement>(_docString, condition, trueBody, falseBody);
1573
38.9k
}
1574
1575
ASTPointer<TryStatement> Parser::parseTryStatement(ASTPointer<ASTString> const& _docString)
1576
505
{
1577
505
  RecursionGuard recursionGuard(*this);
1578
505
  ASTNodeFactory nodeFactory(*this);
1579
505
  expectToken(Token::Try);
1580
505
  ASTPointer<Expression> externalCall = parseExpression();
1581
505
  std::vector<ASTPointer<TryCatchClause>> clauses;
1582
1583
505
  ASTNodeFactory successClauseFactory(*this);
1584
505
  ASTPointer<ParameterList> returnsParameters;
1585
505
  if (m_scanner->currentToken() == Token::Returns)
1586
115
  {
1587
115
    advance();
1588
115
    VarDeclParserOptions options;
1589
115
    options.allowEmptyName = true;
1590
115
    options.allowLocationSpecifier = true;
1591
115
    returnsParameters = parseParameterList(options, false);
1592
115
  }
1593
505
  ASTPointer<Block> successBlock = parseBlock();
1594
505
  successClauseFactory.setEndPositionFromNode(successBlock);
1595
505
  clauses.emplace_back(successClauseFactory.createNode<TryCatchClause>(
1596
505
    std::make_shared<ASTString>(), returnsParameters, successBlock
1597
505
  ));
1598
1599
505
  do
1600
781
  {
1601
781
    clauses.emplace_back(parseCatchClause());
1602
781
  }
1603
781
  while (m_scanner->currentToken() == Token::Catch);
1604
505
  nodeFactory.setEndPositionFromNode(clauses.back());
1605
505
  return nodeFactory.createNode<TryStatement>(
1606
505
    _docString, externalCall, clauses
1607
505
  );
1608
505
}
1609
1610
ASTPointer<TryCatchClause> Parser::parseCatchClause()
1611
687
{
1612
687
  RecursionGuard recursionGuard(*this);
1613
687
  ASTNodeFactory nodeFactory(*this);
1614
687
  expectToken(Token::Catch);
1615
687
  ASTPointer<ASTString> errorName = std::make_shared<std::string>();
1616
687
  ASTPointer<ParameterList> errorParameters;
1617
687
  if (m_scanner->currentToken() != Token::LBrace)
1618
399
  {
1619
399
    if (m_scanner->currentToken() == Token::Identifier)
1620
274
      errorName = expectIdentifierToken();
1621
399
    VarDeclParserOptions options;
1622
399
    options.allowEmptyName = true;
1623
399
    options.allowLocationSpecifier = true;
1624
399
    errorParameters = parseParameterList(options, !errorName->empty());
1625
399
  }
1626
687
  ASTPointer<Block> block = parseBlock();
1627
687
  nodeFactory.setEndPositionFromNode(block);
1628
687
  return nodeFactory.createNode<TryCatchClause>(errorName, errorParameters, block);
1629
687
}
1630
1631
ASTPointer<WhileStatement> Parser::parseWhileStatement(ASTPointer<ASTString> const& _docString)
1632
275
{
1633
275
  RecursionGuard recursionGuard(*this);
1634
275
  ASTNodeFactory nodeFactory(*this);
1635
275
  expectToken(Token::While);
1636
275
  expectToken(Token::LParen);
1637
275
  ASTPointer<Expression> condition = parseExpression();
1638
275
  expectToken(Token::RParen);
1639
275
  ASTPointer<Statement> body = parseStatement();
1640
275
  nodeFactory.setEndPositionFromNode(body);
1641
275
  return nodeFactory.createNode<WhileStatement>(_docString, condition, body, false);
1642
275
}
1643
1644
ASTPointer<WhileStatement> Parser::parseDoWhileStatement(ASTPointer<ASTString> const& _docString)
1645
94
{
1646
94
  RecursionGuard recursionGuard(*this);
1647
94
  ASTNodeFactory nodeFactory(*this);
1648
94
  expectToken(Token::Do);
1649
94
  ASTPointer<Statement> body = parseStatement();
1650
94
  expectToken(Token::While);
1651
94
  expectToken(Token::LParen);
1652
94
  ASTPointer<Expression> condition = parseExpression();
1653
94
  expectToken(Token::RParen);
1654
94
  nodeFactory.markEndPosition();
1655
94
  expectToken(Token::Semicolon);
1656
94
  return nodeFactory.createNode<WhileStatement>(_docString, condition, body, true);
1657
94
}
1658
1659
1660
ASTPointer<ForStatement> Parser::parseForStatement(ASTPointer<ASTString> const& _docString)
1661
3.38k
{
1662
3.38k
  RecursionGuard recursionGuard(*this);
1663
3.38k
  ASTNodeFactory nodeFactory(*this);
1664
3.38k
  ASTPointer<Statement> initExpression;
1665
3.38k
  ASTPointer<Expression> conditionExpression;
1666
3.38k
  ASTPointer<ExpressionStatement> loopExpression;
1667
3.38k
  expectToken(Token::For);
1668
3.38k
  expectToken(Token::LParen);
1669
1670
  // TODO: Maybe here have some predicate like peekExpression() instead of checking for semicolon and RParen?
1671
3.38k
  if (m_scanner->currentToken() != Token::Semicolon)
1672
3.18k
    initExpression = parseSimpleStatement(ASTPointer<ASTString>());
1673
3.38k
  expectToken(Token::Semicolon);
1674
1675
3.38k
  if (m_scanner->currentToken() != Token::Semicolon)
1676
3.20k
    conditionExpression = parseExpression();
1677
3.38k
  expectToken(Token::Semicolon);
1678
1679
3.38k
  if (m_scanner->currentToken() != Token::RParen)
1680
3.16k
    loopExpression = parseExpressionStatement(ASTPointer<ASTString>());
1681
3.38k
  expectToken(Token::RParen);
1682
1683
3.38k
  ASTPointer<Statement> body = parseStatement();
1684
3.38k
  nodeFactory.setEndPositionFromNode(body);
1685
3.38k
  return nodeFactory.createNode<ForStatement>(
1686
3.38k
    _docString,
1687
3.38k
    initExpression,
1688
3.38k
    conditionExpression,
1689
3.38k
    loopExpression,
1690
3.38k
    body
1691
3.38k
  );
1692
3.38k
}
1693
1694
ASTPointer<EmitStatement> Parser::parseEmitStatement(ASTPointer<ASTString> const& _docString)
1695
1.58k
{
1696
1.58k
  expectToken(Token::Emit, false);
1697
1698
1.58k
  ASTNodeFactory nodeFactory(*this);
1699
1.58k
  advance();
1700
1.58k
  ASTNodeFactory eventCallNodeFactory(*this);
1701
1702
1.58k
  if (m_scanner->currentToken() != Token::Identifier)
1703
1
    fatalParserError(5620_error, "Expected event name or path.");
1704
1705
1.58k
  IndexAccessedPath iap;
1706
1.65k
  while (true)
1707
1.64k
  {
1708
1.64k
    iap.path.push_back(parseIdentifier());
1709
1.64k
    if (m_scanner->currentToken() != Token::Period)
1710
1.58k
      break;
1711
65
    advance();
1712
65
  }
1713
1714
1.58k
  auto eventName = expressionFromIndexAccessStructure(iap);
1715
1.58k
  expectToken(Token::LParen);
1716
1717
1.58k
  auto functionCallArguments = parseFunctionCallArguments();
1718
1.58k
  eventCallNodeFactory.markEndPosition();
1719
1.58k
  nodeFactory.markEndPosition();
1720
1.58k
  expectToken(Token::RParen);
1721
1.58k
  auto eventCall = eventCallNodeFactory.createNode<FunctionCall>(
1722
1.58k
    eventName,
1723
1.58k
    functionCallArguments.arguments,
1724
1.58k
    functionCallArguments.parameterNames,
1725
1.58k
    functionCallArguments.parameterNameLocations
1726
1.58k
  );
1727
1.58k
  return nodeFactory.createNode<EmitStatement>(_docString, eventCall);
1728
1.58k
}
1729
1730
ASTPointer<RevertStatement> Parser::parseRevertStatement(ASTPointer<ASTString> const& _docString)
1731
90
{
1732
90
  ASTNodeFactory nodeFactory(*this);
1733
90
  solAssert(*expectIdentifierToken() == "revert", "");
1734
1735
90
  ASTNodeFactory errorCallNodeFactory(*this);
1736
1737
90
  solAssert(m_scanner->currentToken() == Token::Identifier, "");
1738
1739
90
  IndexAccessedPath iap;
1740
127
  while (true)
1741
126
  {
1742
126
    iap.path.push_back(parseIdentifier());
1743
126
    if (m_scanner->currentToken() != Token::Period)
1744
89
      break;
1745
37
    advance();
1746
37
  }
1747
1748
90
  auto errorName = expressionFromIndexAccessStructure(iap);
1749
90
  expectToken(Token::LParen);
1750
1751
90
  auto functionCallArguments = parseFunctionCallArguments();
1752
90
  errorCallNodeFactory.markEndPosition();
1753
90
  nodeFactory.markEndPosition();
1754
90
  expectToken(Token::RParen);
1755
90
  auto errorCall = errorCallNodeFactory.createNode<FunctionCall>(
1756
90
    errorName,
1757
90
    functionCallArguments.arguments,
1758
90
    functionCallArguments.parameterNames,
1759
90
    functionCallArguments.parameterNameLocations
1760
90
  );
1761
90
  return nodeFactory.createNode<RevertStatement>(_docString, errorCall);
1762
90
}
1763
1764
ASTPointer<VariableDeclarationStatement> Parser::parsePostfixVariableDeclarationStatement(
1765
  ASTPointer<ASTString> const& _docString
1766
)
1767
28
{
1768
28
  RecursionGuard recursionGuard(*this);
1769
28
  ASTNodeFactory nodeFactory(*this);
1770
1771
28
  expectToken(Token::Let);
1772
1773
28
  std::vector<ASTPointer<VariableDeclaration>> variables;
1774
28
  variables.emplace_back(parsePostfixVariableDeclaration());
1775
28
  nodeFactory.setEndPositionFromNode(variables.back());
1776
1777
28
  ASTPointer<Expression> value;
1778
28
  if (m_scanner->currentToken() == Token::Assign)
1779
1
  {
1780
1
    advance();
1781
1
    value = parseExpression();
1782
1
    nodeFactory.setEndPositionFromNode(value);
1783
1
  }
1784
28
  return nodeFactory.createNode<VariableDeclarationStatement>(_docString, variables, value);
1785
28
}
1786
1787
ASTPointer<VariableDeclaration> Parser::parsePostfixVariableDeclaration()
1788
266
{
1789
266
  RecursionGuard recursionGuard(*this);
1790
266
  ASTNodeFactory nodeFactory(*this);
1791
1792
266
  ASTPointer<StructuredDocumentation> const documentation = parseStructuredDocumentation();
1793
1794
266
  nodeFactory.markEndPosition();
1795
266
  auto [identifier, nameLocation] = expectIdentifierWithLocation();
1796
1797
266
  ASTPointer<Expression> type;
1798
266
  if (m_scanner->currentToken() == Token::Colon)
1799
172
  {
1800
172
    advance();
1801
172
    type = parseBinaryExpression();
1802
172
    nodeFactory.setEndPositionFromNode(type);
1803
172
  }
1804
1805
266
  return nodeFactory.createNode<VariableDeclaration>(
1806
266
    nullptr,
1807
266
    identifier,
1808
266
    nameLocation,
1809
266
    nullptr,
1810
266
    Visibility::Default,
1811
266
    documentation,
1812
266
    false,
1813
266
    VariableDeclaration::Mutability::Mutable,
1814
266
    nullptr,
1815
266
    VariableDeclaration::Location::Unspecified,
1816
266
    type
1817
266
  );
1818
266
}
1819
1820
ASTPointer<TypeClassDefinition> Parser::parseTypeClassDefinition()
1821
61
{
1822
61
  solAssert(m_experimentalSolidityEnabledInCurrentSourceUnit);
1823
61
  RecursionGuard recursionGuard(*this);
1824
61
  ASTNodeFactory nodeFactory(*this);
1825
1826
61
  std::vector<ASTPointer<ASTNode>> subNodes;
1827
1828
61
  ASTPointer<StructuredDocumentation> const documentation = parseStructuredDocumentation();
1829
1830
61
  expectToken(Token::Class);
1831
  // TODO: parseTypeVariable()? parseTypeVariableDeclaration()?
1832
61
  ASTPointer<VariableDeclaration> typeVariable;
1833
61
  {
1834
61
    ASTNodeFactory nodeFactory(*this);
1835
61
    nodeFactory.markEndPosition();
1836
61
    auto [identifier, nameLocation] = expectIdentifierWithLocation();
1837
61
    typeVariable = nodeFactory.createNode<VariableDeclaration>(
1838
61
      nullptr,
1839
61
      identifier,
1840
61
      nameLocation,
1841
61
      nullptr,
1842
61
      Visibility::Default,
1843
61
      nullptr
1844
61
    );
1845
61
  }
1846
61
  expectToken(Token::Colon);
1847
61
  auto [name, nameLocation] = expectIdentifierWithLocation();
1848
61
  expectToken(Token::LBrace);
1849
97
  while (true)
1850
84
  {
1851
84
    Token currentTokenValue = m_scanner->currentToken();
1852
84
    if (currentTokenValue == Token::RBrace)
1853
48
      break;
1854
36
    expectToken(Token::Function, false);
1855
36
    subNodes.push_back(parseFunctionDefinition(false, false));
1856
36
  }
1857
61
  nodeFactory.markEndPosition();
1858
61
  expectToken(Token::RBrace);
1859
1860
61
  return nodeFactory.createNode<TypeClassDefinition>(
1861
61
    typeVariable,
1862
61
    name,
1863
61
    nameLocation,
1864
61
    documentation,
1865
61
    subNodes
1866
61
  );
1867
61
}
1868
1869
ASTPointer<TypeClassName> Parser::parseTypeClassName()
1870
55
{
1871
55
  RecursionGuard recursionGuard(*this);
1872
55
  ASTNodeFactory nodeFactory(*this);
1873
55
  std::variant<Token, ASTPointer<IdentifierPath>> name;
1874
55
  if (TokenTraits::isBuiltinTypeClassName(m_scanner->currentToken()))
1875
7
  {
1876
7
    nodeFactory.markEndPosition();
1877
7
    name = m_scanner->currentToken();
1878
7
    advance();
1879
7
  }
1880
48
  else
1881
48
  {
1882
48
    auto identifierPath = parseIdentifierPath();
1883
48
    name = identifierPath;
1884
48
    nodeFactory.setEndPositionFromNode(identifierPath);
1885
48
  }
1886
55
  return nodeFactory.createNode<TypeClassName>(name);
1887
55
}
1888
1889
ASTPointer<TypeClassInstantiation> Parser::parseTypeClassInstantiation()
1890
59
{
1891
59
  solAssert(m_experimentalSolidityEnabledInCurrentSourceUnit);
1892
59
  RecursionGuard recursionGuard(*this);
1893
59
  ASTNodeFactory nodeFactory(*this);
1894
1895
59
  std::vector<ASTPointer<ASTNode>> subNodes;
1896
1897
59
  expectToken(Token::Instantiation);
1898
  // TODO: parseTypeConstructor()
1899
59
  ASTPointer<TypeName> typeConstructor = parseTypeName();
1900
59
  ASTPointer<ParameterList> argumentSorts;
1901
59
  if (m_scanner->currentToken() == Token::LParen)
1902
9
  {
1903
9
    argumentSorts = parseParameterList();
1904
9
  }
1905
59
  expectToken(Token::Colon);
1906
59
  ASTPointer<TypeClassName> typeClassName = parseTypeClassName();
1907
59
  expectToken(Token::LBrace);
1908
144
  while (true)
1909
123
  {
1910
123
    Token currentTokenValue = m_scanner->currentToken();
1911
123
    if (currentTokenValue == Token::RBrace)
1912
38
      break;
1913
85
    expectToken(Token::Function, false);
1914
    // TODO: require body already during parsing?
1915
85
    subNodes.push_back(parseFunctionDefinition(false, true));
1916
85
  }
1917
59
  nodeFactory.markEndPosition();
1918
59
  expectToken(Token::RBrace);
1919
1920
59
  return nodeFactory.createNode<TypeClassInstantiation>(
1921
59
    typeConstructor,
1922
59
    argumentSorts,
1923
59
    typeClassName,
1924
59
    subNodes
1925
59
  );
1926
59
}
1927
1928
ASTPointer<TypeDefinition> Parser::parseTypeDefinition()
1929
205
{
1930
205
  solAssert(m_experimentalSolidityEnabledInCurrentSourceUnit);
1931
205
  ASTNodeFactory nodeFactory(*this);
1932
205
  expectToken(Token::Type);
1933
205
  auto&& [name, nameLocation] = expectIdentifierWithLocation();
1934
1935
205
  ASTPointer<ParameterList> arguments;
1936
205
  if (m_scanner->currentToken() == Token::LParen)
1937
33
    arguments = parseParameterList();
1938
1939
205
  ASTPointer<Expression> expression;
1940
205
  if (m_scanner->currentToken() == Token::Assign)
1941
38
  {
1942
38
    expectToken(Token::Assign);
1943
1944
38
    if (m_scanner->currentToken() != Token::Builtin)
1945
12
      expression = parseExpression();
1946
26
    else
1947
26
    {
1948
26
      expectToken(Token::Builtin);
1949
26
      expectToken(Token::LParen);
1950
1951
26
      expression = nodeFactory.createNode<Builtin>(
1952
26
        std::make_shared<std::string>(m_scanner->currentLiteral()),
1953
26
        m_scanner->currentLocation()
1954
26
      );
1955
1956
26
      expectToken(Token::StringLiteral);
1957
26
      expectToken(Token::RParen);
1958
26
    }
1959
38
  }
1960
205
  nodeFactory.markEndPosition();
1961
205
  expectToken(Token::Semicolon);
1962
205
  return nodeFactory.createNode<TypeDefinition>(
1963
205
    std::move(name),
1964
205
    std::move(nameLocation),
1965
205
    std::move(arguments),
1966
205
    std::move(expression)
1967
205
  );
1968
205
}
1969
1970
ASTPointer<Statement> Parser::parseSimpleStatement(ASTPointer<ASTString> const& _docString)
1971
64.9k
{
1972
64.9k
  RecursionGuard recursionGuard(*this);
1973
64.9k
  LookAheadInfo statementType;
1974
64.9k
  IndexAccessedPath iap;
1975
1976
64.9k
  if (m_experimentalSolidityEnabledInCurrentSourceUnit && m_scanner->currentToken() == Token::Let)
1977
28
    return parsePostfixVariableDeclarationStatement(_docString);
1978
1979
64.9k
  if (m_scanner->currentToken() == Token::LParen)
1980
2.97k
  {
1981
2.97k
    ASTNodeFactory nodeFactory(*this);
1982
2.97k
    size_t emptyComponents = 0;
1983
    // First consume all empty components.
1984
2.97k
    expectToken(Token::LParen);
1985
3.43k
    while (m_scanner->currentToken() == Token::Comma)
1986
468
    {
1987
468
      advance();
1988
468
      emptyComponents++;
1989
468
    }
1990
1991
    // Now see whether we have a variable declaration or an expression.
1992
2.97k
    std::tie(statementType, iap) = tryParseIndexAccessedPath();
1993
2.97k
    switch (statementType)
1994
2.97k
    {
1995
1.06k
    case LookAheadInfo::VariableDeclaration:
1996
1.06k
    {
1997
1.06k
      std::vector<ASTPointer<VariableDeclaration>> variables;
1998
1.06k
      ASTPointer<Expression> value;
1999
      // We have already parsed something like `(,,,,a.b.c[2][3]`
2000
1.06k
      VarDeclParserOptions options;
2001
1.06k
      options.allowLocationSpecifier = true;
2002
1.06k
      variables = std::vector<ASTPointer<VariableDeclaration>>(emptyComponents, nullptr);
2003
1.06k
      variables.push_back(parseVariableDeclaration(options, typeNameFromIndexAccessStructure(iap)));
2004
2005
2.88k
      while (m_scanner->currentToken() != Token::RParen)
2006
1.82k
      {
2007
1.82k
        expectToken(Token::Comma);
2008
1.82k
        if (m_scanner->currentToken() == Token::Comma || m_scanner->currentToken() == Token::RParen)
2009
978
          variables.push_back(nullptr);
2010
848
        else
2011
848
          variables.push_back(parseVariableDeclaration(options));
2012
1.82k
      }
2013
1.06k
      expectToken(Token::RParen);
2014
1.06k
      expectToken(Token::Assign);
2015
1.06k
      value = parseExpression();
2016
1.06k
      nodeFactory.setEndPositionFromNode(value);
2017
1.06k
      return nodeFactory.createNode<VariableDeclarationStatement>(_docString, variables, value);
2018
0
    }
2019
1.90k
    case LookAheadInfo::Expression:
2020
1.90k
    {
2021
      // Complete parsing the expression in the current component.
2022
1.90k
      std::vector<ASTPointer<Expression>> components(emptyComponents, nullptr);
2023
1.90k
      components.push_back(parseExpression(expressionFromIndexAccessStructure(iap)));
2024
3.89k
      while (m_scanner->currentToken() != Token::RParen)
2025
1.99k
      {
2026
1.99k
        expectToken(Token::Comma);
2027
1.99k
        if (m_scanner->currentToken() == Token::Comma || m_scanner->currentToken() == Token::RParen)
2028
440
          components.push_back(ASTPointer<Expression>());
2029
1.55k
        else
2030
1.55k
          components.push_back(parseExpression());
2031
1.99k
      }
2032
1.90k
      nodeFactory.markEndPosition();
2033
1.90k
      expectToken(Token::RParen);
2034
1.90k
      return parseExpressionStatement(_docString, nodeFactory.createNode<TupleExpression>(components, false));
2035
0
    }
2036
0
    default:
2037
0
      solAssert(false);
2038
2.97k
    }
2039
2.97k
  }
2040
61.9k
  else
2041
61.9k
  {
2042
61.9k
    std::tie(statementType, iap) = tryParseIndexAccessedPath();
2043
61.9k
    switch (statementType)
2044
61.9k
    {
2045
11.5k
    case LookAheadInfo::VariableDeclaration:
2046
11.5k
      return parseVariableDeclarationStatement(_docString, typeNameFromIndexAccessStructure(iap));
2047
50.3k
    case LookAheadInfo::Expression:
2048
50.3k
      return parseExpressionStatement(_docString, expressionFromIndexAccessStructure(iap));
2049
0
    default:
2050
0
      solAssert(false);
2051
61.9k
    }
2052
61.9k
  }
2053
2054
  // FIXME: Workaround for spurious GCC 12.1 warning (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105794)
2055
0
  util::unreachable();
2056
0
}
2057
2058
bool Parser::IndexAccessedPath::empty() const
2059
66.5k
{
2060
66.5k
  if (!indices.empty())
2061
66.5k
    solAssert(!path.empty());
2062
2063
66.5k
  return path.empty() && indices.empty();
2064
66.5k
}
2065
2066
2067
std::pair<Parser::LookAheadInfo, Parser::IndexAccessedPath> Parser::tryParseIndexAccessedPath()
2068
64.9k
{
2069
  // These two cases are very hard to distinguish:
2070
  // x[7 * 20 + 3] a;     and     x[7 * 20 + 3] = 9;
2071
  // In the first case, x is a type name, in the second it is the name of a variable.
2072
  // As an extension, we can even have:
2073
  // `x.y.z[1][2] a;` and `x.y.z[1][2] = 10;`
2074
  // Where in the first, x.y.z leads to a type name where in the second, it accesses structs.
2075
2076
64.9k
  auto statementType = peekStatementType();
2077
64.9k
  switch (statementType)
2078
64.9k
  {
2079
10.6k
  case LookAheadInfo::VariableDeclaration:
2080
33.8k
  case LookAheadInfo::Expression:
2081
33.8k
    return std::make_pair(
2082
33.8k
      m_experimentalSolidityEnabledInCurrentSourceUnit ? LookAheadInfo::Expression : statementType,
2083
33.8k
      IndexAccessedPath()
2084
33.8k
    );
2085
31.0k
  default:
2086
31.0k
    break;
2087
64.9k
  }
2088
2089
  // At this point, we have 'Identifier "["' or 'Identifier "." Identifier' or 'ElementoryTypeName "["'.
2090
  // We parse '(Identifier ("." Identifier)* |ElementaryTypeName) ( "[" Expression "]" )*'
2091
  // until we can decide whether to hand this over to ExpressionStatement or create a
2092
  // VariableDeclarationStatement out of it.
2093
31.0k
  IndexAccessedPath iap = parseIndexAccessedPath();
2094
2095
31.0k
  if (m_experimentalSolidityEnabledInCurrentSourceUnit)
2096
0
    return std::make_pair(LookAheadInfo::Expression, std::move(iap));
2097
2098
31.0k
  if (m_scanner->currentToken() == Token::Identifier || TokenTraits::isLocationSpecifier(m_scanner->currentToken()))
2099
1.95k
    return std::make_pair(LookAheadInfo::VariableDeclaration, std::move(iap));
2100
29.1k
  else
2101
29.1k
    return std::make_pair(LookAheadInfo::Expression, std::move(iap));
2102
31.0k
}
2103
2104
ASTPointer<VariableDeclarationStatement> Parser::parseVariableDeclarationStatement(
2105
  ASTPointer<ASTString> const& _docString,
2106
  ASTPointer<TypeName> const& _lookAheadArrayType
2107
)
2108
11.5k
{
2109
  // This does not parse multi variable declaration statements starting directly with
2110
  // `(`, they are parsed in parseSimpleStatement, because they are hard to distinguish
2111
  // from tuple expressions.
2112
11.5k
  RecursionGuard recursionGuard(*this);
2113
11.5k
  ASTNodeFactory nodeFactory(*this);
2114
11.5k
  if (_lookAheadArrayType)
2115
1.94k
    nodeFactory.setLocation(_lookAheadArrayType->location());
2116
2117
11.5k
  VarDeclParserOptions options;
2118
11.5k
  options.allowLocationSpecifier = true;
2119
11.5k
  std::vector<ASTPointer<VariableDeclaration>> variables;
2120
11.5k
  variables.emplace_back(parseVariableDeclaration(options, _lookAheadArrayType));
2121
11.5k
  nodeFactory.setEndPositionFromNode(variables.back());
2122
2123
11.5k
  ASTPointer<Expression> value;
2124
11.5k
  if (m_scanner->currentToken() == Token::Assign)
2125
7.36k
  {
2126
7.36k
    advance();
2127
7.36k
    value = parseExpression();
2128
7.36k
    nodeFactory.setEndPositionFromNode(value);
2129
7.36k
  }
2130
11.5k
  return nodeFactory.createNode<VariableDeclarationStatement>(_docString, variables, value);
2131
11.5k
}
2132
2133
ASTPointer<ExpressionStatement> Parser::parseExpressionStatement(
2134
  ASTPointer<ASTString> const& _docString,
2135
  ASTPointer<Expression> const& _partialParserResult
2136
)
2137
55.3k
{
2138
55.3k
  RecursionGuard recursionGuard(*this);
2139
55.3k
  ASTPointer<Expression> expression = parseExpression(_partialParserResult);
2140
55.3k
  return ASTNodeFactory(*this, expression).createNode<ExpressionStatement>(_docString, expression);
2141
55.3k
}
2142
2143
ASTPointer<Expression> Parser::parseExpression(
2144
  ASTPointer<Expression> const& _partiallyParsedExpression
2145
)
2146
414k
{
2147
414k
  RecursionGuard recursionGuard(*this);
2148
414k
  ASTPointer<Expression> expression = parseBinaryExpression(4, _partiallyParsedExpression);
2149
414k
  if (TokenTraits::isAssignmentOp(m_scanner->currentToken()))
2150
38.6k
  {
2151
38.6k
    Token assignmentOperator = m_scanner->currentToken();
2152
38.6k
    advance();
2153
38.6k
    ASTPointer<Expression> rightHandSide = parseExpression();
2154
38.6k
    ASTNodeFactory nodeFactory(*this, expression);
2155
38.6k
    nodeFactory.setEndPositionFromNode(rightHandSide);
2156
38.6k
    return nodeFactory.createNode<Assignment>(expression, assignmentOperator, rightHandSide);
2157
38.6k
  }
2158
375k
  else if (m_scanner->currentToken() == Token::Conditional)
2159
1.75k
  {
2160
1.75k
    advance();
2161
1.75k
    ASTPointer<Expression> trueExpression = parseExpression();
2162
1.75k
    expectToken(Token::Colon);
2163
1.75k
    ASTPointer<Expression> falseExpression = parseExpression();
2164
1.75k
    ASTNodeFactory nodeFactory(*this, expression);
2165
1.75k
    nodeFactory.setEndPositionFromNode(falseExpression);
2166
1.75k
    return nodeFactory.createNode<Conditional>(expression, trueExpression, falseExpression);
2167
1.75k
  }
2168
373k
  else
2169
373k
    return expression;
2170
414k
}
2171
2172
ASTPointer<Expression> Parser::parseBinaryExpression(
2173
  int _minPrecedence,
2174
  ASTPointer<Expression> const& _partiallyParsedExpression
2175
)
2176
517k
{
2177
517k
  RecursionGuard recursionGuard(*this);
2178
517k
  ASTPointer<Expression> expression = parseUnaryExpression(_partiallyParsedExpression);
2179
517k
  ASTNodeFactory nodeFactory(*this, expression);
2180
517k
  int precedence = tokenPrecedence(m_scanner->currentToken());
2181
856k
  for (; precedence >= _minPrecedence; --precedence)
2182
442k
    while (tokenPrecedence(m_scanner->currentToken()) == precedence)
2183
103k
    {
2184
103k
      Token op = m_scanner->currentToken();
2185
103k
      advance();
2186
2187
103k
      static_assert(TokenTraits::hasExpHighestPrecedence(), "Exp does not have the highest precedence");
2188
2189
      // Parse a**b**c as a**(b**c)
2190
103k
      ASTPointer<Expression> right = (op == Token::Exp) ?
2191
6.33k
        parseBinaryExpression(precedence) :
2192
103k
        parseBinaryExpression(precedence + 1);
2193
103k
      nodeFactory.setEndPositionFromNode(right);
2194
103k
      expression = nodeFactory.createNode<BinaryOperation>(expression, op, right);
2195
103k
    }
2196
517k
  return expression;
2197
517k
}
2198
2199
int Parser::tokenPrecedence(Token _token) const
2200
950k
{
2201
950k
  if (m_experimentalSolidityEnabledInCurrentSourceUnit)
2202
8.67k
  {
2203
8.67k
    switch (_token)
2204
8.67k
    {
2205
16
    case Token::Colon:
2206
16
      return 1000;
2207
3
    case Token::RightArrow:
2208
3
      return 999;
2209
8.65k
    default:
2210
8.65k
      break;
2211
8.67k
    }
2212
8.67k
  }
2213
950k
  return TokenTraits::precedence(m_scanner->currentToken());
2214
950k
}
2215
2216
ASTPointer<Expression> Parser::parseUnaryExpression(
2217
  ASTPointer<Expression> const& _partiallyParsedExpression
2218
)
2219
561k
{
2220
561k
  RecursionGuard recursionGuard(*this);
2221
561k
  ASTNodeFactory nodeFactory = _partiallyParsedExpression ?
2222
531k
    ASTNodeFactory(*this, _partiallyParsedExpression) : ASTNodeFactory(*this);
2223
561k
  Token token = m_scanner->currentToken();
2224
2225
561k
  if (!_partiallyParsedExpression && token == Token::Add)
2226
10
    fatalParserError(9636_error, "Use of unary + is disallowed.");
2227
2228
561k
  if (!_partiallyParsedExpression && (TokenTraits::isUnaryOp(token) || TokenTraits::isCountOp(token)))
2229
44.6k
  {
2230
    // prefix expression
2231
44.6k
    advance();
2232
44.6k
    ASTPointer<Expression> subExpression = parseUnaryExpression();
2233
44.6k
    nodeFactory.setEndPositionFromNode(subExpression);
2234
44.6k
    return nodeFactory.createNode<UnaryOperation>(token, subExpression, true);
2235
44.6k
  }
2236
517k
  else
2237
517k
  {
2238
    // potential postfix expression
2239
517k
    ASTPointer<Expression> subExpression = parseLeftHandSideExpression(_partiallyParsedExpression);
2240
517k
    token = m_scanner->currentToken();
2241
2242
517k
    if (!TokenTraits::isCountOp(token))
2243
504k
      return subExpression;
2244
12.3k
    nodeFactory.markEndPosition();
2245
12.3k
    advance();
2246
12.3k
    return nodeFactory.createNode<UnaryOperation>(token, subExpression, false);
2247
517k
  }
2248
561k
}
2249
2250
ASTPointer<Expression> Parser::parseLeftHandSideExpression(
2251
  ASTPointer<Expression> const& _partiallyParsedExpression
2252
)
2253
517k
{
2254
517k
  RecursionGuard recursionGuard(*this);
2255
517k
  ASTNodeFactory nodeFactory = _partiallyParsedExpression ?
2256
486k
    ASTNodeFactory(*this, _partiallyParsedExpression) : ASTNodeFactory(*this);
2257
2258
517k
  ASTPointer<Expression> expression;
2259
517k
  if (_partiallyParsedExpression)
2260
30.9k
    expression = _partiallyParsedExpression;
2261
486k
  else if (m_scanner->currentToken() == Token::New)
2262
3.28k
  {
2263
3.28k
    expectToken(Token::New);
2264
3.28k
    ASTPointer<TypeName> typeName(parseTypeName());
2265
3.28k
    nodeFactory.setEndPositionFromNode(typeName);
2266
3.28k
    expression = nodeFactory.createNode<NewExpression>(typeName);
2267
3.28k
  }
2268
483k
  else if (m_scanner->currentToken() == Token::Payable)
2269
275
  {
2270
275
    expectToken(Token::Payable);
2271
275
    nodeFactory.markEndPosition();
2272
275
    auto expressionType = nodeFactory.createNode<ElementaryTypeName>(
2273
275
      ElementaryTypeNameToken(Token::Address, 0, 0),
2274
275
      std::make_optional(StateMutability::Payable)
2275
275
    );
2276
275
    expression = nodeFactory.createNode<ElementaryTypeNameExpression>(expressionType);
2277
275
    expectToken(Token::LParen, false);
2278
275
  }
2279
482k
  else
2280
482k
    expression = parsePrimaryExpression();
2281
2282
781k
  while (true)
2283
775k
  {
2284
775k
    switch (m_scanner->currentToken())
2285
775k
    {
2286
100k
    case Token::LBrack:
2287
100k
    {
2288
100k
      advance();
2289
100k
      ASTPointer<Expression> index;
2290
100k
      ASTPointer<Expression> endIndex;
2291
100k
      if (m_scanner->currentToken() != Token::RBrack && m_scanner->currentToken() != Token::Colon)
2292
98.7k
        index = parseExpression();
2293
100k
      if (m_scanner->currentToken() == Token::Colon)
2294
789
      {
2295
789
        expectToken(Token::Colon);
2296
789
        if (m_scanner->currentToken() != Token::RBrack)
2297
409
          endIndex = parseExpression();
2298
789
        nodeFactory.markEndPosition();
2299
789
        expectToken(Token::RBrack);
2300
789
        expression = nodeFactory.createNode<IndexRangeAccess>(expression, index, endIndex);
2301
789
      }
2302
99.2k
      else
2303
99.2k
      {
2304
99.2k
        nodeFactory.markEndPosition();
2305
99.2k
        expectToken(Token::RBrack);
2306
99.2k
        expression = nodeFactory.createNode<IndexAccess>(expression, index);
2307
99.2k
      }
2308
100k
      break;
2309
0
    }
2310
127k
    case Token::Period:
2311
127k
    {
2312
127k
      advance();
2313
127k
      nodeFactory.markEndPosition();
2314
127k
      SourceLocation memberLocation = currentLocation();
2315
127k
      ASTPointer<ASTString> memberName = expectIdentifierTokenOrAddress();
2316
127k
      expression = nodeFactory.createNode<MemberAccess>(expression, std::move(memberName), std::move(memberLocation));
2317
127k
      break;
2318
0
    }
2319
39.3k
    case Token::LParen:
2320
39.3k
    {
2321
39.3k
      advance();
2322
39.3k
      auto functionCallArguments = parseFunctionCallArguments();
2323
39.3k
      nodeFactory.markEndPosition();
2324
39.3k
      expectToken(Token::RParen);
2325
39.3k
      expression = nodeFactory.createNode<FunctionCall>(
2326
39.3k
        expression,
2327
39.3k
        functionCallArguments.arguments,
2328
39.3k
        functionCallArguments.parameterNames,
2329
39.3k
        functionCallArguments.parameterNameLocations);
2330
39.3k
      break;
2331
0
    }
2332
943
    case Token::LBrace:
2333
943
    {
2334
      // See if this is followed by <identifier>, followed by ":". If not, it is not
2335
      // a function call options but a Block (from a try statement).
2336
943
      if (
2337
943
        m_scanner->peekNextToken() != Token::Identifier ||
2338
577
        m_scanner->peekNextNextToken() != Token::Colon
2339
943
      )
2340
401
        return expression;
2341
2342
542
      expectToken(Token::LBrace);
2343
542
      auto optionList = parseNamedArguments();
2344
2345
542
      nodeFactory.markEndPosition();
2346
542
      expectToken(Token::RBrace);
2347
2348
542
      expression = nodeFactory.createNode<FunctionCallOptions>(expression, optionList.arguments, optionList.parameterNames);
2349
542
      break;
2350
943
    }
2351
507k
    default:
2352
507k
      return expression;
2353
775k
    }
2354
775k
  }
2355
517k
}
2356
2357
ASTPointer<Expression> Parser::parseLiteral()
2358
323k
{
2359
323k
  RecursionGuard recursionGuard(*this);
2360
323k
  ASTNodeFactory nodeFactory(*this);
2361
323k
  Token initialToken = m_scanner->currentToken();
2362
323k
  ASTPointer<ASTString> value = std::make_shared<std::string>(m_scanner->currentLiteral());
2363
2364
323k
  switch (initialToken)
2365
323k
  {
2366
8.91k
  case Token::TrueLiteral:
2367
16.7k
  case Token::FalseLiteral:
2368
297k
  case Token::Number:
2369
297k
  {
2370
297k
    nodeFactory.markEndPosition();
2371
297k
    advance();
2372
297k
    break;
2373
16.7k
  }
2374
9.15k
  case Token::StringLiteral:
2375
10.0k
  case Token::UnicodeStringLiteral:
2376
26.4k
  case Token::HexStringLiteral:
2377
26.4k
  {
2378
27.5k
    while (m_scanner->peekNextToken() == initialToken)
2379
1.15k
    {
2380
1.15k
      advance();
2381
1.15k
      *value += m_scanner->currentLiteral();
2382
1.15k
    }
2383
26.4k
    nodeFactory.markEndPosition();
2384
26.4k
    advance();
2385
26.4k
    if (m_scanner->currentToken() == Token::Illegal)
2386
11
      fatalParserError(5428_error, to_string(m_scanner->currentError()));
2387
26.4k
    break;
2388
10.0k
  }
2389
0
  default:
2390
0
    solAssert(false);
2391
323k
  }
2392
2393
323k
  if (initialToken == Token::Number && (
2394
280k
    TokenTraits::isEtherSubdenomination(m_scanner->currentToken()) ||
2395
280k
    TokenTraits::isTimeSubdenomination(m_scanner->currentToken())
2396
280k
  ))
2397
475
  {
2398
475
    nodeFactory.markEndPosition();
2399
475
    Literal::SubDenomination subDenomination = static_cast<Literal::SubDenomination>(m_scanner->currentToken());
2400
475
    advance();
2401
475
    return nodeFactory.createNode<Literal>(initialToken, std::move(value), subDenomination);
2402
475
  }
2403
2404
323k
  return nodeFactory.createNode<Literal>(initialToken, std::move(value), Literal::SubDenomination::None);
2405
323k
}
2406
2407
ASTPointer<Expression> Parser::parsePrimaryExpression()
2408
482k
{
2409
482k
  RecursionGuard recursionGuard(*this);
2410
482k
  ASTNodeFactory nodeFactory(*this);
2411
482k
  Token token = m_scanner->currentToken();
2412
482k
  ASTPointer<Expression> expression;
2413
2414
482k
  switch (token)
2415
482k
  {
2416
8.91k
  case Token::TrueLiteral:
2417
16.7k
  case Token::FalseLiteral:
2418
297k
  case Token::Number:
2419
306k
  case Token::StringLiteral:
2420
307k
  case Token::UnicodeStringLiteral:
2421
323k
  case Token::HexStringLiteral:
2422
323k
    expression = parseLiteral();
2423
323k
    break;
2424
132k
  case Token::Identifier:
2425
132k
    nodeFactory.markEndPosition();
2426
132k
    expression = nodeFactory.createNode<Identifier>(getLiteralAndAdvance());
2427
132k
    break;
2428
404
  case Token::Type:
2429
    // Inside expressions "type" is the name of a special, globally-available function.
2430
404
    nodeFactory.markEndPosition();
2431
404
    advance();
2432
404
    expression = nodeFactory.createNode<Identifier>(std::make_shared<ASTString>("type"));
2433
404
    break;
2434
8.78k
  case Token::LParen:
2435
14.0k
  case Token::LBrack:
2436
14.0k
  {
2437
    // Tuple/parenthesized expression or inline array/bracketed expression.
2438
    // Special cases: ()/[] is empty tuple/array type, (x) is not a real tuple,
2439
    // (x,) is one-dimensional tuple, elements in arrays cannot be left out, only in tuples.
2440
14.0k
    advance();
2441
14.0k
    std::vector<ASTPointer<Expression>> components;
2442
14.0k
    Token oppositeToken = (token == Token::LParen ? Token::RParen : Token::RBrack);
2443
14.0k
    bool isArray = (token == Token::LBrack);
2444
2445
14.0k
    if (m_scanner->currentToken() != oppositeToken)
2446
25.3k
      while (true)
2447
20.5k
      {
2448
20.5k
        if (m_scanner->currentToken() != Token::Comma && m_scanner->currentToken() != oppositeToken)
2449
17.7k
          components.push_back(parseExpression());
2450
2.85k
        else if (isArray)
2451
808
          parserError(4799_error, "Expected expression (inline array elements cannot be omitted).");
2452
2.04k
        else
2453
2.04k
          components.push_back(ASTPointer<Expression>());
2454
2455
20.5k
        if (m_scanner->currentToken() == oppositeToken)
2456
8.66k
          break;
2457
2458
11.9k
        expectToken(Token::Comma);
2459
11.9k
      }
2460
14.0k
    nodeFactory.markEndPosition();
2461
14.0k
    expectToken(oppositeToken);
2462
14.0k
    expression = nodeFactory.createNode<TupleExpression>(components, isArray);
2463
14.0k
    break;
2464
8.78k
  }
2465
162
  case Token::Illegal:
2466
162
    fatalParserError(8936_error, to_string(m_scanner->currentError()));
2467
162
    break;
2468
11.5k
  default:
2469
11.5k
    if (TokenTraits::isElementaryTypeName(token))
2470
11.0k
    {
2471
      //used for casts
2472
11.0k
      unsigned firstSize;
2473
11.0k
      unsigned secondSize;
2474
11.0k
      std::tie(firstSize, secondSize) = m_scanner->currentTokenInfo();
2475
11.0k
      auto expressionType = nodeFactory.createNode<ElementaryTypeName>(
2476
11.0k
        ElementaryTypeNameToken(m_scanner->currentToken(), firstSize, secondSize)
2477
11.0k
      );
2478
11.0k
      expression = nodeFactory.createNode<ElementaryTypeNameExpression>(expressionType);
2479
11.0k
      advance();
2480
11.0k
    }
2481
490
    else
2482
490
      fatalParserError(6933_error, "Expected primary expression.");
2483
11.5k
    break;
2484
482k
  }
2485
477k
  return expression;
2486
482k
}
2487
2488
std::vector<ASTPointer<Expression>> Parser::parseFunctionCallListArguments()
2489
42.0k
{
2490
42.0k
  RecursionGuard recursionGuard(*this);
2491
42.0k
  std::vector<ASTPointer<Expression>> arguments;
2492
42.0k
  if (m_scanner->currentToken() != Token::RParen)
2493
34.6k
  {
2494
34.6k
    arguments.push_back(parseExpression());
2495
47.6k
    while (m_scanner->currentToken() != Token::RParen)
2496
12.9k
    {
2497
12.9k
      expectToken(Token::Comma);
2498
12.9k
      arguments.push_back(parseExpression());
2499
12.9k
    }
2500
34.6k
  }
2501
42.0k
  return arguments;
2502
42.0k
}
2503
2504
Parser::FunctionCallArguments Parser::parseFunctionCallArguments()
2505
41.0k
{
2506
41.0k
  RecursionGuard recursionGuard(*this);
2507
41.0k
  FunctionCallArguments ret;
2508
2509
41.0k
  Token token = m_scanner->currentToken();
2510
41.0k
  if (token == Token::LBrace)
2511
478
  {
2512
    // call({arg1 : 1, arg2 : 2 })
2513
478
    expectToken(Token::LBrace);
2514
478
    ret = parseNamedArguments();
2515
478
    expectToken(Token::RBrace);
2516
478
  }
2517
40.5k
  else
2518
40.5k
    ret.arguments = parseFunctionCallListArguments();
2519
41.0k
  return ret;
2520
41.0k
}
2521
2522
Parser::FunctionCallArguments Parser::parseNamedArguments()
2523
1.02k
{
2524
1.02k
  FunctionCallArguments ret;
2525
2526
1.02k
  bool first = true;
2527
2.80k
  while (m_scanner->currentToken() != Token::RBrace)
2528
1.78k
  {
2529
1.78k
    if (!first)
2530
765
      expectToken(Token::Comma);
2531
2532
1.78k
    auto identifierWithLocation = expectIdentifierWithLocation();
2533
2534
    // Add name
2535
1.78k
    ret.parameterNames.emplace_back(std::move(identifierWithLocation.first));
2536
    // Add location
2537
1.78k
    ret.parameterNameLocations.emplace_back(std::move(identifierWithLocation.second));
2538
2539
1.78k
    expectToken(Token::Colon);
2540
1.78k
    ret.arguments.emplace_back(parseExpression());
2541
2542
1.78k
    if (
2543
1.78k
      m_scanner->currentToken() == Token::Comma &&
2544
767
      m_scanner->peekNextToken() == Token::RBrace
2545
1.78k
    )
2546
12
    {
2547
12
      parserError(2074_error, "Unexpected trailing comma.");
2548
12
      advance();
2549
12
    }
2550
2551
1.78k
    first = false;
2552
1.78k
  }
2553
2554
1.02k
  return ret;
2555
1.02k
}
2556
2557
bool Parser::variableDeclarationStart()
2558
33.5k
{
2559
33.5k
  Token currentToken = m_scanner->currentToken();
2560
33.5k
  return
2561
33.5k
    currentToken == Token::Identifier ||
2562
25.3k
    currentToken == Token::Mapping ||
2563
24.6k
    TokenTraits::isElementaryTypeName(currentToken) ||
2564
8.48k
    (currentToken == Token::Function && m_scanner->peekNextToken() == Token::LParen);
2565
33.5k
}
2566
2567
std::optional<std::string> Parser::findLicenseString(std::vector<ASTPointer<ASTNode>> const& _nodes)
2568
27.9k
{
2569
  // We circumvent the scanner here, because it skips non-docstring comments.
2570
27.9k
  static std::regex const licenseNameRegex("([a-zA-Z0-9 ()+.-]+)");
2571
27.9k
  static std::regex const licenseDeclarationRegex("SPDX-License-Identifier:\\s*(.+?)([\n\r]|(\\*/))");
2572
2573
  // Search inside all parts of the source not covered by parsed nodes.
2574
  // This will leave e.g. "global comments".
2575
27.9k
  using iter = std::string::const_iterator;
2576
27.9k
  std::vector<std::pair<iter, iter>> sequencesToSearch;
2577
27.9k
  std::string const& source = m_scanner->charStream().source();
2578
27.9k
  sequencesToSearch.emplace_back(source.begin(), source.end());
2579
27.9k
  for (ASTPointer<ASTNode> const& node: _nodes)
2580
77.3k
    if (node->location().hasText())
2581
77.3k
    {
2582
77.3k
      sequencesToSearch.back().second = source.begin() + node->location().start;
2583
77.3k
      sequencesToSearch.emplace_back(source.begin() + node->location().end, source.end());
2584
77.3k
    }
2585
2586
27.9k
  std::vector<std::string> licenseNames;
2587
27.9k
  for (auto const& [start, end]: sequencesToSearch)
2588
105k
  {
2589
105k
    auto declarationsBegin = std::sregex_iterator(start, end, licenseDeclarationRegex);
2590
105k
    auto declarationsEnd = std::sregex_iterator();
2591
2592
105k
    for (std::sregex_iterator declIt = declarationsBegin; declIt != declarationsEnd; ++declIt)
2593
361
      if (!declIt->empty())
2594
361
      {
2595
361
        std::string license = boost::trim_copy(std::string((*declIt)[1]));
2596
361
        licenseNames.emplace_back(std::move(license));
2597
361
      }
2598
105k
  }
2599
2600
27.9k
  if (licenseNames.size() == 1)
2601
289
  {
2602
289
std::string const& license = licenseNames.front();
2603
289
    if (regex_match(license, licenseNameRegex))
2604
261
      return license;
2605
28
    else
2606
28
      parserError(
2607
28
        1114_error,
2608
28
        {-1, -1, m_scanner->currentLocation().sourceName},
2609
28
        "Invalid SPDX license identifier."
2610
28
      );
2611
289
  }
2612
27.6k
  else if (licenseNames.empty())
2613
27.6k
    parserWarning(
2614
27.6k
      1878_error,
2615
27.6k
      {-1, -1, m_scanner->currentLocation().sourceName},
2616
27.6k
      "SPDX license identifier not provided in source file. "
2617
27.6k
      "Before publishing, consider adding a comment containing "
2618
27.6k
      "\"SPDX-License-Identifier: <SPDX-License>\" to each source file. "
2619
27.6k
      "Use \"SPDX-License-Identifier: UNLICENSED\" for non-open-source code. "
2620
27.6k
      "Please see https://spdx.org for more information."
2621
27.6k
    );
2622
19
  else
2623
19
    parserError(
2624
19
      3716_error,
2625
19
      {-1, -1, m_scanner->currentLocation().sourceName},
2626
19
      "Multiple SPDX license identifiers found in source file. "
2627
19
      "Use \"AND\" or \"OR\" to combine multiple licenses. "
2628
19
      "Please see https://spdx.org for more information."
2629
19
    );
2630
2631
27.7k
  return {};
2632
27.9k
}
2633
2634
Parser::LookAheadInfo Parser::peekStatementType() const
2635
64.9k
{
2636
  // Distinguish between variable declaration (and potentially assignment) and expression statement
2637
  // (which include assignments to other expressions and pre-declared variables).
2638
  // We have a variable declaration if we get a keyword that specifies a type name.
2639
  // If it is an identifier or an elementary type name followed by an identifier
2640
  // or a mutability specifier, we also have a variable declaration.
2641
  // If we get an identifier followed by a "[" or ".", it can be both ("lib.type[9] a;" or "variable.el[9] = 7;").
2642
  // In all other cases, we have an expression statement.
2643
64.9k
  Token token(m_scanner->currentToken());
2644
64.9k
  bool mightBeTypeName = (TokenTraits::isElementaryTypeName(token) || token == Token::Identifier);
2645
2646
64.9k
  if (token == Token::Mapping || token == Token::Function)
2647
306
    return LookAheadInfo::VariableDeclaration;
2648
64.6k
  if (mightBeTypeName)
2649
59.2k
  {
2650
59.2k
    Token next = m_scanner->peekNextToken();
2651
    // So far we only allow ``address payable`` in variable declaration statements and in no other
2652
    // kind of statement. This means, for example, that we do not allow type expressions of the form
2653
    // ``address payable;``.
2654
    // If we want to change this in the future, we need to consider another scanner token here.
2655
59.2k
    if (TokenTraits::isElementaryTypeName(token) && TokenTraits::isStateMutabilitySpecifier(next))
2656
111
      return LookAheadInfo::VariableDeclaration;
2657
59.0k
    if (next == Token::Identifier || TokenTraits::isLocationSpecifier(next))
2658
10.2k
      return LookAheadInfo::VariableDeclaration;
2659
48.8k
    if (next == Token::LBrack || next == Token::Period)
2660
31.0k
      return LookAheadInfo::IndexAccessStructure;
2661
48.8k
  }
2662
23.1k
  return LookAheadInfo::Expression;
2663
64.6k
}
2664
2665
Parser::IndexAccessedPath Parser::parseIndexAccessedPath()
2666
31.0k
{
2667
31.0k
  IndexAccessedPath iap;
2668
31.0k
  if (m_scanner->currentToken() == Token::Identifier)
2669
29.2k
  {
2670
29.2k
    iap.path.push_back(parseIdentifier());
2671
69.7k
    while (m_scanner->currentToken() == Token::Period)
2672
40.4k
    {
2673
40.4k
      advance();
2674
40.4k
      if (m_experimentalSolidityEnabledInCurrentSourceUnit && m_scanner->currentToken() == Token::Number)
2675
0
      {
2676
0
        ASTNodeFactory nodeFactory(*this);
2677
0
        nodeFactory.markEndPosition();
2678
0
        iap.path.push_back(nodeFactory.createNode<Identifier>(getLiteralAndAdvance()));
2679
0
      }
2680
40.4k
      else
2681
40.4k
        iap.path.push_back(parseIdentifierOrAddress());
2682
40.4k
    }
2683
29.2k
  }
2684
1.76k
  else
2685
1.76k
  {
2686
1.76k
    unsigned firstNum;
2687
1.76k
    unsigned secondNum;
2688
1.76k
    std::tie(firstNum, secondNum) = m_scanner->currentTokenInfo();
2689
1.76k
    auto expressionType = ASTNodeFactory(*this).createNode<ElementaryTypeName>(
2690
1.76k
      ElementaryTypeNameToken(m_scanner->currentToken(), firstNum, secondNum)
2691
1.76k
    );
2692
1.76k
    iap.path.push_back(ASTNodeFactory(*this).createNode<ElementaryTypeNameExpression>(expressionType));
2693
1.76k
    advance();
2694
1.76k
  }
2695
67.5k
  while (m_scanner->currentToken() == Token::LBrack)
2696
36.5k
  {
2697
36.5k
    expectToken(Token::LBrack);
2698
36.5k
    ASTPointer<Expression> index;
2699
36.5k
    if (m_scanner->currentToken() != Token::RBrack && m_scanner->currentToken() != Token::Colon)
2700
33.0k
      index = parseExpression();
2701
36.5k
    SourceLocation indexLocation = iap.path.front()->location();
2702
36.5k
    if (m_scanner->currentToken() == Token::Colon)
2703
977
    {
2704
977
      expectToken(Token::Colon);
2705
977
      ASTPointer<Expression> endIndex;
2706
977
      if (m_scanner->currentToken() != Token::RBrack)
2707
359
        endIndex = parseExpression();
2708
977
      indexLocation.end = currentLocation().end;
2709
977
      iap.indices.emplace_back(IndexAccessedPath::Index{index, {endIndex}, indexLocation});
2710
977
      expectToken(Token::RBrack);
2711
977
    }
2712
35.5k
    else
2713
35.5k
    {
2714
35.5k
      indexLocation.end = currentLocation().end;
2715
35.5k
      iap.indices.emplace_back(IndexAccessedPath::Index{index, {}, indexLocation});
2716
35.5k
      expectToken(Token::RBrack);
2717
35.5k
    }
2718
36.5k
  }
2719
2720
31.0k
  return iap;
2721
31.0k
}
2722
2723
ASTPointer<TypeName> Parser::typeNameFromIndexAccessStructure(Parser::IndexAccessedPath const& _iap)
2724
12.6k
{
2725
12.6k
  if (_iap.empty())
2726
10.6k
    return {};
2727
2728
1.95k
  RecursionGuard recursionGuard(*this);
2729
1.95k
  ASTNodeFactory nodeFactory(*this);
2730
1.95k
  SourceLocation location = _iap.path.front()->location();
2731
1.95k
  location.end = _iap.path.back()->location().end;
2732
1.95k
  nodeFactory.setLocation(location);
2733
2734
1.95k
  ASTPointer<TypeName> type;
2735
1.95k
  if (auto typeName = dynamic_cast<ElementaryTypeNameExpression const*>(_iap.path.front().get()))
2736
1.66k
  {
2737
1.66k
    solAssert(_iap.path.size() == 1, "");
2738
1.66k
    type = nodeFactory.createNode<ElementaryTypeName>(typeName->type().typeName());
2739
1.66k
  }
2740
290
  else
2741
290
  {
2742
290
    std::vector<ASTString> path;
2743
290
    std::vector<SourceLocation> pathLocations;
2744
2745
290
    for (auto const& el: _iap.path)
2746
536
    {
2747
536
      auto& identifier = dynamic_cast<Identifier const&>(*el);
2748
536
      path.push_back(identifier.name());
2749
536
      pathLocations.push_back(identifier.location());
2750
536
    }
2751
2752
290
    type = nodeFactory.createNode<UserDefinedTypeName>(nodeFactory.createNode<IdentifierPath>(path, pathLocations));
2753
290
  }
2754
1.95k
  for (auto const& lengthExpression: _iap.indices)
2755
3.38k
  {
2756
3.38k
    if (lengthExpression.end)
2757
21
      parserError(5464_error, lengthExpression.location, "Expected array length expression.");
2758
3.38k
    nodeFactory.setLocation(lengthExpression.location);
2759
3.38k
    type = nodeFactory.createNode<ArrayTypeName>(type, lengthExpression.start);
2760
3.38k
  }
2761
1.95k
  return type;
2762
12.6k
}
2763
2764
ASTPointer<Expression> Parser::expressionFromIndexAccessStructure(
2765
  Parser::IndexAccessedPath const& _iap
2766
)
2767
53.8k
{
2768
53.8k
  if (_iap.empty())
2769
23.1k
    return {};
2770
2771
30.7k
  RecursionGuard recursionGuard(*this);
2772
30.7k
  ASTNodeFactory nodeFactory(*this, _iap.path.front());
2773
30.7k
  ASTPointer<Expression> expression(_iap.path.front());
2774
70.9k
  for (size_t i = 1; i < _iap.path.size(); ++i)
2775
40.2k
  {
2776
40.2k
    SourceLocation location(_iap.path.front()->location());
2777
40.2k
    location.end = _iap.path[i]->location().end;
2778
40.2k
    nodeFactory.setLocation(location);
2779
40.2k
    Identifier const& identifier = dynamic_cast<Identifier const&>(*_iap.path[i]);
2780
40.2k
    expression = nodeFactory.createNode<MemberAccess>(
2781
40.2k
      expression,
2782
40.2k
      std::make_shared<ASTString>(identifier.name()),
2783
40.2k
      identifier.location()
2784
40.2k
    );
2785
40.2k
  }
2786
30.7k
  for (auto const& index: _iap.indices)
2787
32.7k
  {
2788
32.7k
    nodeFactory.setLocation(index.location);
2789
32.7k
    if (index.end)
2790
881
      expression = nodeFactory.createNode<IndexRangeAccess>(expression, index.start, *index.end);
2791
31.9k
    else
2792
31.9k
      expression = nodeFactory.createNode<IndexAccess>(expression, index.start);
2793
32.7k
  }
2794
30.7k
  return expression;
2795
53.8k
}
2796
2797
ASTPointer<ParameterList> Parser::createEmptyParameterList()
2798
23.0k
{
2799
23.0k
  RecursionGuard recursionGuard(*this);
2800
23.0k
  ASTNodeFactory nodeFactory(*this);
2801
23.0k
  nodeFactory.setLocationEmpty();
2802
23.0k
  return nodeFactory.createNode<ParameterList>(std::vector<ASTPointer<VariableDeclaration>>());
2803
23.0k
}
2804
2805
ASTPointer<ASTString> Parser::expectIdentifierToken()
2806
237k
{
2807
237k
  expectToken(Token::Identifier, false /* do not advance */);
2808
237k
  return getLiteralAndAdvance();
2809
237k
}
2810
2811
ASTPointer<ASTString> Parser::expectIdentifierTokenOrAddress()
2812
168k
{
2813
168k
  ASTPointer<ASTString> result;
2814
168k
  if (m_scanner->currentToken() == Token::Address)
2815
51
  {
2816
51
    result = std::make_shared<ASTString>("address");
2817
51
    advance();
2818
51
  }
2819
167k
  else
2820
167k
  {
2821
167k
    expectToken(Token::Identifier, false /* do not advance */);
2822
167k
    result = getLiteralAndAdvance();
2823
167k
  }
2824
168k
  return result;
2825
168k
}
2826
2827
ASTPointer<ASTString> Parser::getLiteralAndAdvance()
2828
539k
{
2829
539k
  ASTPointer<ASTString> identifier = std::make_shared<ASTString>(m_scanner->currentLiteral());
2830
539k
  advance();
2831
539k
  return identifier;
2832
539k
}
2833
2834
bool Parser::isQuotedPath() const
2835
4.13k
{
2836
4.13k
  return m_scanner->currentToken() == Token::StringLiteral;
2837
4.13k
}
2838
2839
bool Parser::isStdlibPath() const
2840
612
{
2841
612
  return m_experimentalSolidityEnabledInCurrentSourceUnit
2842
47
    && m_scanner->currentToken() == Token::Identifier
2843
26
    && m_scanner->currentLiteral() == "std";
2844
612
}
2845
2846
ASTPointer<ASTString> Parser::getStdlibImportPathAndAdvance()
2847
26
{
2848
26
  ASTPointer<ASTString> std = expectIdentifierToken();
2849
26
  if (m_scanner->currentToken() == Token::Period)
2850
25
    advance();
2851
26
  ASTPointer<ASTString> library = expectIdentifierToken();
2852
26
  return std::make_shared<ASTString>(*std + "." + *library);
2853
26
}
2854
2855
}