/* * Copyright (c) 2021, Itamar S. * Copyright (c) 2023, Volodymyr V. * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include namespace GLSL { class Parser final { AK_MAKE_NONCOPYABLE(Parser); public: explicit Parser(Vector tokens, String const& filename); ~Parser() = default; ErrorOr> parse(); bool eof() const; RefPtr root_node() const { return m_root_node; } void print_tokens() const; Vector const& tokens() const { return m_tokens; } Vector const& errors() const { return m_errors; } private: enum class DeclarationType { Function, Variable, Struct, }; ErrorOr> match_declaration_in_translation_unit(); ErrorOr match_struct_declaration(); ErrorOr match_function_declaration(); ErrorOr match_variable_declaration(); ErrorOr match_block_statement(); ErrorOr match_expression(); ErrorOr match_name(); ErrorOr match_string_literal(); ErrorOr match_numeric_literal(); ErrorOr match_boolean_literal(); ErrorOr match_type(); ErrorOr>> parse_declarations_in_translation_unit(ASTNode const& parent); ErrorOr> parse_single_declaration_in_translation_unit(ASTNode const& parent); ErrorOr> parse_declaration(ASTNode const& parent, DeclarationType); ErrorOr> parse_struct_declaration(ASTNode const& parent); ErrorOr>> parse_struct_members(StructDeclaration& parent); ErrorOr> parse_function_declaration(ASTNode const& parent); ErrorOr>> parse_parameter_list(ASTNode const& parent); ErrorOr> parse_function_definition(ASTNode const& parent); ErrorOr> parse_variable_declaration(ASTNode const& parent, bool expect_semicolon = true); ErrorOr> parse_statement(ASTNode const& parent); ErrorOr> parse_block_statement(ASTNode const& parent); ErrorOr> parse_if_statement(ASTNode const& parent); ErrorOr> parse_for_statement(ASTNode const& parent); ErrorOr> parse_return_statement(ASTNode const& parent); enum class Associativity { LeftToRight, RightToLeft }; static HashMap s_operator_associativity; ErrorOr> parse_expression(ASTNode const& parent, int min_precedence = 0, Associativity associativity = Associativity::LeftToRight); ErrorOr> parse_unary_expression(ASTNode const& parent); ErrorOr>> parse_function_call_args(ASTNode const& parent); ErrorOr> parse_boolean_literal(ASTNode const& parent); ErrorOr> parse_numeric_literal(ASTNode const& parent); ErrorOr> parse_string_literal(ASTNode const& parent); ErrorOr> parse_name(ASTNode const& parent, bool allow_sized_name = false); ErrorOr> parse_type(ASTNode const& parent); bool match_unary_op(); ErrorOr consume_unary_op(); bool match_binary_op(); ErrorOr peek_binary_op(); bool match_storage_qualifier(); ErrorOr consume_storage_qualifier(); Token peek(size_t offset = 0) const; Optional peek(Token::Type) const; bool match(Token::Type); bool match_keyword(StringView); bool match_preprocessor(); ErrorOr consume(); ErrorOr consume(Token::Type); ErrorOr consume_keyword(StringView); ErrorOr consume_preprocessor(); Position position() const; Position previous_token_end() const; Optional index_of_token_at(Position pos) const; Vector tokens_in_range(Position start, Position end) const; ErrorOr text_in_range(Position start, Position end) const; ErrorOr error(StringView message = {}); template NonnullRefPtr create_ast_node(ASTNode const& parent, Position const& start, Optional end, Args&&... args) { auto node = adopt_ref(*new T(&parent, start, end, m_filename, forward(args)...)); return node; } NonnullRefPtr create_root_ast_node(Position const& start, Position end) { auto node = adopt_ref(*new TranslationUnit(nullptr, start, end, m_filename)); m_root_node = node; return node; } DummyAstNode& get_dummy_node() { static NonnullRefPtr dummy = adopt_ref(*new DummyAstNode(nullptr, {}, {}, {})); return dummy; } struct State { size_t token_index { 0 }; }; void save_state(); void load_state(); State m_state; Vector m_saved_states; String m_filename; Vector m_tokens; RefPtr m_root_node; Vector m_errors; }; }