/* * Copyright (c) 2021, Itamar S. * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include "AK/NonnullRefPtr.h" #include "AST.h" #include "Preprocessor.h" #include #include namespace Cpp { class Parser final { AK_MAKE_NONCOPYABLE(Parser); public: explicit Parser(Vector tokens, String const& filename); ~Parser() = default; NonnullRefPtr parse(); bool eof() const; RefPtr node_at(Position) const; Optional index_of_node_at(Position) const; Optional token_at(Position) const; Optional index_of_token_at(Position) const; RefPtr root_node() const { return m_root_node; } String text_of_node(const ASTNode&) const; StringView text_of_token(const Cpp::Token& token) const; void print_tokens() const; const Vector& errors() const { return m_errors; } struct TodoEntry { String content; String filename; size_t line { 0 }; size_t column { 0 }; }; Vector get_todo_entries() const; Vector tokens_in_range(Position start, Position end) const; private: enum class DeclarationType { Function, Variable, Enum, Class, Namespace, Constructor, Destructor, }; Optional match_declaration_in_translation_unit(); Optional match_class_member(const StringView& class_name); bool match_function_declaration(); bool match_comment(); bool match_preprocessor(); bool match_whitespace(); bool match_variable_declaration(); bool match_expression(); bool match_secondary_expression(); bool match_enum_declaration(); bool match_class_declaration(); bool match_literal(); bool match_unary_expression(); bool match_boolean_literal(); bool match_keyword(const String&); bool match_block_statement(); bool match_namespace_declaration(); bool match_template_arguments(); bool match_name(); bool match_cpp_cast_expression(); bool match_c_style_cast_expression(); bool match_sizeof_expression(); bool match_braced_init_list(); bool match_type(); bool match_named_type(); bool match_access_specifier(); bool match_constructor(const StringView& class_name); bool match_destructor(const StringView& class_name); Optional> parse_parameter_list(ASTNode& parent); Optional consume_whitespace(); void consume_preprocessor(); NonnullRefPtr parse_declaration(ASTNode& parent, DeclarationType); NonnullRefPtr parse_function_declaration(ASTNode& parent); NonnullRefPtr parse_function_definition(ASTNode& parent); NonnullRefPtr parse_statement(ASTNode& parent); NonnullRefPtr parse_variable_declaration(ASTNode& parent, bool expect_semicolon = true); NonnullRefPtr parse_expression(ASTNode& parent); NonnullRefPtr parse_primary_expression(ASTNode& parent); NonnullRefPtr parse_secondary_expression(ASTNode& parent, NonnullRefPtr lhs); NonnullRefPtr parse_function_call(ASTNode& parent); NonnullRefPtr parse_string_literal(ASTNode& parent); NonnullRefPtr parse_return_statement(ASTNode& parent); NonnullRefPtr parse_enum_declaration(ASTNode& parent); NonnullRefPtr parse_class_declaration(ASTNode& parent); NonnullRefPtr parse_literal(ASTNode& parent); NonnullRefPtr parse_unary_expression(ASTNode& parent); NonnullRefPtr parse_boolean_literal(ASTNode& parent); NonnullRefPtr parse_type(ASTNode& parent); NonnullRefPtr parse_named_type(ASTNode& parent); NonnullRefPtr parse_binary_expression(ASTNode& parent, NonnullRefPtr lhs, BinaryOp); NonnullRefPtr parse_assignment_expression(ASTNode& parent, NonnullRefPtr lhs, AssignmentOp); NonnullRefPtr parse_for_statement(ASTNode& parent); NonnullRefPtr parse_block_statement(ASTNode& parent); NonnullRefPtr parse_comment(ASTNode& parent); NonnullRefPtr parse_if_statement(ASTNode& parent); NonnullRefPtr parse_namespace_declaration(ASTNode& parent, bool is_nested_namespace = false); NonnullRefPtrVector parse_declarations_in_translation_unit(ASTNode& parent); RefPtr parse_single_declaration_in_translation_unit(ASTNode& parent); NonnullRefPtrVector parse_template_arguments(ASTNode& parent); NonnullRefPtr parse_name(ASTNode& parent); NonnullRefPtr parse_cpp_cast_expression(ASTNode& parent); NonnullRefPtr parse_sizeof_expression(ASTNode& parent); NonnullRefPtr parse_braced_init_list(ASTNode& parent); NonnullRefPtr parse_c_style_cast_expression(ASTNode& parent); NonnullRefPtrVector parse_class_members(StructOrClassDeclaration& parent); NonnullRefPtr parse_constructor(ASTNode& parent); NonnullRefPtr parse_destructor(ASTNode& parent); bool match(Token::Type); Token consume(Token::Type); Token consume(); Token consume_keyword(const String&); Token peek(size_t offset = 0) const; Optional peek(Token::Type) const; Position position() const; String text_in_range(Position start, Position end) const; void save_state(); void load_state(); struct State { size_t token_index { 0 }; NonnullRefPtrVector state_nodes; }; void error(StringView message = {}); template NonnullRefPtr create_ast_node(ASTNode& parent, const Position& start, Optional end, Args&&... args) { auto node = adopt_ref(*new T(&parent, start, end, m_filename, forward(args)...)); if (m_saved_states.is_empty()) { m_nodes.append(node); } else { m_state.state_nodes.append(node); } return node; } NonnullRefPtr create_root_ast_node(const Position& start, Position end) { auto node = adopt_ref(*new TranslationUnit(nullptr, start, end, m_filename)); m_nodes.append(node); m_root_node = node; return node; } DummyAstNode& get_dummy_node() { static NonnullRefPtr dummy = adopt_ref(*new DummyAstNode(nullptr, {}, {}, {})); return dummy; } bool match_attribute_specification(); void consume_attribute_specification(); void consume_access_specifier(); bool match_ellipsis(); Vector parse_type_qualifiers(); Vector parse_function_qualifiers(); enum class CtorOrDtor { Ctor, Dtor, }; void parse_constructor_or_destructor_impl(FunctionDeclaration&, CtorOrDtor); String m_filename; Vector m_tokens; State m_state; Vector m_saved_states; RefPtr m_root_node; Vector m_errors; NonnullRefPtrVector m_nodes; }; }