diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/AST.h b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/AST.h index fcc77f569d4..cf053a8bf82 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/AST.h +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/AST.h @@ -523,6 +523,20 @@ protected: void dump_tree(StringBuilder& builder) override; }; +class Enumerator : public Expression { +public: + Enumerator(Badge, StringView value) + : m_value(value) + { + } + +protected: + void dump_tree(StringBuilder& builder) override; + +private: + StringView m_value; +}; + class FunctionPointer : public Expression { public: FunctionPointer(FunctionDeclarationRef declaration) diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/ASTPrinting.cpp b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/ASTPrinting.cpp index da8c71bb026..bb2dc687d2c 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/ASTPrinting.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/ASTPrinting.cpp @@ -178,6 +178,11 @@ void Variable::dump_tree(StringBuilder& builder) dump_node(builder, "Var {}", name()); } +void Enumerator::dump_tree(StringBuilder& builder) +{ + dump_node(builder, "Enumerator {}", m_value); +} + void FunctionPointer::dump_tree(StringBuilder& builder) { dump_node(builder, "Func \"{}\"", m_declaration->m_name); diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Forward.h b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Forward.h index 4323b06abb7..e0be9e2c690 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Forward.h +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Forward.h @@ -45,6 +45,8 @@ class TreeList; class RecordDirectListInitialization; class FunctionCall; class SlotName; +class Enumerator; +using EnumeratorRef = NonnullRefPtr; class Variable; using VariableRef = NonnullRefPtr; class FunctionPointer; diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Function.cpp b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Function.cpp index c91ad43c2a7..23b89e0b280 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Function.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Function.cpp @@ -40,6 +40,16 @@ FunctionDeclarationRef TranslationUnit::find_declaration_by_name(StringView name return it->value; } +EnumeratorRef TranslationUnit::get_node_for_enumerator_value(StringView value) +{ + if (auto it = m_enumerator_nodes.find(value); it != m_enumerator_nodes.end()) + return it->value; + + auto enumerator = NonnullRefPtr(NonnullRefPtr::Adopt, *new Enumerator { {}, value }); + m_enumerator_nodes.set(value, enumerator); + return enumerator; +} + FunctionDeclaration::FunctionDeclaration(StringView name, Vector&& arguments) : m_name(name) , m_arguments(arguments) diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Function.h b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Function.h index fae8563eb02..4eb7acd5897 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Function.h +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Function.h @@ -30,12 +30,15 @@ public: DiagnosticEngine& diag() { return m_diagnostic_engine; } Vector functions_to_compile() const { return m_functions_to_compile; } + EnumeratorRef get_node_for_enumerator_value(StringView value); + private: StringView m_filename; DiagnosticEngine m_diagnostic_engine; Vector m_functions_to_compile; Vector> m_declarations_owner; HashMap m_function_index; + HashMap m_enumerator_nodes; }; struct FunctionArgument { diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/Lexer.cpp b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/Lexer.cpp index b694488bade..ef97a33e919 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/Lexer.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/Lexer.cpp @@ -185,6 +185,15 @@ void tokenize_tree(SpecificationParsingContext& ctx, TokenizerState& state, XML: return; } + if (element.name == tag_emu_const) { + auto maybe_contents = get_text_contents(child); + if (!maybe_contents.has_value()) + report_error("malformed subtree, expected single text child node"); + + tokens.append({ TokenType::Enumerator, maybe_contents.value_or(""sv), move(child_location) }); + return; + } + if (tree_type == TreeType::Header && element.name == tag_span) { auto element_class = get_attribute_by_name(child, attribute_class); if (element_class != class_secnum) diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/Lexer.h b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/Lexer.h index a2b173cdcf8..1b6ba0dd363 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/Lexer.h +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/Lexer.h @@ -12,6 +12,7 @@ namespace JSSpecCompiler { inline constexpr StringView tag_emu_alg = "emu-alg"sv; inline constexpr StringView tag_emu_clause = "emu-clause"sv; +inline constexpr StringView tag_emu_const = "emu-const"sv; inline constexpr StringView tag_emu_import = "emu-import"sv; inline constexpr StringView tag_emu_intro = "emu-intro"sv; inline constexpr StringView tag_emu_val = "emu-val"sv; diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/SpecParser.cpp b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/SpecParser.cpp index c56ec18a363..6c008966a08 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/SpecParser.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/SpecParser.cpp @@ -16,6 +16,11 @@ namespace JSSpecCompiler { +TranslationUnitRef SpecificationParsingContext::translation_unit() +{ + return m_translation_unit; +} + DiagnosticEngine& SpecificationParsingContext::diag() { return m_translation_unit->diag(); diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/SpecParser.h b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/SpecParser.h index dcb2f2e2654..26cd33a7070 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/SpecParser.h +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/SpecParser.h @@ -26,6 +26,7 @@ public: { } + TranslationUnitRef translation_unit(); DiagnosticEngine& diag(); template diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.cpp b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.cpp index 8a607d5559d..ca2f1ee2209 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.cpp @@ -316,6 +316,8 @@ TextParseErrorOr TextParser::parse_expression() } } VERIFY(expression); + } else if (token.type == TokenType::Enumerator) { + expression = m_ctx.translation_unit()->get_node_for_enumerator_value(token.data); } else if (token.type == TokenType::Number) { expression = make_ref_counted(MUST(Crypto::BigFraction::from_string(token.data))); } else if (token.type == TokenType::String) { diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/Token.h b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/Token.h index 79bd62483c8..5499a546ad4 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/Token.h +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/Token.h @@ -30,6 +30,7 @@ constexpr i32 closing_bracket_precedence = 18; F(Comma, 17, Invalid, Comma, Invalid, "','") \ F(Division, 5, Invalid, Division, Invalid, "division") \ F(Dot, -1, Invalid, Invalid, Invalid, "punctuation mark '.'") \ + F(Enumerator, -1, Invalid, Invalid, Invalid, "enumerator") \ F(Equals, 10, Invalid, CompareEqual, Invalid, "equals") \ F(ExclamationMark, 3, AssertCompletion, Invalid, Invalid, "exclamation mark") \ F(FunctionCall, 2, Invalid, FunctionCall, Invalid, "function call token") \ diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Tests/spec-parsing.xml b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Tests/spec-parsing.xml index 7fce954d55d..22dd3b2250d 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Tests/spec-parsing.xml +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Tests/spec-parsing.xml @@ -41,4 +41,12 @@ + +

4 Enumerators ( )

+ +
    +
  1. Return ? WellKnownConstants(enumerator).
  2. +
+
+
diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Tests/spec-parsing.xml.expectation b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Tests/spec-parsing.xml.expectation index 3583354b249..5826154115a 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Tests/spec-parsing.xml.expectation +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Tests/spec-parsing.xml.expectation @@ -54,3 +54,11 @@ TreeList Func "WellKnownConstants" Var a +Enumerators(): +TreeList + ReturnNode + UnaryOperation ReturnIfAbrubt + FunctionCall + Func "WellKnownConstants" + Enumerator enumerator +