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

LibJS: Add Parser::syntax_error() helper

Instead of having fprintf()s all over the place we can now use
syntax_error("message") or syntax_error("message", line, column).

This takes care of a consistent format, appending a newline and getting
the line number and column of the current token if the last two params
are omitted.
This commit is contained in:
Linus Groh 2020-04-29 21:37:51 +01:00 committed by Andreas Kling
parent 85fd0d2187
commit 624eaa32af
2 changed files with 14 additions and 18 deletions

View file

@ -259,7 +259,6 @@ NonnullRefPtr<Statement> Parser::parse_statement()
consume_or_insert_semicolon(); consume_or_insert_semicolon();
return create_ast_node<ExpressionStatement>(move(expr)); return create_ast_node<ExpressionStatement>(move(expr));
} }
m_parser_state.m_has_errors = true;
expected("statement (missing switch case)"); expected("statement (missing switch case)");
consume(); consume();
return create_ast_node<ErrorStatement>(); return create_ast_node<ErrorStatement>();
@ -390,7 +389,6 @@ NonnullRefPtr<Expression> Parser::parse_primary_expression()
case TokenType::New: case TokenType::New:
return parse_new_expression(); return parse_new_expression();
default: default:
m_parser_state.m_has_errors = true;
expected("primary expression (missing switch case)"); expected("primary expression (missing switch case)");
consume(); consume();
return create_ast_node<ErrorExpression>(); return create_ast_node<ErrorExpression>();
@ -430,7 +428,6 @@ NonnullRefPtr<Expression> Parser::parse_unary_prefixed_expression()
consume(); consume();
return create_ast_node<UnaryExpression>(UnaryOp::Delete, parse_expression(precedence, associativity)); return create_ast_node<UnaryExpression>(UnaryOp::Delete, parse_expression(precedence, associativity));
default: default:
m_parser_state.m_has_errors = true;
expected("primary expression (missing switch case)"); expected("primary expression (missing switch case)");
consume(); consume();
return create_ast_node<ErrorExpression>(); return create_ast_node<ErrorExpression>();
@ -468,12 +465,7 @@ NonnullRefPtr<ObjectExpression> Parser::parse_object_expression()
need_colon = false; need_colon = false;
is_spread = true; is_spread = true;
} else { } else {
m_parser_state.m_has_errors = true; syntax_error(String::format("Unexpected token %s as member in object initialization. Expected a numeric literal, string literal or identifier", m_parser_state.m_current_token.name()));
auto& current_token = m_parser_state.m_current_token;
fprintf(stderr, "Syntax Error: Unexpected token %s as member in object initialization. Expected a numeric literal, string literal or identifier (line: %zu, column: %zu))\n",
current_token.name(),
current_token.line_number(),
current_token.line_column());
consume(); consume();
continue; continue;
} }
@ -662,7 +654,6 @@ NonnullRefPtr<Expression> Parser::parse_secondary_expression(NonnullRefPtr<Expre
case TokenType::QuestionMark: case TokenType::QuestionMark:
return parse_conditional_expression(move(lhs)); return parse_conditional_expression(move(lhs));
default: default:
m_parser_state.m_has_errors = true;
expected("secondary expression (missing switch case)"); expected("secondary expression (missing switch case)");
consume(); consume();
return create_ast_node<ErrorExpression>(); return create_ast_node<ErrorExpression>();
@ -829,8 +820,7 @@ NonnullRefPtr<ThrowStatement> Parser::parse_throw_statement()
// Automatic semicolon insertion: terminate statement when throw is followed by newline // Automatic semicolon insertion: terminate statement when throw is followed by newline
if (m_parser_state.m_current_token.trivia().contains('\n')) { if (m_parser_state.m_current_token.trivia().contains('\n')) {
m_parser_state.m_has_errors = true; syntax_error("No line break is allowed between 'throw' and its expression");
fprintf(stderr, "Syntax Error: no line break is allowed between 'throw' and its expression\n");
return create_ast_node<ThrowStatement>(create_ast_node<ErrorExpression>()); return create_ast_node<ThrowStatement>(create_ast_node<ErrorExpression>());
} }
@ -1197,14 +1187,18 @@ Token Parser::consume(TokenType expected_type)
} }
void Parser::expected(const char* what) void Parser::expected(const char* what)
{
syntax_error(String::format("Unexpected token %s. Expected %s", m_parser_state.m_current_token.name(), what));
}
void Parser::syntax_error(const String& message, size_t line, size_t column)
{ {
m_parser_state.m_has_errors = true; m_parser_state.m_has_errors = true;
auto& current_token = m_parser_state.m_current_token; if (line == 0 || column == 0) {
fprintf(stderr, "Syntax Error: Unexpected token %s. Expected %s (line: %zu, column: %zu)\n", line = m_parser_state.m_current_token.line_number();
current_token.name(), column = m_parser_state.m_current_token.line_column();
what, }
current_token.line_number(), fprintf(stderr, "Syntax Error: %s (line: %zu, column: %zu)\n", message.characters(), line, column);
current_token.line_column());
} }
void Parser::save_state() void Parser::save_state()
@ -1218,4 +1212,5 @@ void Parser::load_state()
m_parser_state = m_saved_state.value(); m_parser_state = m_saved_state.value();
m_saved_state.clear(); m_saved_state.clear();
} }
} }

View file

@ -89,6 +89,7 @@ private:
bool match(TokenType type) const; bool match(TokenType type) const;
bool done() const; bool done() const;
void expected(const char* what); void expected(const char* what);
void syntax_error(const String& message, size_t line = 0, size_t column = 0);
Token consume(); Token consume();
Token consume(TokenType type); Token consume(TokenType type);
void consume_or_insert_semicolon(); void consume_or_insert_semicolon();