mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 12:53:13 +00:00
Remove parse_exec stuff
This commit is contained in:
parent
54d7c29221
commit
a51bd03a5c
5 changed files with 1 additions and 889 deletions
|
@ -100,7 +100,7 @@ FISH_OBJS := function.o builtin.o complete.o env.o exec.o expand.o \
|
||||||
env_universal.o env_universal_common.o input_common.o event.o \
|
env_universal.o env_universal_common.o input_common.o event.o \
|
||||||
signal.o io.o parse_util.o common.o screen.o path.o autoload.o \
|
signal.o io.o parse_util.o common.o screen.o path.o autoload.o \
|
||||||
parser_keywords.o iothread.o color.o postfork.o \
|
parser_keywords.o iothread.o color.o postfork.o \
|
||||||
builtin_test.o parse_tree.o parse_productions.o parse_exec.o
|
builtin_test.o parse_tree.o parse_productions.o
|
||||||
|
|
||||||
FISH_INDENT_OBJS := fish_indent.o print_help.o common.o \
|
FISH_INDENT_OBJS := fish_indent.o print_help.o common.o \
|
||||||
parser_keywords.o wutil.o tokenizer.o
|
parser_keywords.o wutil.o tokenizer.o
|
||||||
|
|
114
builtin.cpp
114
builtin.cpp
|
@ -65,7 +65,6 @@
|
||||||
#include "path.h"
|
#include "path.h"
|
||||||
#include "history.h"
|
#include "history.h"
|
||||||
#include "parse_tree.h"
|
#include "parse_tree.h"
|
||||||
#include "parse_exec.h"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The default prompt for the read command
|
The default prompt for the read command
|
||||||
|
@ -3956,104 +3955,6 @@ static int builtin_history(parser_t &parser, wchar_t **argv)
|
||||||
|
|
||||||
#pragma mark Simulator
|
#pragma mark Simulator
|
||||||
|
|
||||||
struct parse_execution_simulator_t : public parse_execution_visitor_t
|
|
||||||
{
|
|
||||||
wcstring_list_t result;
|
|
||||||
|
|
||||||
wcstring &back()
|
|
||||||
{
|
|
||||||
assert(! result.empty());
|
|
||||||
return result.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
void append_src(node_offset_t idx)
|
|
||||||
{
|
|
||||||
wcstring tmp;
|
|
||||||
context->get_source(idx, &tmp);
|
|
||||||
back().append(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void append(const wchar_t *s)
|
|
||||||
{
|
|
||||||
back().append(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool enter_job_list(void)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool enter_job(void)
|
|
||||||
{
|
|
||||||
result.resize(result.size() + 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void visit_statement(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void visit_boolean_statement(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void enter_if_clause(const exec_if_clause_t &statement)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void exit_if_clause(const exec_if_clause_t &statement)
|
|
||||||
{
|
|
||||||
append_format(back(), L"\nIF successful jump to %lu", (unsigned long)statement.body);
|
|
||||||
}
|
|
||||||
|
|
||||||
void visit_basic_statement(const exec_basic_statement_t &statement)
|
|
||||||
{
|
|
||||||
wcstring &line = this->back();
|
|
||||||
if (! line.empty())
|
|
||||||
{
|
|
||||||
line.append(L" <pipe> ");
|
|
||||||
}
|
|
||||||
switch (statement.decoration)
|
|
||||||
{
|
|
||||||
case exec_basic_statement_t::decoration_builtin:
|
|
||||||
line.append(L"<builtin> ");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case exec_basic_statement_t::decoration_command:
|
|
||||||
line.append(L"<command> ");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
line.append(L"cmd:");
|
|
||||||
this->append_src(statement.command_idx);
|
|
||||||
for (size_t i=0; i < statement.arguments().size(); i++)
|
|
||||||
{
|
|
||||||
const exec_argument_t &arg = statement.arguments().at(i);
|
|
||||||
append(L" ");
|
|
||||||
append(L"arg:");
|
|
||||||
append_src(arg.parse_node_idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void visit_function(const exec_function_header_t &function)
|
|
||||||
{
|
|
||||||
wcstring &line = this->back();
|
|
||||||
line.append(L"define function: ");
|
|
||||||
wcstring tmp;
|
|
||||||
context->get_source(function.name_idx, &tmp);
|
|
||||||
line.append(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void exit_job_list(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int builtin_parse(parser_t &parser, wchar_t **argv)
|
int builtin_parse(parser_t &parser, wchar_t **argv)
|
||||||
{
|
{
|
||||||
struct sigaction act;
|
struct sigaction act;
|
||||||
|
@ -4090,21 +3991,6 @@ int builtin_parse(parser_t &parser, wchar_t **argv)
|
||||||
{
|
{
|
||||||
const wcstring dump = parse_dump_tree(parse_tree, src);
|
const wcstring dump = parse_dump_tree(parse_tree, src);
|
||||||
fprintf(stderr, "%ls", dump.c_str());
|
fprintf(stderr, "%ls", dump.c_str());
|
||||||
if (0)
|
|
||||||
{
|
|
||||||
parse_execution_context_t ctx(parse_tree, src);
|
|
||||||
parse_execution_simulator_t sim;
|
|
||||||
sim.context = &ctx;
|
|
||||||
while (ctx.visit_next_node(&sim))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
stdout_buffer.append(L"Simulating execution:\n");
|
|
||||||
for (size_t i=0; i < sim.result.size(); i++)
|
|
||||||
{
|
|
||||||
stdout_buffer.append(sim.result.at(i));
|
|
||||||
stdout_buffer.push_back(L'\n');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return STATUS_BUILTIN_OK;
|
return STATUS_BUILTIN_OK;
|
||||||
|
|
|
@ -112,13 +112,11 @@
|
||||||
D08A32B817B446A300F3A533 /* signal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0855C13B3ACEE0099B651 /* signal.cpp */; };
|
D08A32B817B446A300F3A533 /* signal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0855C13B3ACEE0099B651 /* signal.cpp */; };
|
||||||
D08A32B917B446B100F3A533 /* parse_productions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0FE8EE7179FB75F008C9F21 /* parse_productions.cpp */; };
|
D08A32B917B446B100F3A533 /* parse_productions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0FE8EE7179FB75F008C9F21 /* parse_productions.cpp */; };
|
||||||
D08A32BA17B446B100F3A533 /* parse_tree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0C52F351765284C00BFAB82 /* parse_tree.cpp */; };
|
D08A32BA17B446B100F3A533 /* parse_tree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0C52F351765284C00BFAB82 /* parse_tree.cpp */; };
|
||||||
D08A32BB17B446B100F3A533 /* parse_exec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0C52F331765281F00BFAB82 /* parse_exec.cpp */; };
|
|
||||||
D08A32BC17B4473B00F3A533 /* libncurses.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D02A8C15983CFA008E62BD /* libncurses.dylib */; };
|
D08A32BC17B4473B00F3A533 /* libncurses.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D02A8C15983CFA008E62BD /* libncurses.dylib */; };
|
||||||
D08A32BD17B4474000F3A533 /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D02A8A15983CDF008E62BD /* libiconv.dylib */; };
|
D08A32BD17B4474000F3A533 /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D02A8A15983CDF008E62BD /* libiconv.dylib */; };
|
||||||
D0A564FE168D23D800AF6161 /* man in CopyFiles */ = {isa = PBXBuildFile; fileRef = D0A564F1168D0BAB00AF6161 /* man */; };
|
D0A564FE168D23D800AF6161 /* man in CopyFiles */ = {isa = PBXBuildFile; fileRef = D0A564F1168D0BAB00AF6161 /* man */; };
|
||||||
D0A56501168D258300AF6161 /* man in Copy Files */ = {isa = PBXBuildFile; fileRef = D0A564F1168D0BAB00AF6161 /* man */; };
|
D0A56501168D258300AF6161 /* man in Copy Files */ = {isa = PBXBuildFile; fileRef = D0A564F1168D0BAB00AF6161 /* man */; };
|
||||||
D0C52F371765284C00BFAB82 /* parse_tree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0C52F351765284C00BFAB82 /* parse_tree.cpp */; };
|
D0C52F371765284C00BFAB82 /* parse_tree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0C52F351765284C00BFAB82 /* parse_tree.cpp */; };
|
||||||
D0C52F381765720600BFAB82 /* parse_exec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0C52F331765281F00BFAB82 /* parse_exec.cpp */; };
|
|
||||||
D0CBD587159EF0E10024809C /* launch_fish.scpt in Resources */ = {isa = PBXBuildFile; fileRef = D0CBD586159EF0E10024809C /* launch_fish.scpt */; };
|
D0CBD587159EF0E10024809C /* launch_fish.scpt in Resources */ = {isa = PBXBuildFile; fileRef = D0CBD586159EF0E10024809C /* launch_fish.scpt */; };
|
||||||
D0D02A67159837AD008E62BD /* complete.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0853713B3ACEE0099B651 /* complete.cpp */; };
|
D0D02A67159837AD008E62BD /* complete.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0853713B3ACEE0099B651 /* complete.cpp */; };
|
||||||
D0D02A69159837B2008E62BD /* env.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0853A13B3ACEE0099B651 /* env.cpp */; };
|
D0D02A69159837B2008E62BD /* env.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0853A13B3ACEE0099B651 /* env.cpp */; };
|
||||||
|
@ -497,8 +495,6 @@
|
||||||
D0B6B0FE14E88BA400AD6C10 /* color.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = color.cpp; sourceTree = "<group>"; };
|
D0B6B0FE14E88BA400AD6C10 /* color.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = color.cpp; sourceTree = "<group>"; };
|
||||||
D0B6B0FF14E88BA400AD6C10 /* color.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = color.h; sourceTree = "<group>"; };
|
D0B6B0FF14E88BA400AD6C10 /* color.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = color.h; sourceTree = "<group>"; };
|
||||||
D0C4FD9415A7D7EE00212EF1 /* config.fish */ = {isa = PBXFileReference; lastKnownFileType = text; name = config.fish; path = etc/config.fish; sourceTree = "<group>"; };
|
D0C4FD9415A7D7EE00212EF1 /* config.fish */ = {isa = PBXFileReference; lastKnownFileType = text; name = config.fish; path = etc/config.fish; sourceTree = "<group>"; };
|
||||||
D0C52F331765281F00BFAB82 /* parse_exec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parse_exec.cpp; sourceTree = "<group>"; };
|
|
||||||
D0C52F341765281F00BFAB82 /* parse_exec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = parse_exec.h; sourceTree = "<group>"; };
|
|
||||||
D0C52F351765284C00BFAB82 /* parse_tree.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parse_tree.cpp; sourceTree = "<group>"; };
|
D0C52F351765284C00BFAB82 /* parse_tree.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parse_tree.cpp; sourceTree = "<group>"; };
|
||||||
D0C52F361765284C00BFAB82 /* parse_tree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = parse_tree.h; sourceTree = "<group>"; };
|
D0C52F361765284C00BFAB82 /* parse_tree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = parse_tree.h; sourceTree = "<group>"; };
|
||||||
D0C6FCC914CFA4B0004CE8AD /* autoload.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = autoload.cpp; sourceTree = "<group>"; };
|
D0C6FCC914CFA4B0004CE8AD /* autoload.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = autoload.cpp; sourceTree = "<group>"; };
|
||||||
|
@ -665,8 +661,6 @@
|
||||||
D0FE8EE7179FB75F008C9F21 /* parse_productions.cpp */,
|
D0FE8EE7179FB75F008C9F21 /* parse_productions.cpp */,
|
||||||
D0C52F361765284C00BFAB82 /* parse_tree.h */,
|
D0C52F361765284C00BFAB82 /* parse_tree.h */,
|
||||||
D0C52F351765284C00BFAB82 /* parse_tree.cpp */,
|
D0C52F351765284C00BFAB82 /* parse_tree.cpp */,
|
||||||
D0C52F341765281F00BFAB82 /* parse_exec.h */,
|
|
||||||
D0C52F331765281F00BFAB82 /* parse_exec.cpp */,
|
|
||||||
D0A0850D13B3ACEE0099B651 /* fallback.h */,
|
D0A0850D13B3ACEE0099B651 /* fallback.h */,
|
||||||
D0A0853E13B3ACEE0099B651 /* fallback.cpp */,
|
D0A0853E13B3ACEE0099B651 /* fallback.cpp */,
|
||||||
D0A0850E13B3ACEE0099B651 /* function.h */,
|
D0A0850E13B3ACEE0099B651 /* function.h */,
|
||||||
|
@ -1130,7 +1124,6 @@
|
||||||
files = (
|
files = (
|
||||||
D08A32B917B446B100F3A533 /* parse_productions.cpp in Sources */,
|
D08A32B917B446B100F3A533 /* parse_productions.cpp in Sources */,
|
||||||
D08A32BA17B446B100F3A533 /* parse_tree.cpp in Sources */,
|
D08A32BA17B446B100F3A533 /* parse_tree.cpp in Sources */,
|
||||||
D08A32BB17B446B100F3A533 /* parse_exec.cpp in Sources */,
|
|
||||||
D08A32A717B446A300F3A533 /* autoload.cpp in Sources */,
|
D08A32A717B446A300F3A533 /* autoload.cpp in Sources */,
|
||||||
D08A32A817B446A300F3A533 /* builtin_test.cpp in Sources */,
|
D08A32A817B446A300F3A533 /* builtin_test.cpp in Sources */,
|
||||||
D08A32A917B446A300F3A533 /* color.cpp in Sources */,
|
D08A32A917B446A300F3A533 /* color.cpp in Sources */,
|
||||||
|
@ -1255,7 +1248,6 @@
|
||||||
D0D02A7B15983928008E62BD /* env_universal_common.cpp in Sources */,
|
D0D02A7B15983928008E62BD /* env_universal_common.cpp in Sources */,
|
||||||
D0D02A89159839DF008E62BD /* fish.cpp in Sources */,
|
D0D02A89159839DF008E62BD /* fish.cpp in Sources */,
|
||||||
D0C52F371765284C00BFAB82 /* parse_tree.cpp in Sources */,
|
D0C52F371765284C00BFAB82 /* parse_tree.cpp in Sources */,
|
||||||
D0C52F381765720600BFAB82 /* parse_exec.cpp in Sources */,
|
|
||||||
D0FE8EE8179FB760008C9F21 /* parse_productions.cpp in Sources */,
|
D0FE8EE8179FB760008C9F21 /* parse_productions.cpp in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
|
593
parse_exec.cpp
593
parse_exec.cpp
|
@ -1,593 +0,0 @@
|
||||||
#include "parse_exec.h"
|
|
||||||
#include <stack>
|
|
||||||
|
|
||||||
struct exec_node_t
|
|
||||||
{
|
|
||||||
node_offset_t parse_node_idx;
|
|
||||||
node_offset_t body_parse_node_idx;
|
|
||||||
bool visited;
|
|
||||||
|
|
||||||
explicit exec_node_t(node_offset_t pni) : parse_node_idx(pni), body_parse_node_idx(NODE_OFFSET_INVALID), visited(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit exec_node_t(node_offset_t pni, node_offset_t body_pni) : parse_node_idx(pni), body_parse_node_idx(body_pni), visited(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
exec_basic_statement_t::exec_basic_statement_t() : command_idx(0), decoration(decoration_plain)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class parse_exec_t
|
|
||||||
{
|
|
||||||
parse_node_tree_t parse_tree;
|
|
||||||
wcstring src;
|
|
||||||
|
|
||||||
/* The stack of nodes as we execute them */
|
|
||||||
std::vector<exec_node_t> exec_nodes;
|
|
||||||
|
|
||||||
/* The stack of commands being built */
|
|
||||||
std::vector<exec_basic_statement_t> assembling_statements;
|
|
||||||
|
|
||||||
/* Current visitor (very transient) */
|
|
||||||
struct parse_execution_visitor_t * visitor;
|
|
||||||
|
|
||||||
const parse_node_t &get_child(const parse_node_t &parent, node_offset_t which) const
|
|
||||||
{
|
|
||||||
return parse_tree.at(parent.child_offset(which));
|
|
||||||
}
|
|
||||||
|
|
||||||
void pop_push_specific(node_offset_t idx1, node_offset_t idx2 = NODE_OFFSET_INVALID, node_offset_t idx3 = NODE_OFFSET_INVALID, node_offset_t idx4 = NODE_OFFSET_INVALID, node_offset_t idx5 = NODE_OFFSET_INVALID)
|
|
||||||
{
|
|
||||||
PARSE_ASSERT(! exec_nodes.empty());
|
|
||||||
// Figure out the offset of the children
|
|
||||||
exec_node_t &top = exec_nodes.back();
|
|
||||||
const parse_node_t &parse_node = parse_tree.at(top.parse_node_idx);
|
|
||||||
node_offset_t child_node_idx = parse_node.child_start;
|
|
||||||
|
|
||||||
// Remove the top node
|
|
||||||
exec_nodes.pop_back();
|
|
||||||
|
|
||||||
// Append the given children, backwards
|
|
||||||
const node_offset_t idxs[] = {idx5, idx4, idx3, idx2, idx1};
|
|
||||||
for (size_t q=0; q < sizeof idxs / sizeof *idxs; q++)
|
|
||||||
{
|
|
||||||
node_offset_t idx = idxs[q];
|
|
||||||
if (idx != (node_offset_t)(-1))
|
|
||||||
{
|
|
||||||
PARSE_ASSERT(idx < parse_node.child_count);
|
|
||||||
exec_nodes.push_back(exec_node_t(child_node_idx + idx));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void push(node_offset_t global_idx)
|
|
||||||
{
|
|
||||||
exec_nodes.push_back(exec_node_t(global_idx));
|
|
||||||
}
|
|
||||||
|
|
||||||
void push(const exec_node_t &node)
|
|
||||||
{
|
|
||||||
exec_nodes.push_back(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void pop_push(node_offset_t child_idx, node_offset_t child_count = 1)
|
|
||||||
{
|
|
||||||
PARSE_ASSERT(! exec_nodes.empty());
|
|
||||||
if (child_count == 0)
|
|
||||||
{
|
|
||||||
// No children, just remove the top node
|
|
||||||
exec_nodes.pop_back();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Figure out the offset of the children
|
|
||||||
exec_node_t &top = exec_nodes.back();
|
|
||||||
const parse_node_t &parse_node = parse_tree.at(top.parse_node_idx);
|
|
||||||
PARSE_ASSERT(child_idx < parse_node.child_count);
|
|
||||||
node_offset_t child_node_idx = parse_node.child_start + child_idx;
|
|
||||||
|
|
||||||
// Remove the top node
|
|
||||||
exec_nodes.pop_back();
|
|
||||||
|
|
||||||
// Append the given children, backwards
|
|
||||||
node_offset_t cursor = child_count;
|
|
||||||
while (cursor--)
|
|
||||||
{
|
|
||||||
exec_nodes.push_back(exec_node_t(child_node_idx + cursor));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void pop()
|
|
||||||
{
|
|
||||||
PARSE_ASSERT(! exec_nodes.empty());
|
|
||||||
exec_nodes.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
void pop_push_all()
|
|
||||||
{
|
|
||||||
exec_node_t &top = exec_nodes.back();
|
|
||||||
const parse_node_t &parse_node = parse_tree.at(top.parse_node_idx);
|
|
||||||
pop_push(0, parse_node.child_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
void assemble_1_argument_or_redirection(node_offset_t idx, exec_arguments_and_redirections_t *output) const
|
|
||||||
{
|
|
||||||
const parse_node_t &node = parse_tree.at(idx);
|
|
||||||
PARSE_ASSERT(output != NULL);
|
|
||||||
PARSE_ASSERT(node.type == symbol_argument_or_redirection);
|
|
||||||
PARSE_ASSERT(node.child_count == 1);
|
|
||||||
node_offset_t child_idx = node.child_offset(0);
|
|
||||||
const parse_node_t &child = parse_tree.at(child_idx);
|
|
||||||
switch (child.type)
|
|
||||||
{
|
|
||||||
case parse_token_type_string:
|
|
||||||
// Argument
|
|
||||||
{
|
|
||||||
exec_argument_t arg = exec_argument_t();
|
|
||||||
arg.parse_node_idx = child_idx;
|
|
||||||
output->arguments.push_back(arg);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case parse_token_type_redirection:
|
|
||||||
// Redirection
|
|
||||||
{
|
|
||||||
exec_redirection_t redirect = exec_redirection_t();
|
|
||||||
redirect.parse_node_idx = child_idx;
|
|
||||||
output->redirections.push_back(redirect);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
PARSER_DIE();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void assemble_arguments_and_redirections(node_offset_t start_idx, exec_arguments_and_redirections_t *output) const
|
|
||||||
{
|
|
||||||
node_offset_t idx = start_idx;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
const parse_node_t &node = parse_tree.at(idx);
|
|
||||||
PARSE_ASSERT(node.type == symbol_arguments_or_redirections_list);
|
|
||||||
PARSE_ASSERT(node.child_count == 0 || node.child_count == 2);
|
|
||||||
if (node.child_count == 0)
|
|
||||||
{
|
|
||||||
// No more children
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Skip to next child
|
|
||||||
assemble_1_argument_or_redirection(node.child_offset(0), output);
|
|
||||||
idx = node.child_offset(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void assemble_command_for_plain_statement(node_offset_t idx, parse_keyword_t decoration)
|
|
||||||
{
|
|
||||||
const parse_node_t &node = parse_tree.at(idx);
|
|
||||||
PARSE_ASSERT(node.type == symbol_plain_statement);
|
|
||||||
PARSE_ASSERT(node.child_count == 2);
|
|
||||||
exec_basic_statement_t statement;
|
|
||||||
statement.set_decoration(decoration);
|
|
||||||
statement.command_idx = node.child_offset(0);
|
|
||||||
assemble_arguments_and_redirections(node.child_offset(1), &statement.arguments_and_redirections);
|
|
||||||
visitor->visit_basic_statement(statement);
|
|
||||||
}
|
|
||||||
|
|
||||||
void assemble_block_statement(node_offset_t parse_node_idx)
|
|
||||||
{
|
|
||||||
|
|
||||||
const parse_node_t &node = parse_tree.at(parse_node_idx);
|
|
||||||
PARSE_ASSERT(node.type == symbol_block_statement);
|
|
||||||
PARSE_ASSERT(node.child_count == 5);
|
|
||||||
|
|
||||||
// Fetch arguments and redirections. These ought to be evaluated before the job list
|
|
||||||
exec_block_statement_t statement;
|
|
||||||
assemble_arguments_and_redirections(node.child_offset(4), &statement.arguments_and_redirections);
|
|
||||||
|
|
||||||
// Generic visit
|
|
||||||
visitor->enter_block_statement(statement);
|
|
||||||
|
|
||||||
// Dig into the header to discover the type
|
|
||||||
const parse_node_t &header_parent = parse_tree.at(node.child_offset(0));
|
|
||||||
PARSE_ASSERT(header_parent.type == symbol_block_header);
|
|
||||||
PARSE_ASSERT(header_parent.child_count == 1);
|
|
||||||
const node_offset_t header_idx = header_parent.child_offset(0);
|
|
||||||
|
|
||||||
// Fetch body (job list)
|
|
||||||
node_offset_t body_idx = node.child_offset(2);
|
|
||||||
PARSE_ASSERT(parse_tree.at(body_idx).type == symbol_job_list);
|
|
||||||
|
|
||||||
pop();
|
|
||||||
push(exec_node_t(header_idx, body_idx));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* which: 0 -> if, 1 -> else if, 2 -> else */
|
|
||||||
void assemble_if_else_clause(exec_node_t &exec_node, const parse_node_t &node, int which)
|
|
||||||
{
|
|
||||||
if (which == 0)
|
|
||||||
{
|
|
||||||
PARSE_ASSERT(node.type == symbol_if_clause);
|
|
||||||
PARSE_ASSERT(node.child_count == 4);
|
|
||||||
}
|
|
||||||
else if (which == 2)
|
|
||||||
{
|
|
||||||
PARSE_ASSERT(node.type == symbol_else_continuation);
|
|
||||||
PARSE_ASSERT(node.child_count == 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct exec_if_clause_t clause;
|
|
||||||
if (which == 0)
|
|
||||||
{
|
|
||||||
clause.body = node.child_offset(3);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
clause.body = node.child_offset(1);
|
|
||||||
}
|
|
||||||
if (! exec_node.visited)
|
|
||||||
{
|
|
||||||
visitor->enter_if_clause(clause);
|
|
||||||
exec_node.visited = true;
|
|
||||||
if (which == 0)
|
|
||||||
{
|
|
||||||
push(node.child_offset(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
visitor->exit_if_clause(clause);
|
|
||||||
pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void assemble_arguments(node_offset_t start_idx, exec_argument_list_t *output) const
|
|
||||||
{
|
|
||||||
node_offset_t idx = start_idx;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
const parse_node_t &node = parse_tree.at(idx);
|
|
||||||
PARSE_ASSERT(node.type == symbol_argument_list);
|
|
||||||
if (node.type == symbol_argument_list)
|
|
||||||
{
|
|
||||||
// argument list, may be empty
|
|
||||||
PARSE_ASSERT(node.child_count == 0 || node.child_count == 1);
|
|
||||||
if (node.child_count == 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
idx = node.child_offset(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// nonempty argument list
|
|
||||||
PARSE_ASSERT(node.child_count == 2);
|
|
||||||
output->push_back(exec_argument_t(node.child_offset(0)));
|
|
||||||
idx = node.child_offset(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void assemble_1_case_item(exec_switch_statement_t *statement, node_offset_t node_idx)
|
|
||||||
{
|
|
||||||
const parse_node_t &node = parse_tree.at(node_idx);
|
|
||||||
PARSE_ASSERT(node.type == symbol_case_item);
|
|
||||||
|
|
||||||
// add a new case
|
|
||||||
size_t len = statement->cases.size();
|
|
||||||
statement->cases.resize(len + 1);
|
|
||||||
exec_switch_case_t &new_case = statement->cases.back();
|
|
||||||
|
|
||||||
// assemble it
|
|
||||||
new_case.body = node.child_offset(3);
|
|
||||||
assemble_arguments(node.child_offset(1), &new_case.arguments);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void assemble_case_item_list(exec_switch_statement_t *statement, node_offset_t node_idx)
|
|
||||||
{
|
|
||||||
const parse_node_t &node = parse_tree.at(node_idx);
|
|
||||||
PARSE_ASSERT(node.type == symbol_case_item_list);
|
|
||||||
PARSE_ASSERT(node.child_count == 0 || node.child_count == 2);
|
|
||||||
if (node.child_count == 2)
|
|
||||||
{
|
|
||||||
assemble_1_case_item(statement, node.child_offset(0));
|
|
||||||
assemble_case_item_list(statement, node.child_offset(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void assemble_switch_statement(const exec_node_t &exec_node, const parse_node_t &parse_node)
|
|
||||||
{
|
|
||||||
PARSE_ASSERT(parse_node.type == symbol_switch_statement);
|
|
||||||
exec_switch_statement_t statement;
|
|
||||||
|
|
||||||
statement.argument.parse_node_idx = parse_node.child_offset(1);
|
|
||||||
assemble_case_item_list(&statement, parse_node.child_offset(3));
|
|
||||||
|
|
||||||
visitor->visit_switch_statement(statement);
|
|
||||||
|
|
||||||
// pop off the switch
|
|
||||||
pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void assemble_function_header(const exec_node_t &exec_node, const parse_node_t &header)
|
|
||||||
{
|
|
||||||
PARSE_ASSERT(header.type == symbol_function_header);
|
|
||||||
PARSE_ASSERT(&header == &parse_tree.at(exec_node.parse_node_idx));
|
|
||||||
PARSE_ASSERT(exec_node.body_parse_node_idx != NODE_OFFSET_INVALID);
|
|
||||||
exec_function_header_t function_info;
|
|
||||||
function_info.name_idx = header.child_offset(1);
|
|
||||||
function_info.body_idx = exec_node.body_parse_node_idx;
|
|
||||||
assemble_arguments(header.child_offset(2), &function_info.arguments);
|
|
||||||
visitor->visit_function(function_info);
|
|
||||||
|
|
||||||
// Always pop
|
|
||||||
pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void enter_parse_node(size_t idx);
|
|
||||||
void run_top_node(void);
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
void get_node_string(node_offset_t idx, wcstring *output) const
|
|
||||||
{
|
|
||||||
const parse_node_t &node = parse_tree.at(idx);
|
|
||||||
PARSE_ASSERT(node.source_start <= src.size());
|
|
||||||
PARSE_ASSERT(node.source_start + node.source_length <= src.size());
|
|
||||||
output->assign(src, node.source_start, node.source_length);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool visit_next_node(parse_execution_visitor_t *v);
|
|
||||||
|
|
||||||
parse_exec_t(const parse_node_tree_t &tree, const wcstring &s) : parse_tree(tree), src(s), visitor(NULL)
|
|
||||||
{
|
|
||||||
if (! parse_tree.empty())
|
|
||||||
{
|
|
||||||
exec_nodes.push_back(exec_node_t(0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void parse_exec_t::run_top_node()
|
|
||||||
{
|
|
||||||
PARSE_ASSERT(! exec_nodes.empty());
|
|
||||||
exec_node_t &exec_node = exec_nodes.back();
|
|
||||||
const node_offset_t parse_node_idx = exec_node.parse_node_idx;
|
|
||||||
const parse_node_t &parse_node = parse_tree.at(exec_node.parse_node_idx);
|
|
||||||
bool log = true;
|
|
||||||
|
|
||||||
if (log)
|
|
||||||
{
|
|
||||||
wcstring tmp;
|
|
||||||
tmp.append(exec_nodes.size(), L' ');
|
|
||||||
tmp.append(parse_node.describe());
|
|
||||||
printf("%ls\n", tmp.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (parse_node.type)
|
|
||||||
{
|
|
||||||
case symbol_job_list:
|
|
||||||
PARSE_ASSERT(parse_node.child_count == 0 || parse_node.child_count == 2);
|
|
||||||
if (parse_node.child_count == 0)
|
|
||||||
{
|
|
||||||
// No more jobs, done
|
|
||||||
visitor->exit_job_list();
|
|
||||||
pop();
|
|
||||||
}
|
|
||||||
else if (parse_tree.at(parse_node.child_start + 0).type == parse_token_type_end)
|
|
||||||
{
|
|
||||||
// Empty job, so just skip it
|
|
||||||
pop_push(1, 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Normal job
|
|
||||||
visitor->enter_job_list();
|
|
||||||
pop_push(0, 2);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case symbol_job:
|
|
||||||
{
|
|
||||||
PARSE_ASSERT(parse_node.child_count == 2);
|
|
||||||
visitor->enter_job();
|
|
||||||
pop_push_all();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case symbol_job_continuation:
|
|
||||||
PARSE_ASSERT(parse_node.child_count == 0 || parse_node.child_count == 3);
|
|
||||||
if (parse_node.child_count == 0)
|
|
||||||
{
|
|
||||||
// All done with this job
|
|
||||||
visitor->exit_job();
|
|
||||||
pop();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Skip the pipe
|
|
||||||
pop_push(1, 2);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case symbol_statement:
|
|
||||||
{
|
|
||||||
PARSE_ASSERT(parse_node.child_count == 1);
|
|
||||||
pop_push_all();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case symbol_block_statement:
|
|
||||||
{
|
|
||||||
PARSE_ASSERT(parse_node.child_count == 5);
|
|
||||||
assemble_block_statement(parse_node_idx);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case symbol_block_header:
|
|
||||||
{
|
|
||||||
PARSE_ASSERT(parse_node.child_count == 1);
|
|
||||||
pop_push_all();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case symbol_function_header:
|
|
||||||
{
|
|
||||||
PARSE_ASSERT(parse_node.child_count == 3);
|
|
||||||
assemble_function_header(exec_node, parse_node);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case symbol_if_statement:
|
|
||||||
{
|
|
||||||
PARSE_ASSERT(parse_node.child_count == 4);
|
|
||||||
pop_push(0, 2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case symbol_if_clause:
|
|
||||||
{
|
|
||||||
PARSE_ASSERT(parse_node.child_count == 4);
|
|
||||||
assemble_if_else_clause(exec_node, parse_node, 0);
|
|
||||||
pop();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case symbol_else_clause:
|
|
||||||
{
|
|
||||||
PARSE_ASSERT(parse_node.child_count == 0 || parse_node.child_count == 2);
|
|
||||||
if (parse_node.child_count == 0)
|
|
||||||
{
|
|
||||||
// No else
|
|
||||||
pop();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// We have an else
|
|
||||||
pop_push(1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case symbol_else_continuation:
|
|
||||||
{
|
|
||||||
// Figure out if this is an else if or a terminating else
|
|
||||||
PARSE_ASSERT(parse_node.child_count == 2);
|
|
||||||
const parse_node_t &first_child = get_child(parse_node, 1);
|
|
||||||
PARSE_ASSERT(first_child.type == symbol_if_clause || first_child.type == parse_token_type_end);
|
|
||||||
if (first_child.type == symbol_if_clause)
|
|
||||||
{
|
|
||||||
pop_push_all();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// else
|
|
||||||
assemble_if_else_clause(exec_node, parse_node, 2);
|
|
||||||
pop();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case symbol_switch_statement:
|
|
||||||
{
|
|
||||||
assemble_switch_statement(exec_node, parse_node);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case symbol_decorated_statement:
|
|
||||||
{
|
|
||||||
PARSE_ASSERT(parse_node.child_count == 1 || parse_node.child_count == 2);
|
|
||||||
|
|
||||||
node_offset_t plain_statement_idx = parse_node.child_offset(parse_node.child_count - 1);
|
|
||||||
parse_keyword_t decoration = static_cast<parse_keyword_t>(parse_node.tag);
|
|
||||||
assemble_command_for_plain_statement(plain_statement_idx, decoration);
|
|
||||||
pop();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The following symbols should be handled by their parents, i.e. never pushed on our stack
|
|
||||||
case symbol_case_item_list:
|
|
||||||
case symbol_plain_statement:
|
|
||||||
case symbol_arguments_or_redirections_list:
|
|
||||||
case symbol_argument_or_redirection:
|
|
||||||
fprintf(stderr, "Unexpected token type %ls at index %ld. This should have been handled by the parent.\n", token_type_description(parse_node.type).c_str(), exec_node.parse_node_idx);
|
|
||||||
PARSER_DIE();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case parse_token_type_end:
|
|
||||||
PARSE_ASSERT(parse_node.child_count == 0);
|
|
||||||
pop();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "Unhandled token type %ls at index %ld\n", token_type_description(parse_node.type).c_str(), exec_node.parse_node_idx);
|
|
||||||
PARSER_DIE();
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool parse_exec_t::visit_next_node(parse_execution_visitor_t *v)
|
|
||||||
{
|
|
||||||
PARSE_ASSERT(v != NULL);
|
|
||||||
PARSE_ASSERT(visitor == NULL);
|
|
||||||
if (exec_nodes.empty())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
visitor = v;
|
|
||||||
run_top_node();
|
|
||||||
visitor = NULL;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void parse_exec_t::enter_parse_node(size_t idx)
|
|
||||||
{
|
|
||||||
PARSE_ASSERT(idx < parse_tree.size());
|
|
||||||
exec_node_t exec(idx);
|
|
||||||
exec_nodes.push_back(exec);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
parse_execution_context_t::parse_execution_context_t(const parse_node_tree_t &n, const wcstring &s)
|
|
||||||
{
|
|
||||||
ctx = new parse_exec_t(n, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
parse_execution_context_t::~parse_execution_context_t()
|
|
||||||
{
|
|
||||||
delete ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool parse_execution_context_t::visit_next_node(parse_execution_visitor_t *visitor)
|
|
||||||
{
|
|
||||||
return ctx->visit_next_node(visitor);
|
|
||||||
}
|
|
||||||
|
|
||||||
void parse_execution_context_t::get_source(node_offset_t idx, wcstring *result) const
|
|
||||||
{
|
|
||||||
return ctx->get_node_string(idx, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
173
parse_exec.h
173
parse_exec.h
|
@ -1,173 +0,0 @@
|
||||||
/**\file parse_exec.h
|
|
||||||
|
|
||||||
Programmatic execution of a parse tree
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FISH_PARSE_EXEC_H
|
|
||||||
#define FISH_PARSE_EXEC_H
|
|
||||||
|
|
||||||
#include "parse_tree.h"
|
|
||||||
|
|
||||||
struct parse_execution_visitor_t;
|
|
||||||
class parse_exec_t;
|
|
||||||
class parse_execution_context_t
|
|
||||||
{
|
|
||||||
parse_exec_t *ctx; //owned
|
|
||||||
|
|
||||||
public:
|
|
||||||
parse_execution_context_t(const parse_node_tree_t &n, const wcstring &s);
|
|
||||||
~parse_execution_context_t();
|
|
||||||
|
|
||||||
bool visit_next_node(parse_execution_visitor_t *visitor);
|
|
||||||
|
|
||||||
// Gets the source for a node at a given index
|
|
||||||
void get_source(node_offset_t idx, wcstring *result) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct exec_argument_t
|
|
||||||
{
|
|
||||||
node_offset_t parse_node_idx;
|
|
||||||
exec_argument_t(node_offset_t p) : parse_node_idx(p)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
exec_argument_t()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
typedef std::vector<exec_argument_t> exec_argument_list_t;
|
|
||||||
|
|
||||||
struct exec_redirection_t
|
|
||||||
{
|
|
||||||
node_offset_t parse_node_idx;
|
|
||||||
};
|
|
||||||
typedef std::vector<exec_redirection_t> exec_redirection_list_t;
|
|
||||||
|
|
||||||
struct exec_arguments_and_redirections_t
|
|
||||||
{
|
|
||||||
exec_argument_list_t arguments;
|
|
||||||
exec_redirection_list_t redirections;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct exec_basic_statement_t
|
|
||||||
{
|
|
||||||
// Node containing the command
|
|
||||||
node_offset_t command_idx;
|
|
||||||
|
|
||||||
// Arguments
|
|
||||||
exec_arguments_and_redirections_t arguments_and_redirections;
|
|
||||||
|
|
||||||
// Decoration
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
decoration_plain,
|
|
||||||
decoration_command,
|
|
||||||
decoration_builtin
|
|
||||||
} decoration;
|
|
||||||
|
|
||||||
exec_basic_statement_t();
|
|
||||||
|
|
||||||
void set_decoration(uint32_t k)
|
|
||||||
{
|
|
||||||
PARSE_ASSERT(k == parse_keyword_none || k == parse_keyword_command || k == parse_keyword_builtin);
|
|
||||||
switch (k)
|
|
||||||
{
|
|
||||||
case parse_keyword_none:
|
|
||||||
decoration = decoration_plain;
|
|
||||||
break;
|
|
||||||
case parse_keyword_command:
|
|
||||||
decoration = decoration_command;
|
|
||||||
break;
|
|
||||||
case parse_keyword_builtin:
|
|
||||||
decoration = decoration_builtin;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PARSER_DIE();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const exec_argument_list_t &arguments() const
|
|
||||||
{
|
|
||||||
return arguments_and_redirections.arguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
const exec_redirection_list_t &redirections() const
|
|
||||||
{
|
|
||||||
return arguments_and_redirections.redirections;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct exec_function_header_t
|
|
||||||
{
|
|
||||||
// Node containing the function name
|
|
||||||
node_offset_t name_idx;
|
|
||||||
|
|
||||||
// Node containing the function body
|
|
||||||
node_offset_t body_idx;
|
|
||||||
|
|
||||||
// Arguments
|
|
||||||
exec_argument_list_t arguments;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct exec_block_statement_t
|
|
||||||
{
|
|
||||||
// Arguments
|
|
||||||
exec_arguments_and_redirections_t arguments_and_redirections;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct exec_if_clause_t
|
|
||||||
{
|
|
||||||
// Node containing the body of the if statement
|
|
||||||
node_offset_t body;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct exec_switch_case_t
|
|
||||||
{
|
|
||||||
exec_argument_list_t arguments;
|
|
||||||
node_offset_t body;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct exec_switch_statement_t
|
|
||||||
{
|
|
||||||
exec_argument_t argument;
|
|
||||||
std::vector<exec_switch_case_t> cases;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct parse_execution_visitor_t
|
|
||||||
{
|
|
||||||
node_offset_t node_idx;
|
|
||||||
parse_execution_context_t *context;
|
|
||||||
|
|
||||||
parse_execution_visitor_t() : node_idx(0), context(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool enter_job_list(void)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
virtual bool enter_job(void)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
virtual void visit_statement(void) { }
|
|
||||||
virtual void visit_function(const exec_function_header_t &function) { }
|
|
||||||
virtual bool enter_block_statement(const exec_block_statement_t &statement)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void enter_if_clause(const exec_if_clause_t &statement) { }
|
|
||||||
virtual void exit_if_clause(const exec_if_clause_t &statement) { }
|
|
||||||
|
|
||||||
virtual void visit_switch_statement(const exec_switch_statement_t &header) { }
|
|
||||||
|
|
||||||
|
|
||||||
virtual void visit_boolean_statement(void) { }
|
|
||||||
virtual void visit_basic_statement(const exec_basic_statement_t &statement) { }
|
|
||||||
virtual void exit_job(void) { }
|
|
||||||
virtual void exit_job_list(void) { }
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
Reference in a new issue