LibJS: Parse "this" as ThisExpression
This commit is contained in:
parent
110ca6b0b6
commit
f8f65053bd
Notes:
sideshowbarker
2024-07-19 07:39:59 +09:00
Author: https://github.com/sunverwerth Commit: https://github.com/SerenityOS/serenity/commit/f8f65053bdb Pull-request: https://github.com/SerenityOS/serenity/pull/1772
6 changed files with 37 additions and 17 deletions
|
@ -662,6 +662,16 @@ void Identifier::dump(int indent) const
|
|||
printf("Identifier \"%s\"\n", m_string.characters());
|
||||
}
|
||||
|
||||
Value ThisExpression::execute(Interpreter& interpreter) const
|
||||
{
|
||||
return interpreter.this_value();
|
||||
}
|
||||
|
||||
void ThisExpression::dump(int indent) const
|
||||
{
|
||||
ASTNode::dump(indent);
|
||||
}
|
||||
|
||||
Value AssignmentExpression::execute(Interpreter& interpreter) const
|
||||
{
|
||||
auto rhs_result = m_rhs->execute(interpreter);
|
||||
|
|
|
@ -502,6 +502,15 @@ private:
|
|||
FlyString m_string;
|
||||
};
|
||||
|
||||
class ThisExpression final : public Expression {
|
||||
public:
|
||||
virtual Value execute(Interpreter&) const override;
|
||||
virtual void dump(int indent) const override;
|
||||
|
||||
private:
|
||||
virtual const char* class_name() const override { return "ThisExpression"; }
|
||||
};
|
||||
|
||||
class CallExpression : public Expression {
|
||||
public:
|
||||
CallExpression(NonnullRefPtr<Expression> callee, NonnullRefPtrVector<Expression> arguments = {})
|
||||
|
|
|
@ -158,10 +158,6 @@ void Interpreter::set_variable(const FlyString& name, Value value, bool first_as
|
|||
|
||||
Optional<Value> Interpreter::get_variable(const FlyString& name)
|
||||
{
|
||||
static FlyString this_name = "this";
|
||||
if (name == this_name)
|
||||
return this_value();
|
||||
|
||||
for (ssize_t i = m_scope_stack.size() - 1; i >= 0; --i) {
|
||||
auto& scope = m_scope_stack.at(i);
|
||||
auto value = scope.variables.get(name);
|
||||
|
|
|
@ -66,6 +66,7 @@ Lexer::Lexer(StringView source)
|
|||
s_keywords.set("null", TokenType::NullLiteral);
|
||||
s_keywords.set("return", TokenType::Return);
|
||||
s_keywords.set("switch", TokenType::Switch);
|
||||
s_keywords.set("this", TokenType::This);
|
||||
s_keywords.set("throw", TokenType::Throw);
|
||||
s_keywords.set("true", TokenType::BoolLiteral);
|
||||
s_keywords.set("try", TokenType::Try);
|
||||
|
|
|
@ -317,6 +317,9 @@ NonnullRefPtr<Expression> Parser::parse_primary_expression()
|
|||
consume(TokenType::ParenClose);
|
||||
return expression;
|
||||
}
|
||||
case TokenType::This:
|
||||
consume();
|
||||
return create_ast_node<ThisExpression>();
|
||||
case TokenType::Identifier: {
|
||||
auto arrow_function_result = try_parse_arrow_function_expression(false);
|
||||
if (!arrow_function_result.is_null()) {
|
||||
|
@ -400,14 +403,13 @@ NonnullRefPtr<ObjectExpression> Parser::parse_object_expression()
|
|||
m_parser_state.m_has_errors = true;
|
||||
auto& current_token = m_parser_state.m_current_token;
|
||||
fprintf(stderr, "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());
|
||||
current_token.name(),
|
||||
current_token.line_number(),
|
||||
current_token.line_column());
|
||||
consume();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (match(TokenType::Colon)) {
|
||||
consume(TokenType::Colon);
|
||||
properties.set(property_name, parse_expression(0));
|
||||
|
@ -487,7 +489,7 @@ NonnullRefPtr<Expression> Parser::parse_secondary_expression(NonnullRefPtr<Expre
|
|||
case TokenType::Percent:
|
||||
consume();
|
||||
return create_ast_node<BinaryExpression>(BinaryOp::Modulo, move(lhs), parse_expression(min_precedence, associativity));
|
||||
case TokenType::DoubleAsterisk:
|
||||
case TokenType::DoubleAsterisk:
|
||||
consume();
|
||||
return create_ast_node<BinaryExpression>(BinaryOp::Exponentiation, move(lhs), parse_expression(min_precedence, associativity));
|
||||
case TokenType::GreaterThan:
|
||||
|
@ -905,6 +907,7 @@ bool Parser::match_expression() const
|
|||
|| type == TokenType::BracketOpen
|
||||
|| type == TokenType::ParenOpen
|
||||
|| type == TokenType::Function
|
||||
|| type == TokenType::This
|
||||
|| match_unary_prefixed_expression();
|
||||
}
|
||||
|
||||
|
@ -997,10 +1000,10 @@ Token Parser::consume(TokenType type)
|
|||
m_parser_state.m_has_errors = true;
|
||||
auto& current_token = m_parser_state.m_current_token;
|
||||
fprintf(stderr, "Error: Unexpected token %s. Expected %s (line: %zu, column: %zu))\n",
|
||||
current_token.name(),
|
||||
Token::name(type),
|
||||
current_token.line_number(),
|
||||
current_token.line_column());
|
||||
current_token.name(),
|
||||
Token::name(type),
|
||||
current_token.line_number(),
|
||||
current_token.line_column());
|
||||
}
|
||||
return consume();
|
||||
}
|
||||
|
@ -1010,10 +1013,10 @@ void Parser::expected(const char* what)
|
|||
m_parser_state.m_has_errors = true;
|
||||
auto& current_token = m_parser_state.m_current_token;
|
||||
fprintf(stderr, "Error: Unexpected token %s. Expected %s (line: %zu, column: %zu)\n",
|
||||
current_token.name(),
|
||||
what,
|
||||
current_token.line_number(),
|
||||
current_token.line_column());
|
||||
current_token.name(),
|
||||
what,
|
||||
current_token.line_number(),
|
||||
current_token.line_column());
|
||||
}
|
||||
|
||||
void Parser::save_state()
|
||||
|
|
|
@ -111,6 +111,7 @@ namespace JS {
|
|||
__ENUMERATE_JS_TOKEN(SlashEquals) \
|
||||
__ENUMERATE_JS_TOKEN(StringLiteral) \
|
||||
__ENUMERATE_JS_TOKEN(Switch) \
|
||||
__ENUMERATE_JS_TOKEN(This) \
|
||||
__ENUMERATE_JS_TOKEN(Throw) \
|
||||
__ENUMERATE_JS_TOKEN(Tilde) \
|
||||
__ENUMERATE_JS_TOKEN(Try) \
|
||||
|
|
Loading…
Add table
Reference in a new issue