mirror of
https://github.com/RGBCube/serenity
synced 2025-05-23 21:55:08 +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