mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 15:32:46 +00:00 
			
		
		
		
	JSSpecCompiler: Allow storing NullableTrees 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 { | ||||
| 
 | ||||
| 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() | ||||
| { | ||||
|     return { { &m_left }, { &m_right } }; | ||||
|  | @ -43,8 +66,8 @@ Vector<NodeSubtreePointer> IfBranch::subtrees() | |||
| 
 | ||||
| Vector<NodeSubtreePointer> ElseIfBranch::subtrees() | ||||
| { | ||||
|     if (m_condition.has_value()) | ||||
|         return { { &m_condition.value() }, { &m_branch } }; | ||||
|     if (m_condition) | ||||
|         return { { &m_condition }, { &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: | ||||
|     Tree* m_tree_ptr; | ||||
|     Variant<Tree*, NullableTree*> m_tree_ptr; | ||||
| }; | ||||
| 
 | ||||
| // ===== Generic nodes =====
 | ||||
|  | @ -258,7 +262,7 @@ protected: | |||
| 
 | ||||
| class ElseIfBranch : public Node { | ||||
| public: | ||||
|     ElseIfBranch(Optional<Tree> condition, Tree branch) | ||||
|     ElseIfBranch(NullableTree condition, Tree branch) | ||||
|         : m_condition(condition) | ||||
|         , m_branch(branch) | ||||
|     { | ||||
|  | @ -266,7 +270,7 @@ public: | |||
| 
 | ||||
|     Vector<NodeSubtreePointer> subtrees() override; | ||||
| 
 | ||||
|     Optional<Tree> m_condition; | ||||
|     NullableTree m_condition; | ||||
|     Tree m_branch; | ||||
| 
 | ||||
| protected: | ||||
|  |  | |||
|  | @ -91,9 +91,9 @@ void IfBranch::dump_tree(StringBuilder& builder) | |||
| 
 | ||||
| void ElseIfBranch::dump_tree(StringBuilder& builder) | ||||
| { | ||||
|     dump_node(builder, "ElseIfBranch {}", m_condition.has_value() ? "ElseIf" : "Else"); | ||||
|     if (m_condition.has_value()) | ||||
|         (*m_condition)->format_tree(builder); | ||||
|     dump_node(builder, "ElseIfBranch {}", m_condition ? "ElseIf" : "Else"); | ||||
|     if (m_condition) | ||||
|         m_condition->format_tree(builder); | ||||
|     m_branch->format_tree(builder); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -10,13 +10,24 @@ | |||
| 
 | ||||
| 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) | ||||
| { | ||||
|     NodeSubtreePointer pointer { &tree }; | ||||
|     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)); | ||||
| } | ||||
|  |  | |||
|  | @ -17,13 +17,14 @@ class RecursiveASTVisitor { | |||
| public: | ||||
|     virtual ~RecursiveASTVisitor() = default; | ||||
| 
 | ||||
|     void run_in_const_subtree(NullableTree tree); | ||||
|     void run_in_subtree(Tree& tree); | ||||
| 
 | ||||
| protected: | ||||
|     virtual RecursionDecision on_entry(Tree) { return RecursionDecision::Recurse; } | ||||
|     virtual void on_leave(Tree) { } | ||||
| 
 | ||||
|     void replace_current_node_with(Tree tree); | ||||
|     void replace_current_node_with(NullableTree tree); | ||||
| 
 | ||||
| private: | ||||
|     RecursionDecision recurse(Tree root, NodeSubtreePointer& pointer); | ||||
|  |  | |||
|  | @ -382,7 +382,7 @@ ParseErrorOr<TextParser::IfConditionParseResult> TextParser::parse_if_beginning( | |||
|     auto rollback = rollback_point(); | ||||
| 
 | ||||
|     bool is_if_branch = !consume_word("if"sv).is_error(); | ||||
|     Optional<Tree> condition; | ||||
|     NullableTree condition = nullptr; | ||||
|     if (is_if_branch) { | ||||
|         condition = TRY(parse_condition()); | ||||
|     } else { | ||||
|  | @ -406,9 +406,8 @@ ParseErrorOr<Tree> TextParser::parse_inline_if_else() | |||
| 
 | ||||
|     rollback.disarm(); | ||||
|     if (is_if_branch) | ||||
|         return make_ref_counted<IfBranch>(*condition, then_branch); | ||||
|     else | ||||
|         return make_ref_counted<ElseIfBranch>(condition, then_branch); | ||||
|         return make_ref_counted<IfBranch>(condition.release_nonnull(), then_branch); | ||||
|     return make_ref_counted<ElseIfBranch>(condition, then_branch); | ||||
| } | ||||
| 
 | ||||
| // <if> :== <if_condition> then$ <substeps>
 | ||||
|  | @ -437,7 +436,7 @@ ParseErrorOr<Tree> TextParser::parse_else(Tree else_branch) | |||
|     TRY(expect_eof()); | ||||
| 
 | ||||
|     rollback.disarm(); | ||||
|     return make_ref_counted<ElseIfBranch>(Optional<Tree> {}, else_branch); | ||||
|     return make_ref_counted<ElseIfBranch>(nullptr, else_branch); | ||||
| } | ||||
| 
 | ||||
| // <simple_step> | <inline_if>
 | ||||
|  |  | |||
|  | @ -33,7 +33,7 @@ public: | |||
| private: | ||||
|     struct IfConditionParseResult { | ||||
|         bool is_if_branch; | ||||
|         Optional<Tree> condition; | ||||
|         NullableTree condition; | ||||
|     }; | ||||
| 
 | ||||
|     void retreat(); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Klishch
						Dan Klishch