mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 07:30:19 +00:00
LibJS: Implement ConditionalExpression (ternary "?:" operator)
This commit is contained in:
parent
522d8c5d71
commit
0622181d1f
Notes:
sideshowbarker
2024-07-19 07:58:43 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/0622181d1f8
5 changed files with 83 additions and 1 deletions
|
@ -970,4 +970,34 @@ void SwitchCase::dump(int indent) const
|
|||
}
|
||||
}
|
||||
|
||||
Value ConditionalExpression::execute(Interpreter& interpreter) const
|
||||
{
|
||||
auto test_result = m_test->execute(interpreter);
|
||||
if (interpreter.exception())
|
||||
return {};
|
||||
Value result;
|
||||
if (test_result.to_boolean()) {
|
||||
result = m_consequent->execute(interpreter);
|
||||
} else {
|
||||
result = m_alternate->execute(interpreter);
|
||||
}
|
||||
if (interpreter.exception())
|
||||
return {};
|
||||
return result;
|
||||
}
|
||||
|
||||
void ConditionalExpression::dump(int indent) const
|
||||
{
|
||||
ASTNode::dump(indent);
|
||||
print_indent(indent);
|
||||
printf("(Test)\n");
|
||||
m_test->dump(indent + 1);
|
||||
print_indent(indent);
|
||||
printf("(Consequent)\n");
|
||||
m_test->dump(indent + 1);
|
||||
print_indent(indent);
|
||||
printf("(Alternate)\n");
|
||||
m_test->dump(indent + 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -639,6 +639,26 @@ private:
|
|||
bool m_computed { false };
|
||||
};
|
||||
|
||||
class ConditionalExpression final : public Expression {
|
||||
public:
|
||||
ConditionalExpression(NonnullRefPtr<Expression> test, NonnullRefPtr<Expression> consequent, NonnullRefPtr<Expression> alternate)
|
||||
: m_test(move(test))
|
||||
, m_consequent(move(consequent))
|
||||
, m_alternate(move(alternate))
|
||||
{
|
||||
}
|
||||
|
||||
virtual void dump(int indent) const override;
|
||||
virtual Value execute(Interpreter&) const override;
|
||||
|
||||
private:
|
||||
virtual const char* class_name() const override { return "ConditionalExpression"; }
|
||||
|
||||
NonnullRefPtr<Expression> m_test;
|
||||
NonnullRefPtr<Expression> m_consequent;
|
||||
NonnullRefPtr<Expression> m_alternate;
|
||||
};
|
||||
|
||||
class CatchClause final : public ASTNode {
|
||||
public:
|
||||
CatchClause(const FlyString& parameter, NonnullRefPtr<BlockStatement> body)
|
||||
|
|
|
@ -516,6 +516,8 @@ NonnullRefPtr<Expression> Parser::parse_secondary_expression(NonnullRefPtr<Expre
|
|||
case TokenType::DoublePipe:
|
||||
consume();
|
||||
return create_ast_node<LogicalExpression>(LogicalOp::Or, move(lhs), parse_expression(min_precedence, associativity));
|
||||
case TokenType::QuestionMark:
|
||||
return parse_conditional_expression(move(lhs));
|
||||
default:
|
||||
m_parser_state.m_has_errors = true;
|
||||
expected("secondary expression (missing switch case)");
|
||||
|
@ -660,6 +662,15 @@ NonnullRefPtr<BreakStatement> Parser::parse_break_statement()
|
|||
return create_ast_node<BreakStatement>();
|
||||
}
|
||||
|
||||
NonnullRefPtr<ConditionalExpression> Parser::parse_conditional_expression(NonnullRefPtr<Expression> test)
|
||||
{
|
||||
consume(TokenType::QuestionMark);
|
||||
auto consequent = parse_expression(0);
|
||||
consume(TokenType::Colon);
|
||||
auto alternate = parse_expression(0);
|
||||
return create_ast_node<ConditionalExpression>(move(test), move(consequent), move(alternate));
|
||||
}
|
||||
|
||||
NonnullRefPtr<TryStatement> Parser::parse_try_statement()
|
||||
{
|
||||
consume(TokenType::Try);
|
||||
|
@ -865,7 +876,8 @@ bool Parser::match_secondary_expression() const
|
|||
|| type == TokenType::BracketOpen
|
||||
|| type == TokenType::PlusPlus
|
||||
|| type == TokenType::MinusMinus
|
||||
|| type == TokenType::Instanceof;
|
||||
|| type == TokenType::Instanceof
|
||||
|| type == TokenType::QuestionMark;
|
||||
}
|
||||
|
||||
bool Parser::match_statement() const
|
||||
|
|
|
@ -58,6 +58,7 @@ public:
|
|||
NonnullRefPtr<SwitchStatement> parse_switch_statement();
|
||||
NonnullRefPtr<SwitchCase> parse_switch_case();
|
||||
NonnullRefPtr<BreakStatement> parse_break_statement();
|
||||
NonnullRefPtr<ConditionalExpression> parse_conditional_expression(NonnullRefPtr<Expression> test);
|
||||
|
||||
NonnullRefPtr<Expression> parse_expression(int min_precedence, Associativity associate = Associativity::Right);
|
||||
NonnullRefPtr<Expression> parse_primary_expression();
|
||||
|
|
19
Libraries/LibJS/Tests/ternary-basic.js
Normal file
19
Libraries/LibJS/Tests/ternary-basic.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
function assert(x) { if (!x) throw 1; }
|
||||
|
||||
try {
|
||||
var x = 1;
|
||||
|
||||
assert(x === 1 ? true : false);
|
||||
assert(x ? x : 0);
|
||||
assert(1 < 2 ? (true) : (false));
|
||||
|
||||
var o = {};
|
||||
o.f = true;
|
||||
assert(o.f ? true : false);
|
||||
|
||||
assert(1 ? o.f : null);
|
||||
|
||||
console.log("PASS");
|
||||
} catch (e) {
|
||||
console.log("FAIL: " + e);
|
||||
}
|
Loading…
Reference in a new issue