mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 01:22:43 +00:00 
			
		
		
		
	Shell: Add the (now) free subshell support
This commit is contained in:
		
							parent
							
								
									0fd8d5ad3d
								
							
						
					
					
						commit
						b194d79c53
					
				
					 4 changed files with 92 additions and 0 deletions
				
			
		|  | @ -1569,6 +1569,51 @@ Sequence::~Sequence() | ||||||
| { | { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void Subshell::dump(int level) const | ||||||
|  | { | ||||||
|  |     Node::dump(level); | ||||||
|  |     if (m_block) | ||||||
|  |         m_block->dump(level + 1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | RefPtr<Value> Subshell::run(RefPtr<Shell> shell) | ||||||
|  | { | ||||||
|  |     if (!m_block) | ||||||
|  |         return create<ListValue>({}); | ||||||
|  | 
 | ||||||
|  |     return m_block->run(shell); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Subshell::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata) | ||||||
|  | { | ||||||
|  |     metadata.is_first_in_list = true; | ||||||
|  |     if (m_block) | ||||||
|  |         m_block->highlight_in_editor(editor, shell, metadata); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | HitTestResult Subshell::hit_test_position(size_t offset) | ||||||
|  | { | ||||||
|  |     if (!position().contains(offset)) | ||||||
|  |         return {}; | ||||||
|  | 
 | ||||||
|  |     if (m_block) | ||||||
|  |         return m_block->hit_test_position(offset); | ||||||
|  | 
 | ||||||
|  |     return {}; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Subshell::Subshell(Position position, RefPtr<Node> block) | ||||||
|  |     : Node(move(position)) | ||||||
|  |     , m_block(block) | ||||||
|  | { | ||||||
|  |     if (m_block && m_block->is_syntax_error()) | ||||||
|  |         set_is_syntax_error(m_block->syntax_error_node()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Subshell::~Subshell() | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void SimpleVariable::dump(int level) const | void SimpleVariable::dump(int level) const | ||||||
| { | { | ||||||
|     Node::dump(level); |     Node::dump(level); | ||||||
|  |  | ||||||
							
								
								
									
										16
									
								
								Shell/AST.h
									
										
									
									
									
								
							
							
						
						
									
										16
									
								
								Shell/AST.h
									
										
									
									
									
								
							|  | @ -806,6 +806,22 @@ private: | ||||||
|     RefPtr<Node> m_right; |     RefPtr<Node> m_right; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | class Subshell final : public Node { | ||||||
|  | public: | ||||||
|  |     Subshell(Position, RefPtr<Node> block); | ||||||
|  |     virtual ~Subshell(); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     virtual void dump(int level) const override; | ||||||
|  |     virtual RefPtr<Value> run(RefPtr<Shell>) override; | ||||||
|  |     virtual void highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override; | ||||||
|  |     virtual HitTestResult hit_test_position(size_t) override; | ||||||
|  |     virtual String class_name() const override { return "Subshell"; } | ||||||
|  |     virtual bool would_execute() const override { return true; } | ||||||
|  | 
 | ||||||
|  |     RefPtr<AST::Node> m_block; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| class SimpleVariable final : public Node { | class SimpleVariable final : public Node { | ||||||
| public: | public: | ||||||
|     SimpleVariable(Position, String); |     SimpleVariable(Position, String); | ||||||
|  |  | ||||||
|  | @ -366,6 +366,9 @@ RefPtr<AST::Node> Parser::parse_control_structure() | ||||||
|     if (auto if_expr = parse_if_expr()) |     if (auto if_expr = parse_if_expr()) | ||||||
|         return if_expr; |         return if_expr; | ||||||
| 
 | 
 | ||||||
|  |     if (auto subshell = parse_subshell()) | ||||||
|  |         return subshell; | ||||||
|  | 
 | ||||||
|     return nullptr; |     return nullptr; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -510,6 +513,29 @@ RefPtr<AST::Node> Parser::parse_if_expr() | ||||||
|     return create<AST::IfCond>(else_position, move(condition), move(true_branch), nullptr); // If expr true_branch
 |     return create<AST::IfCond>(else_position, move(condition), move(true_branch), nullptr); // If expr true_branch
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | RefPtr<AST::Node> Parser::parse_subshell() | ||||||
|  | { | ||||||
|  |     auto rule_start = push_start(); | ||||||
|  |     if (!expect('{')) | ||||||
|  |         return nullptr; | ||||||
|  | 
 | ||||||
|  |     auto body = parse_toplevel(); | ||||||
|  | 
 | ||||||
|  |     { | ||||||
|  |         auto cbrace_error_start = push_start(); | ||||||
|  |         if (!expect('}')) { | ||||||
|  |             auto error_start = push_start(); | ||||||
|  |             RefPtr<AST::SyntaxError> syntax_error = create<AST::SyntaxError>("Expected a close brace '}' to end a subshell"); | ||||||
|  |             if (body) | ||||||
|  |                 body->set_is_syntax_error(*syntax_error); | ||||||
|  |             else | ||||||
|  |                 body = syntax_error; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return create<AST::Subshell>(move(body)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| RefPtr<AST::Node> Parser::parse_redirection() | RefPtr<AST::Node> Parser::parse_redirection() | ||||||
| { | { | ||||||
|     auto rule_start = push_start(); |     auto rule_start = push_start(); | ||||||
|  |  | ||||||
|  | @ -53,6 +53,7 @@ private: | ||||||
|     RefPtr<AST::Node> parse_control_structure(); |     RefPtr<AST::Node> parse_control_structure(); | ||||||
|     RefPtr<AST::Node> parse_for_loop(); |     RefPtr<AST::Node> parse_for_loop(); | ||||||
|     RefPtr<AST::Node> parse_if_expr(); |     RefPtr<AST::Node> parse_if_expr(); | ||||||
|  |     RefPtr<AST::Node> parse_subshell(); | ||||||
|     RefPtr<AST::Node> parse_redirection(); |     RefPtr<AST::Node> parse_redirection(); | ||||||
|     RefPtr<AST::Node> parse_list_expression(); |     RefPtr<AST::Node> parse_list_expression(); | ||||||
|     RefPtr<AST::Node> parse_expression(); |     RefPtr<AST::Node> parse_expression(); | ||||||
|  | @ -129,6 +130,8 @@ pipe_sequence :: command '|' pipe_sequence | ||||||
| 
 | 
 | ||||||
| control_structure :: for_expr | control_structure :: for_expr | ||||||
|                    | if_expr |                    | if_expr | ||||||
|  |                    | subshell | ||||||
|  | 
 | ||||||
| for_expr :: 'for' ws+ (identifier ' '+ 'in' ws*)? expression ws+ '{' toplevel '}' | for_expr :: 'for' ws+ (identifier ' '+ 'in' ws*)? expression ws+ '{' toplevel '}' | ||||||
| 
 | 
 | ||||||
| if_expr :: 'if' ws+ or_logical_sequence ws+ '{' toplevel '}' else_clause? | if_expr :: 'if' ws+ or_logical_sequence ws+ '{' toplevel '}' else_clause? | ||||||
|  | @ -136,6 +139,8 @@ if_expr :: 'if' ws+ or_logical_sequence ws+ '{' toplevel '}' else_clause? | ||||||
| else_clause :: else '{' toplevel '}' | else_clause :: else '{' toplevel '}' | ||||||
|              | else if_expr |              | else if_expr | ||||||
| 
 | 
 | ||||||
|  | subshell :: '{' toplevel '}' | ||||||
|  | 
 | ||||||
| command :: redirection command | command :: redirection command | ||||||
|          | list_expression command? |          | list_expression command? | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 AnotherTest
						AnotherTest