mirror of
https://github.com/RGBCube/serenity
synced 2025-05-20 12:55:08 +00:00
JSSpecCompiler: Allow storing NullableTree
s in nodes
And use this in ElseIfBranch node.
This commit is contained in:
parent
4eede5282c
commit
092ed1cc8a
7 changed files with 56 additions and 18 deletions
|
@ -8,6 +8,29 @@
|
||||||
|
|
||||||
namespace JSSpecCompiler {
|
namespace JSSpecCompiler {
|
||||||
|
|
||||||
|
Tree NodeSubtreePointer::get(Badge<RecursiveASTVisitor>)
|
||||||
|
{
|
||||||
|
return m_tree_ptr.visit(
|
||||||
|
[&](NullableTree* nullable_tree) -> Tree {
|
||||||
|
NullableTree copy = *nullable_tree;
|
||||||
|
return copy.release_nonnull();
|
||||||
|
},
|
||||||
|
[&](Tree* tree) -> Tree {
|
||||||
|
return *tree;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeSubtreePointer::replace_subtree(Badge<RecursiveASTVisitor>, NullableTree replacement)
|
||||||
|
{
|
||||||
|
m_tree_ptr.visit(
|
||||||
|
[&](NullableTree* nullable_tree) {
|
||||||
|
*nullable_tree = replacement;
|
||||||
|
},
|
||||||
|
[&](Tree* tree) {
|
||||||
|
*tree = replacement.release_nonnull();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Vector<NodeSubtreePointer> BinaryOperation::subtrees()
|
Vector<NodeSubtreePointer> BinaryOperation::subtrees()
|
||||||
{
|
{
|
||||||
return { { &m_left }, { &m_right } };
|
return { { &m_left }, { &m_right } };
|
||||||
|
@ -43,8 +66,8 @@ Vector<NodeSubtreePointer> IfBranch::subtrees()
|
||||||
|
|
||||||
Vector<NodeSubtreePointer> ElseIfBranch::subtrees()
|
Vector<NodeSubtreePointer> ElseIfBranch::subtrees()
|
||||||
{
|
{
|
||||||
if (m_condition.has_value())
|
if (m_condition)
|
||||||
return { { &m_condition.value() }, { &m_branch } };
|
return { { &m_condition }, { &m_branch } };
|
||||||
return { { &m_branch } };
|
return { { &m_branch } };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,12 +28,16 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Tree& get(Badge<RecursiveASTVisitor>) { return *m_tree_ptr; }
|
NodeSubtreePointer(NullableTree* tree_ptr)
|
||||||
|
: m_tree_ptr(tree_ptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void replace_subtree(Badge<RecursiveASTVisitor>, Tree tree) { *m_tree_ptr = move(tree); }
|
Tree get(Badge<RecursiveASTVisitor>);
|
||||||
|
void replace_subtree(Badge<RecursiveASTVisitor>, NullableTree replacement);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Tree* m_tree_ptr;
|
Variant<Tree*, NullableTree*> m_tree_ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ===== Generic nodes =====
|
// ===== Generic nodes =====
|
||||||
|
@ -258,7 +262,7 @@ protected:
|
||||||
|
|
||||||
class ElseIfBranch : public Node {
|
class ElseIfBranch : public Node {
|
||||||
public:
|
public:
|
||||||
ElseIfBranch(Optional<Tree> condition, Tree branch)
|
ElseIfBranch(NullableTree condition, Tree branch)
|
||||||
: m_condition(condition)
|
: m_condition(condition)
|
||||||
, m_branch(branch)
|
, m_branch(branch)
|
||||||
{
|
{
|
||||||
|
@ -266,7 +270,7 @@ public:
|
||||||
|
|
||||||
Vector<NodeSubtreePointer> subtrees() override;
|
Vector<NodeSubtreePointer> subtrees() override;
|
||||||
|
|
||||||
Optional<Tree> m_condition;
|
NullableTree m_condition;
|
||||||
Tree m_branch;
|
Tree m_branch;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -91,9 +91,9 @@ void IfBranch::dump_tree(StringBuilder& builder)
|
||||||
|
|
||||||
void ElseIfBranch::dump_tree(StringBuilder& builder)
|
void ElseIfBranch::dump_tree(StringBuilder& builder)
|
||||||
{
|
{
|
||||||
dump_node(builder, "ElseIfBranch {}", m_condition.has_value() ? "ElseIf" : "Else");
|
dump_node(builder, "ElseIfBranch {}", m_condition ? "ElseIf" : "Else");
|
||||||
if (m_condition.has_value())
|
if (m_condition)
|
||||||
(*m_condition)->format_tree(builder);
|
m_condition->format_tree(builder);
|
||||||
m_branch->format_tree(builder);
|
m_branch->format_tree(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,13 +10,24 @@
|
||||||
|
|
||||||
namespace JSSpecCompiler {
|
namespace JSSpecCompiler {
|
||||||
|
|
||||||
|
void RecursiveASTVisitor::run_in_const_subtree(NullableTree nullable_tree)
|
||||||
|
{
|
||||||
|
if (nullable_tree) {
|
||||||
|
auto tree = nullable_tree.release_nonnull();
|
||||||
|
auto tree_copy = tree;
|
||||||
|
NodeSubtreePointer pointer { &tree };
|
||||||
|
recurse(tree, pointer);
|
||||||
|
VERIFY(tree == tree_copy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RecursiveASTVisitor::run_in_subtree(Tree& tree)
|
void RecursiveASTVisitor::run_in_subtree(Tree& tree)
|
||||||
{
|
{
|
||||||
NodeSubtreePointer pointer { &tree };
|
NodeSubtreePointer pointer { &tree };
|
||||||
recurse(tree, pointer);
|
recurse(tree, pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecursiveASTVisitor::replace_current_node_with(Tree tree)
|
void RecursiveASTVisitor::replace_current_node_with(NullableTree tree)
|
||||||
{
|
{
|
||||||
m_current_subtree_pointer->replace_subtree({}, move(tree));
|
m_current_subtree_pointer->replace_subtree({}, move(tree));
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,13 +17,14 @@ class RecursiveASTVisitor {
|
||||||
public:
|
public:
|
||||||
virtual ~RecursiveASTVisitor() = default;
|
virtual ~RecursiveASTVisitor() = default;
|
||||||
|
|
||||||
|
void run_in_const_subtree(NullableTree tree);
|
||||||
void run_in_subtree(Tree& tree);
|
void run_in_subtree(Tree& tree);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual RecursionDecision on_entry(Tree) { return RecursionDecision::Recurse; }
|
virtual RecursionDecision on_entry(Tree) { return RecursionDecision::Recurse; }
|
||||||
virtual void on_leave(Tree) { }
|
virtual void on_leave(Tree) { }
|
||||||
|
|
||||||
void replace_current_node_with(Tree tree);
|
void replace_current_node_with(NullableTree tree);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RecursionDecision recurse(Tree root, NodeSubtreePointer& pointer);
|
RecursionDecision recurse(Tree root, NodeSubtreePointer& pointer);
|
||||||
|
|
|
@ -382,7 +382,7 @@ ParseErrorOr<TextParser::IfConditionParseResult> TextParser::parse_if_beginning(
|
||||||
auto rollback = rollback_point();
|
auto rollback = rollback_point();
|
||||||
|
|
||||||
bool is_if_branch = !consume_word("if"sv).is_error();
|
bool is_if_branch = !consume_word("if"sv).is_error();
|
||||||
Optional<Tree> condition;
|
NullableTree condition = nullptr;
|
||||||
if (is_if_branch) {
|
if (is_if_branch) {
|
||||||
condition = TRY(parse_condition());
|
condition = TRY(parse_condition());
|
||||||
} else {
|
} else {
|
||||||
|
@ -406,8 +406,7 @@ ParseErrorOr<Tree> TextParser::parse_inline_if_else()
|
||||||
|
|
||||||
rollback.disarm();
|
rollback.disarm();
|
||||||
if (is_if_branch)
|
if (is_if_branch)
|
||||||
return make_ref_counted<IfBranch>(*condition, then_branch);
|
return make_ref_counted<IfBranch>(condition.release_nonnull(), then_branch);
|
||||||
else
|
|
||||||
return make_ref_counted<ElseIfBranch>(condition, then_branch);
|
return make_ref_counted<ElseIfBranch>(condition, then_branch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,7 +436,7 @@ ParseErrorOr<Tree> TextParser::parse_else(Tree else_branch)
|
||||||
TRY(expect_eof());
|
TRY(expect_eof());
|
||||||
|
|
||||||
rollback.disarm();
|
rollback.disarm();
|
||||||
return make_ref_counted<ElseIfBranch>(Optional<Tree> {}, else_branch);
|
return make_ref_counted<ElseIfBranch>(nullptr, else_branch);
|
||||||
}
|
}
|
||||||
|
|
||||||
// <simple_step> | <inline_if>
|
// <simple_step> | <inline_if>
|
||||||
|
|
|
@ -33,7 +33,7 @@ public:
|
||||||
private:
|
private:
|
||||||
struct IfConditionParseResult {
|
struct IfConditionParseResult {
|
||||||
bool is_if_branch;
|
bool is_if_branch;
|
||||||
Optional<Tree> condition;
|
NullableTree condition;
|
||||||
};
|
};
|
||||||
|
|
||||||
void retreat();
|
void retreat();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue