/* * 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(const StringView& program, const String& filename, Preprocessor::Definitions&& = {}); ~Parser() = default; NonnullRefPtr parse(); bool eof() const; RefPtr eof_node() 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_state.errors; } const Preprocessor::Definitions& preprocessor_definitions() const { return m_preprocessor_definitions; } struct TokenAndPreprocessorDefinition { Token token; Preprocessor::DefinedValue preprocessor_value; }; const Vector& replaced_preprocessor_tokens() const { return m_replaced_preprocessor_tokens; } private: enum class DeclarationType { Function, Variable, Enum, Struct, Namespace, Class, }; Optional match_declaration_in_translation_unit(); 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_struct_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(); 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_struct_or_class_declaration(ASTNode& parent, StructOrClassDeclaration::Type); NonnullRefPtr parse_member_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_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); 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 }; Vector errors; NonnullRefPtrVector 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 (!parent.is_dummy_node()) { m_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_state.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(); bool match_ellipsis(); void initialize_program_tokens(const StringView& program); void add_tokens_for_preprocessor(Token& replaced_token, Preprocessor::DefinedValue&); Vector parse_type_qualifiers(); Vector parse_function_qualifiers(); Preprocessor::Definitions m_preprocessor_definitions; String m_filename; Vector m_tokens; State m_state; Vector m_saved_states; RefPtr m_root_node; Vector m_replaced_preprocessor_tokens; }; }