Parser.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /*
  2. * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2022, kleines Filmröllchen <filmroellchen@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include "Parser.h"
  8. #include "AST.h"
  9. #include "Lexer.h"
  10. #include <AK/Error.h>
  11. #include <AK/GenericLexer.h>
  12. #include <AK/JsonObject.h>
  13. #include <AK/JsonValue.h>
  14. #include <AK/Queue.h>
  15. #include <AK/RefPtr.h>
  16. namespace GUI::GML {
  17. static ErrorOr<NonnullRefPtr<Object>> parse_gml_object(Queue<Token>& tokens)
  18. {
  19. auto object = TRY(try_make_ref_counted<Object>());
  20. auto peek = [&] {
  21. if (tokens.is_empty())
  22. return Token::Type::Unknown;
  23. return tokens.head().m_type;
  24. };
  25. while (peek() == Token::Type::Comment) {
  26. dbgln("found comment {}", tokens.head().m_view);
  27. TRY(object->add_child(TRY(Node::from_token<Comment>(tokens.dequeue()))));
  28. }
  29. if (peek() != Token::Type::ClassMarker)
  30. return Error::from_string_literal("Expected class marker"sv);
  31. tokens.dequeue();
  32. if (peek() != Token::Type::ClassName)
  33. return Error::from_string_literal("Expected class name"sv);
  34. auto class_name = tokens.dequeue();
  35. object->set_name(class_name.m_view);
  36. if (peek() != Token::Type::LeftCurly) {
  37. // Empty object
  38. return object;
  39. }
  40. tokens.dequeue();
  41. for (;;) {
  42. if (peek() == Token::Type::RightCurly) {
  43. // End of object
  44. break;
  45. }
  46. if (peek() == Token::Type::ClassMarker) {
  47. // It's a child object.
  48. TRY(object->add_child(TRY(parse_gml_object(tokens))));
  49. } else if (peek() == Token::Type::Identifier) {
  50. // It's a property.
  51. auto property_name = tokens.dequeue();
  52. if (property_name.m_view.is_empty())
  53. return Error::from_string_literal("Expected non-empty property name"sv);
  54. if (peek() != Token::Type::Colon)
  55. return Error::from_string_literal("Expected ':'"sv);
  56. tokens.dequeue();
  57. RefPtr<ValueNode> value;
  58. if (peek() == Token::Type::ClassMarker)
  59. value = TRY(parse_gml_object(tokens));
  60. else if (peek() == Token::Type::JsonValue)
  61. value = TRY(try_make_ref_counted<JsonValueNode>(TRY(JsonValueNode::from_string(tokens.dequeue().m_view))));
  62. auto property = TRY(try_make_ref_counted<KeyValuePair>(property_name.m_view, value.release_nonnull()));
  63. TRY(object->add_child(property));
  64. } else if (peek() == Token::Type::Comment) {
  65. TRY(object->add_child(TRY(Node::from_token<Comment>(tokens.dequeue()))));
  66. } else {
  67. return Error::from_string_literal("Expected child, property, comment, or }}"sv);
  68. }
  69. }
  70. if (peek() != Token::Type::RightCurly)
  71. return Error::from_string_literal("Expected }}"sv);
  72. tokens.dequeue();
  73. return object;
  74. }
  75. ErrorOr<NonnullRefPtr<GMLFile>> parse_gml(StringView string)
  76. {
  77. auto lexer = Lexer(string);
  78. Queue<Token> tokens;
  79. for (auto& token : lexer.lex())
  80. tokens.enqueue(token);
  81. auto file = TRY(try_make_ref_counted<GMLFile>());
  82. auto peek = [&] {
  83. if (tokens.is_empty())
  84. return Token::Type::Unknown;
  85. return tokens.head().m_type;
  86. };
  87. while (peek() == Token::Type::Comment)
  88. TRY(file->add_child(TRY(Node::from_token<Comment>(tokens.dequeue()))));
  89. TRY(file->add_child(TRY(parse_gml_object(tokens))));
  90. while (!tokens.is_empty())
  91. TRY(file->add_child(TRY(Node::from_token<Comment>(tokens.dequeue()))));
  92. return file;
  93. }
  94. }