1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 02:08:11 +00:00

JSSpecCompiler: Simplify value handling in TextParser::parse_expression

This commit is contained in:
Dan Klishch 2024-01-21 14:34:41 -05:00 committed by Andrew Kaster
parent e1a1f4ed1a
commit a9f3a14a13
2 changed files with 48 additions and 39 deletions

View file

@ -118,7 +118,7 @@ TextParseErrorOr<void> TextParser::expect_eof()
return {}; return {};
} }
// (the)? <record_name> { (<name>: <value>,)* } // <record_initialization> :== (the)? <record_name> { (<name>: <value>,)* }
TextParseErrorOr<Tree> TextParser::parse_record_direct_list_initialization() TextParseErrorOr<Tree> TextParser::parse_record_direct_list_initialization()
{ {
auto rollback = rollback_point(); auto rollback = rollback_point();
@ -194,16 +194,52 @@ TextParseErrorOr<Tree> TextParser::parse_list_initialization()
return make_ref_counted<List>(move(elements)); return make_ref_counted<List>(move(elements));
} }
// <value> :== <identifier> | <well_known_value> | <enumerator> | <number> | <string> | <list_initialization> | <record_initialization>
TextParseErrorOr<Tree> TextParser::parse_value()
{
if (auto identifier = consume_token_with_type(TokenType::Identifier); !identifier.is_error())
return make_ref_counted<UnresolvedReference>(identifier.release_value().data);
if (auto well_known_value = consume_token_with_type(TokenType::WellKnownValue); !well_known_value.is_error()) {
static constexpr struct {
StringView name;
WellKnownNode::Type type;
} translations[] = {
{ "false"sv, WellKnownNode::Type::False },
{ "null"sv, WellKnownNode::Type::Null },
{ "this"sv, WellKnownNode::Type::This },
{ "true"sv, WellKnownNode::Type::True },
{ "undefined"sv, WellKnownNode::Type::Undefined },
};
for (auto [name, type] : translations)
if (well_known_value.value().data == name)
return make_ref_counted<WellKnownNode>(type);
VERIFY_NOT_REACHED();
}
if (auto enumerator = consume_token_with_type(TokenType::Enumerator); !enumerator.is_error())
return m_ctx.translation_unit()->get_node_for_enumerator_value(enumerator.value().data);
if (auto number = consume_token_with_type(TokenType::Number); !number.is_error())
return make_ref_counted<MathematicalConstant>(MUST(Crypto::BigFraction::from_string(number.value().data)));
if (auto string = consume_token_with_type(TokenType::String); !string.is_error())
return make_ref_counted<StringLiteral>(string.value().data);
if (auto list_initialization = parse_list_initialization(); !list_initialization.is_error())
return list_initialization.release_value();
if (auto record_initialization = parse_record_direct_list_initialization(); !record_initialization.is_error())
return record_initialization.release_value();
return TextParseError {};
}
// <expr> // <expr>
TextParseErrorOr<Tree> TextParser::parse_expression() TextParseErrorOr<Tree> TextParser::parse_expression()
{ {
auto rollback = rollback_point(); auto rollback = rollback_point();
if (auto record_init = parse_record_direct_list_initialization(); !record_init.is_error()) {
rollback.disarm();
return record_init.release_value();
}
#define THROW_PARSE_ERROR_IF(expr) \ #define THROW_PARSE_ERROR_IF(expr) \
do { \ do { \
if (expr) { \ if (expr) { \
@ -320,9 +356,6 @@ TextParseErrorOr<Tree> TextParser::parse_expression()
// This is just an opening '(' in expression. // This is just an opening '(' in expression.
stack.append(token); 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()) { } else if (token.is_pre_merged_binary_operator()) {
THROW_PARSE_ERROR_IF(last_element_type != ExpressionType); THROW_PARSE_ERROR_IF(last_element_type != ExpressionType);
stack.append(token); stack.append(token);
@ -345,39 +378,14 @@ TextParseErrorOr<Tree> TextParser::parse_expression()
stack.append(token); stack.append(token);
} }
} else { } else {
NullableTree expression; if (auto expression = parse_value(); !expression.is_error()) {
if (token.type == TokenType::Identifier) { is_consumed = true;
expression = make_ref_counted<UnresolvedReference>(token.data); THROW_PARSE_ERROR_IF(last_element_type == ExpressionType);
} else if (token.type == TokenType::WellKnownValue) { stack.append(expression.release_value());
static constexpr struct { merge_pre_merged();
StringView name;
WellKnownNode::Type type;
} translations[] = {
{ "false"sv, WellKnownNode::Type::False },
{ "null"sv, WellKnownNode::Type::Null },
{ "this"sv, WellKnownNode::Type::This },
{ "true"sv, WellKnownNode::Type::True },
{ "undefined"sv, WellKnownNode::Type::Undefined },
};
for (auto [name, type] : translations) {
if (token.data == name) {
expression = make_ref_counted<WellKnownNode>(type);
break;
}
}
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<MathematicalConstant>(MUST(Crypto::BigFraction::from_string(token.data)));
} else if (token.type == TokenType::String) {
expression = make_ref_counted<StringLiteral>(token.data);
} else { } else {
break; break;
} }
THROW_PARSE_ERROR_IF(last_element_type == ExpressionType);
stack.append(expression.release_nonnull());
merge_pre_merged();
} }
if (!is_consumed) if (!is_consumed)

View file

@ -74,6 +74,7 @@ private:
TextParseErrorOr<Tree> parse_record_direct_list_initialization(); TextParseErrorOr<Tree> parse_record_direct_list_initialization();
TextParseErrorOr<Vector<Tree>> parse_function_arguments(); TextParseErrorOr<Vector<Tree>> parse_function_arguments();
TextParseErrorOr<Tree> parse_list_initialization(); TextParseErrorOr<Tree> parse_list_initialization();
TextParseErrorOr<Tree> parse_value();
TextParseErrorOr<Tree> parse_expression(); TextParseErrorOr<Tree> parse_expression();
TextParseErrorOr<Tree> parse_condition(); TextParseErrorOr<Tree> parse_condition();
TextParseErrorOr<Tree> parse_return_statement(); TextParseErrorOr<Tree> parse_return_statement();