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 {};
}
// (the)? <record_name> { (<name>: <value>,)* }
// <record_initialization> :== (the)? <record_name> { (<name>: <value>,)* }
TextParseErrorOr<Tree> TextParser::parse_record_direct_list_initialization()
{
auto rollback = rollback_point();
@ -194,16 +194,52 @@ TextParseErrorOr<Tree> TextParser::parse_list_initialization()
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>
TextParseErrorOr<Tree> TextParser::parse_expression()
{
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) \
do { \
if (expr) { \
@ -320,9 +356,6 @@ TextParseErrorOr<Tree> 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);
@ -345,39 +378,14 @@ TextParseErrorOr<Tree> TextParser::parse_expression()
stack.append(token);
}
} else {
NullableTree expression;
if (token.type == TokenType::Identifier) {
expression = make_ref_counted<UnresolvedReference>(token.data);
} else if (token.type == TokenType::WellKnownValue) {
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 (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);
if (auto expression = parse_value(); !expression.is_error()) {
is_consumed = true;
THROW_PARSE_ERROR_IF(last_element_type == ExpressionType);
stack.append(expression.release_value());
merge_pre_merged();
} else {
break;
}
THROW_PARSE_ERROR_IF(last_element_type == ExpressionType);
stack.append(expression.release_nonnull());
merge_pre_merged();
}
if (!is_consumed)

View file

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