mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-27 01:50:24 +00:00
Shell: Add the (now) free subshell support
This commit is contained in:
parent
0fd8d5ad3d
commit
b194d79c53
Notes:
sideshowbarker
2024-07-19 02:48:34 +09:00
Author: https://github.com/alimpfard Commit: https://github.com/SerenityOS/serenity/commit/b194d79c53b Pull-request: https://github.com/SerenityOS/serenity/pull/3372 Reviewed-by: https://github.com/tomuta
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
|
||||
{
|
||||
Node::dump(level);
|
||||
|
|
16
Shell/AST.h
16
Shell/AST.h
|
@ -806,6 +806,22 @@ private:
|
|||
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 {
|
||||
public:
|
||||
SimpleVariable(Position, String);
|
||||
|
|
|
@ -366,6 +366,9 @@ RefPtr<AST::Node> Parser::parse_control_structure()
|
|||
if (auto if_expr = parse_if_expr())
|
||||
return if_expr;
|
||||
|
||||
if (auto subshell = parse_subshell())
|
||||
return subshell;
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
auto rule_start = push_start();
|
||||
|
|
|
@ -53,6 +53,7 @@ private:
|
|||
RefPtr<AST::Node> parse_control_structure();
|
||||
RefPtr<AST::Node> parse_for_loop();
|
||||
RefPtr<AST::Node> parse_if_expr();
|
||||
RefPtr<AST::Node> parse_subshell();
|
||||
RefPtr<AST::Node> parse_redirection();
|
||||
RefPtr<AST::Node> parse_list_expression();
|
||||
RefPtr<AST::Node> parse_expression();
|
||||
|
@ -129,6 +130,8 @@ pipe_sequence :: command '|' pipe_sequence
|
|||
|
||||
control_structure :: for_expr
|
||||
| if_expr
|
||||
| subshell
|
||||
|
||||
for_expr :: 'for' ws+ (identifier ' '+ 'in' ws*)? expression ws+ '{' toplevel '}'
|
||||
|
||||
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 if_expr
|
||||
|
||||
subshell :: '{' toplevel '}'
|
||||
|
||||
command :: redirection command
|
||||
| list_expression command?
|
||||
|
||||
|
|
Loading…
Reference in a new issue