diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/SpecParser.cpp b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/SpecParser.cpp index 6c008966a08..5fc673f493c 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/SpecParser.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/SpecParser.cpp @@ -239,7 +239,7 @@ NonnullOwnPtr SpecificationClause::create(SpecificationPars [&](AK::Empty const&) { result = make(move(specification_clause)); }, - [&](ClauseHeader::FunctionDefinition const&) { + [&](OneOf auto const&) { result = make(move(specification_clause)); }); @@ -346,18 +346,26 @@ bool SpecFunction::post_initialize(XML::Node const* element) m_id = maybe_id.value(); } - auto maybe_abstract_operation_id = get_attribute_by_name(element, attribute_aoid); - if (maybe_abstract_operation_id.has_value()) - m_name = maybe_abstract_operation_id.value(); + m_header.header.visit( + [&](ClauseHeader::AbstractOperation const& abstract_operation) { + auto maybe_abstract_operation_id = get_attribute_by_name(element, attribute_aoid); + if (maybe_abstract_operation_id.has_value()) + m_name = MUST(String::from_utf8(maybe_abstract_operation_id.value())); - m_section_number = m_header.section_number; - auto const& [function_name, arguments] = m_header.header.get(); - m_arguments = arguments; + auto const& [function_name, arguments] = abstract_operation; + m_arguments = arguments; - if (m_name != function_name) { - ctx.diag().warn(ctx.location_from_xml_offset(element->offset), - "function name in header and [aoid] do not match"); - } + if (m_name != function_name) { + ctx.diag().warn(ctx.location_from_xml_offset(element->offset), + "function name in header and [aoid] do not match"); + } + }, + [&](ClauseHeader::Accessor const& accessor) { + m_name = MUST(String::formatted("%get {}%", MUST(String::join("."sv, accessor.qualified_name)))); + }, + [&](auto const&) { + VERIFY_NOT_REACHED(); + }); Vector algorithm_nodes; @@ -399,12 +407,12 @@ void SpecFunction::do_collect(TranslationUnitRef translation_unit) translation_unit->adopt_function(make_ref_counted(m_name, m_algorithm.tree(), move(m_arguments))); } -Specification Specification::create(SpecificationParsingContext& ctx, XML::Node const* element) +NonnullOwnPtr Specification::create(SpecificationParsingContext& ctx, XML::Node const* element) { VERIFY(element->as_element().name == tag_specification); - Specification specification; - specification.parse(ctx, element); + auto specification = make(); + specification->parse(ctx, element); return specification; } @@ -486,7 +494,7 @@ void SpecParsingStep::run(TranslationUnitRef translation_unit) return; } - auto specification = Specification::create(ctx, &root); - specification.collect_into(translation_unit); + m_specification = Specification::create(ctx, &root); + m_specification->collect_into(translation_unit); } } diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/SpecParser.h b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/SpecParser.h index 26cd33a7070..cc471c2aefe 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/SpecParser.h +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/SpecParser.h @@ -132,9 +132,8 @@ protected: void do_collect(TranslationUnitRef translation_unit) override; private: - StringView m_section_number; StringView m_id; - StringView m_name; + String m_name; Vector m_arguments; Algorithm m_algorithm; @@ -142,7 +141,7 @@ private: class Specification { public: - static Specification create(SpecificationParsingContext& ctx, XML::Node const* element); + static NonnullOwnPtr create(SpecificationParsingContext& ctx, XML::Node const* element); void collect_into(TranslationUnitRef translation_unit); @@ -161,6 +160,8 @@ public: private: OwnPtr m_document; + OwnPtr m_specification; + ByteBuffer m_input; }; diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.cpp b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.cpp index 1330cf0ff11..6e637e000fa 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.cpp @@ -599,6 +599,69 @@ TextParseErrorOr TextParser::parse_step_with_substeps(Tree substeps) return TextParseError {}; } +// :== (. )* +TextParseErrorOr> TextParser::parse_qualified_name() +{ + Vector qualified_name; + qualified_name.append(TRY(consume_token_with_type(TokenType::Word)).data); + while (true) { + auto token_or_error = consume_token_with_type(TokenType::MemberAccess); + if (token_or_error.is_error()) + return qualified_name; + qualified_name.append(TRY(consume_token_with_type(TokenType::Word)).data); + } +} + +// :== '(' ( (, )*)? ')' +TextParseErrorOr> TextParser::parse_function_arguments_in_declaration() +{ + Vector arguments; + TRY(consume_token_with_type(TokenType::ParenOpen)); + while (true) { + if (arguments.is_empty()) { + auto argument = TRY(consume_token_with_one_of_types({ TokenType::ParenClose, TokenType::Identifier })); + if (argument.type == TokenType::ParenClose) + break; + arguments.append({ argument.data }); + } else { + arguments.append({ TRY(consume_token_with_type(TokenType::Identifier)).data }); + } + auto next_token = TRY(consume_token_with_one_of_types({ TokenType::ParenClose, TokenType::Comma })); + if (next_token.type == TokenType::ParenClose) + break; + } + return arguments; +} + +// :== $ +TextParseErrorOr TextParser::parse_abstract_operation_declaration() +{ + auto rollback = rollback_point(); + + ClauseHeader::AbstractOperation function_definition; + function_definition.name = TRY(consume_token_with_type(TokenType::Word)).data; + function_definition.arguments = TRY(parse_function_arguments_in_declaration()); + TRY(expect_eof()); + + rollback.disarm(); + return function_definition; +} + +// :== get $ +TextParseErrorOr TextParser::parse_accessor_declaration() +{ + auto rollback = rollback_point(); + + TRY(consume_word("get"sv)); + ClauseHeader::Accessor accessor; + accessor.qualified_name = TRY(parse_qualified_name()); + TRY(expect_eof()); + + rollback.disarm(); + return accessor; +} + +// :== | TextParseErrorOr TextParser::parse_clause_header() { ClauseHeader result; @@ -606,27 +669,13 @@ TextParseErrorOr TextParser::parse_clause_header() auto section_number_token = TRY(consume_token_with_type(TokenType::SectionNumber)); result.section_number = section_number_token.data; - ClauseHeader::FunctionDefinition function_definition; - - function_definition.name = TRY(consume_token_with_type(TokenType::Word)).data; - - TRY(consume_token_with_type(TokenType::ParenOpen)); - while (true) { - if (function_definition.arguments.is_empty()) { - auto argument = TRY(consume_token_with_one_of_types({ TokenType::ParenClose, TokenType::Identifier })); - if (argument.type == TokenType::ParenClose) - break; - function_definition.arguments.append({ argument.data }); - } else { - function_definition.arguments.append({ TRY(consume_token_with_type(TokenType::Identifier)).data }); - } - auto next_token = TRY(consume_token_with_one_of_types({ TokenType::ParenClose, TokenType::Comma })); - if (next_token.type == TokenType::ParenClose) - break; + if (auto ao_declaration = parse_abstract_operation_declaration(); !ao_declaration.is_error()) { + result.header = ao_declaration.release_value(); + } else if (auto accessor = parse_accessor_declaration(); !accessor.is_error()) { + result.header = accessor.release_value(); + } else { + return TextParseError {}; } - TRY(expect_eof()); - - result.header = function_definition; return result; } diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.h b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.h index c1a66555252..7142c1521ba 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.h +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.h @@ -13,13 +13,17 @@ namespace JSSpecCompiler { struct ClauseHeader { - struct FunctionDefinition { + struct AbstractOperation { StringView name; Vector arguments; }; + struct Accessor { + Vector qualified_name; + }; + StringView section_number; - Variant header; + Variant header; }; struct TextParseError { }; @@ -86,6 +90,11 @@ private: TextParseErrorOr parse_if(Tree then_branch); TextParseErrorOr parse_else(Tree else_branch); + TextParseErrorOr> parse_qualified_name(); + TextParseErrorOr> parse_function_arguments_in_declaration(); + TextParseErrorOr parse_abstract_operation_declaration(); + TextParseErrorOr parse_accessor_declaration(); + SpecificationParsingContext& m_ctx; Vector const& m_tokens; size_t m_next_token_index = 0;