diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/AST.cpp b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/AST.cpp index 1442ca8b52..99fd5639b8 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/AST.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/AST.cpp @@ -146,4 +146,12 @@ String Variable::name() const return MUST(String::from_utf8(m_name->m_name)); } +Vector List::subtrees() +{ + Vector result; + for (auto& element : m_elements) + result.append({ &element }); + return result; +} + } diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/AST.h b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/AST.h index e5d473b2aa..4790b8f55a 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/AST.h +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/AST.h @@ -547,6 +547,22 @@ protected: void dump_tree(StringBuilder& builder) override; }; +class List : public Expression { +public: + List(Vector&& elements) + : m_elements(elements) + { + } + + Vector subtrees() override; + +protected: + void dump_tree(StringBuilder& builder) override; + +private: + Vector m_elements; +}; + } namespace AK { diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/ASTPrinting.cpp b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/ASTPrinting.cpp index 6647c15ed7..ffad41a289 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/ASTPrinting.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/AST/ASTPrinting.cpp @@ -187,4 +187,11 @@ void FunctionPointer::dump_tree(StringBuilder& builder) dump_node(builder, "Func \"{}\"", m_declaration->m_name); } +void List::dump_tree(StringBuilder& builder) +{ + dump_node(builder, "List"); + for (auto const& element : m_elements) + element->format_tree(builder); +} + } diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/Lexer.cpp b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/Lexer.cpp index ef97a33e91..d4ba9901ed 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/Lexer.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/Lexer.cpp @@ -64,6 +64,8 @@ void tokenize_string(SpecificationParsingContext& ctx, XML::Node const* node, St { ">"sv, TokenType::Greater }, { "is"sv, TokenType::Is }, { "<"sv, TokenType::Less }, + { "»"sv, TokenType::ListEnd }, + { "«"sv, TokenType::ListStart }, { "."sv, TokenType::MemberAccess }, { "×"sv, TokenType::Multiplication }, { "is not equal to"sv, TokenType::NotEquals }, diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.cpp b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.cpp index 51718cade4..1e1f9a7df0 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.cpp @@ -170,6 +170,30 @@ TextParseErrorOr> TextParser::parse_function_arguments() return arguments; } +// :== « ( (, )*)? » +TextParseErrorOr TextParser::parse_list_initialization() +{ + auto rollback = rollback_point(); + + TRY(consume_token_with_type(TokenType::ListStart)); + + if (!consume_token_with_type(TokenType::ListEnd).is_error()) { + rollback.disarm(); + return make_ref_counted(Vector {}); + } + + Vector elements; + while (true) { + elements.append(TRY(parse_expression())); + + auto token = TRY(consume_token_with_one_of_types({ TokenType::ListEnd, TokenType::Comma })); + if (token.type == TokenType::ListEnd) + break; + } + rollback.disarm(); + return make_ref_counted(move(elements)); +} + // TextParseErrorOr TextParser::parse_expression() { @@ -296,6 +320,9 @@ TextParseErrorOr TextParser::parse_expression() // This is just an opening '(' in expression. stack.append(token); } + } else if (token.type == TokenType::ListStart) { + stack.append(TRY(parse_list_initialization())); + is_consumed = true; } else if (token.is_pre_merged_binary_operator()) { THROW_PARSE_ERROR_IF(last_element_type != ExpressionType); stack.append(token); diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.h b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.h index 72d04de6b5..4457ea4435 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.h +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/TextParser.h @@ -73,6 +73,7 @@ private: TextParseErrorOr parse_record_direct_list_initialization(); TextParseErrorOr> parse_function_arguments(); + TextParseErrorOr parse_list_initialization(); TextParseErrorOr parse_expression(); TextParseErrorOr parse_condition(); TextParseErrorOr parse_return_statement(); diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/Token.h b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/Token.h index bd25bb99eb..117ffb495d 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/Token.h +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Parser/Token.h @@ -37,6 +37,8 @@ constexpr i32 closing_bracket_precedence = 18; F(Identifier, -1, Invalid, Invalid, Invalid, "identifier") \ F(Is, -1, Invalid, Invalid, Invalid, "operator is") \ F(Less, 9, Invalid, CompareLess, Invalid, "less than") \ + F(ListEnd, -1, Invalid, Invalid, Invalid, "»") \ + F(ListStart, -1, Invalid, Invalid, Invalid, "«") \ F(MemberAccess, 2, Invalid, MemberAccess, Invalid, "member access operator '.'") \ F(Multiplication, 5, Invalid, Multiplication, Invalid, "multiplication") \ F(NotEquals, 10, Invalid, CompareNotEqual, Invalid, "not equals") \ diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Tests/spec-parsing.xml b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Tests/spec-parsing.xml index 22dd3b2250..69ac82c49c 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Tests/spec-parsing.xml +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Tests/spec-parsing.xml @@ -49,4 +49,18 @@ + +

+ 5 Lists ( a, b ) +

+ +
    +
  1. Let a be « ».
  2. +
  3. Set a to « 1 ».
  4. +
  5. Set a to « 1, 2 ».
  6. +
  7. Set a to « 1, 2, 3 + 4 ».
  8. +
  9. Return unused.
  10. +
+
+
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 5826154115..27213af633 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Tests/spec-parsing.xml.expectation +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Tests/spec-parsing.xml.expectation @@ -62,3 +62,28 @@ TreeList Func "WellKnownConstants" Enumerator enumerator +Lists(a, b): +TreeList + BinaryOperation Assignment + Var a + List + BinaryOperation Assignment + Var a + List + Enumerator 1 + BinaryOperation Assignment + Var a + List + Enumerator 1 + Enumerator 2 + BinaryOperation Assignment + Var a + List + Enumerator 1 + Enumerator 2 + BinaryOperation Plus + MathematicalConstant 3 + MathematicalConstant 4 + ReturnNode + Enumerator unused +