/* * Copyright (c) 2021, Itamar S. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "AK/NonnullRefPtr.h" #include "AST.h" #include namespace Cpp { class Parser final { public: explicit Parser(const StringView&); ~Parser() = default; NonnullRefPtr parse(); bool eof() const; RefPtr eof_node() const; RefPtr node_at(Position) const; Optional token_at(Position) const; RefPtr root_node() const { return m_root_node; } StringView text_of_node(const ASTNode&) const; StringView text_of_token(const Cpp::Token& token) const; void print_tokens() const; Vector errors() const { return m_errors; } private: enum class DeclarationType { Function, Variable, Enum, Struct, }; bool done(); Optional match_declaration(); Optional match_declaration_in_translation_unit(); Optional match_declaration_in_function_definition(); bool match_function_declaration(); bool match_comment(); bool match_preprocessor(); bool match_whitespace(); bool match_variable_declaration(); bool match_expression(); bool match_function_call(); bool match_secondary_expression(); bool match_enum_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(); 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); 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); bool match(Token::Type); Token consume(Token::Type); Token consume(); Token consume_keyword(const String&); Token peek() const; Optional peek(Token::Type) const; Position position() const; StringView text_of_range(Position start, Position end) const; void save_state(); void load_state(); enum class Context { InTranslationUnit, InFunctionDefinition, }; struct State { Context context { Context::InTranslationUnit }; size_t token_index { 0 }; }; void error(StringView message = {}); size_t node_span_size(const ASTNode& node) const; template NonnullRefPtr create_ast_node(ASTNode& parent, const Position& start, Optional end, Args&&... args) { auto node = adopt(*new T(&parent, start, end, forward(args)...)); m_nodes.append(node); return node; } NonnullRefPtr create_root_ast_node(const Position& start, Position end) { auto node = adopt(*new TranslationUnit(nullptr, start, end)); m_nodes.append(node); m_root_node = node; return node; } StringView m_program; Vector m_lines; Vector m_tokens; State m_state; Vector m_saved_states; RefPtr m_root_node; NonnullRefPtrVector m_nodes; Vector m_errors; }; }