mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 12:53:13 +00:00
More work on new parser
This commit is contained in:
parent
048f08080d
commit
e2a506e54a
5 changed files with 257 additions and 118 deletions
|
@ -76,6 +76,7 @@
|
||||||
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 */; };
|
||||||
|
@ -1112,6 +1113,7 @@
|
||||||
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 */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
147
parse_exec.cpp
147
parse_exec.cpp
|
@ -1 +1,148 @@
|
||||||
#include "parse_exec.h"
|
#include "parse_exec.h"
|
||||||
|
#include <stack>
|
||||||
|
|
||||||
|
|
||||||
|
struct exec_node_t
|
||||||
|
{
|
||||||
|
node_offset_t parse_node_idx;
|
||||||
|
|
||||||
|
exec_node_t(size_t pni) : parse_node_idx(pni)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~exec_node_t();
|
||||||
|
};
|
||||||
|
|
||||||
|
exec_node_t::~exec_node_t()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
struct exec_redirection_t : public exec_node_t
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct exec_argument_t : public exec_node_t
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct exec_statement_t
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
decoration_plain,
|
||||||
|
decoration_command,
|
||||||
|
decoration_builtin
|
||||||
|
} decoration;
|
||||||
|
|
||||||
|
std::vector<exec_argument_t> arguments;
|
||||||
|
std::vector<exec_redirection_t> redirections;
|
||||||
|
};
|
||||||
|
|
||||||
|
class parse_exec_t
|
||||||
|
{
|
||||||
|
parse_node_tree_t parse_tree;
|
||||||
|
wcstring src;
|
||||||
|
std::vector<exec_node_t> exec_nodes;
|
||||||
|
|
||||||
|
parse_exec_t(const parse_node_tree_t &tree, const wcstring &s) : parse_tree(tree), src(s)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop_push(uint32_t child_idx)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
exec_nodes.pop_back();
|
||||||
|
exec_nodes.push_back(child_node_idx);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void simulate(void);
|
||||||
|
void enter_parse_node(size_t idx);
|
||||||
|
void run_top_node(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
void parse_exec_t::run_top_node()
|
||||||
|
{
|
||||||
|
PARSE_ASSERT(! exec_nodes.empty());
|
||||||
|
exec_node_t &top = exec_nodes.back();
|
||||||
|
const parse_node_t &parse_node = parse_tree.at(top.parse_node_idx);
|
||||||
|
|
||||||
|
switch (parse_node.type)
|
||||||
|
{
|
||||||
|
case symbol_statement_list:
|
||||||
|
PARSE_ASSERT(parse_node.child_count == 0 || parse_node.child_count == 2);
|
||||||
|
if (parse_node.child_count == 0)
|
||||||
|
{
|
||||||
|
// Statement list done
|
||||||
|
exec_nodes.pop_back();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// First child is a statement, next is the rest of the list
|
||||||
|
node_offset_t head = parse_node.child_start;
|
||||||
|
node_offset_t tail = parse_node.child_start + 1;
|
||||||
|
exec_nodes.pop_back();
|
||||||
|
exec_nodes.push_back(tail);
|
||||||
|
exec_nodes.push_back(head);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case symbol_statement:
|
||||||
|
PARSE_ASSERT(parse_node.child_count == 1);
|
||||||
|
pop_push(0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case decorated_statement:
|
||||||
|
PARSE_ASSERT(parse_node.child_count == 1 || parse_node.child_count == 2 );
|
||||||
|
pop_push(0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Unhandled token type %ld\n", (long)parse_node.type);
|
||||||
|
PARSER_DIE();
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
wcstring parse_exec_t::simulate(void)
|
||||||
|
{
|
||||||
|
PARSE_ASSERT(exec_nodes.empty());
|
||||||
|
assemble_statement_list(0);
|
||||||
|
enter_parse_node(0);
|
||||||
|
run_node();
|
||||||
|
}
|
||||||
|
|
||||||
|
wcstring parse_execution_context_t::simulate()
|
||||||
|
{
|
||||||
|
if (parse_tree.empty())
|
||||||
|
return L"(empty!)";
|
||||||
|
|
||||||
|
PARSE_ASSERT(node_idx < nodes.size());
|
||||||
|
PARSE_ASSERT(nodes.at(node_idx).type == symbol_statement_list);
|
||||||
|
|
||||||
|
wcstring result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_execution_context_t::parse_execution_context_t(const parse_node_tree_t &n, const wcstring &s)
|
||||||
|
{
|
||||||
|
ctx = new parse_exec_t(n, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
wcstring parse_execution_context_t::simulate(void)
|
||||||
|
{
|
||||||
|
return ctx->simulate();
|
||||||
|
}
|
||||||
|
|
15
parse_exec.h
15
parse_exec.h
|
@ -3,9 +3,20 @@
|
||||||
Programmatic execution of a parse tree
|
Programmatic execution of a parse tree
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef FISH_PARSE_TREE_H
|
#ifndef FISH_PARSE_EXEC_H
|
||||||
#define FISH_PARSE_TREE_H
|
#define FISH_PARSE_EXEC_H
|
||||||
|
|
||||||
#include "parse_tree.h"
|
#include "parse_tree.h"
|
||||||
|
|
||||||
|
class parse_exec_t;
|
||||||
|
class parse_execution_context_t
|
||||||
|
{
|
||||||
|
parse_exec_t *ctx;
|
||||||
|
|
||||||
|
public:
|
||||||
|
parse_execution_context_t(const parse_node_tree_t &n, const wcstring &s);
|
||||||
|
wcstring simulate(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
121
parse_tree.cpp
121
parse_tree.cpp
|
@ -1,48 +1,10 @@
|
||||||
#include "expression.h"
|
#include "parse_tree.h"
|
||||||
#include "tokenizer.h"
|
#include "tokenizer.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
struct parse_node_t;
|
|
||||||
typedef size_t node_offset_t;
|
|
||||||
typedef std::vector<parse_node_t> parse_node_tree_t;
|
|
||||||
|
|
||||||
#define PARSE_ASSERT(a) assert(a)
|
|
||||||
|
|
||||||
#define PARSER_DIE() assert(0)
|
|
||||||
|
|
||||||
class parse_command_t;
|
class parse_command_t;
|
||||||
|
|
||||||
enum parse_token_type_t
|
|
||||||
{
|
|
||||||
token_type_invalid,
|
|
||||||
|
|
||||||
// Non-terminal tokens
|
|
||||||
symbol_statement_list,
|
|
||||||
symbol_statement,
|
|
||||||
symbol_block_statement,
|
|
||||||
symbol_block_header,
|
|
||||||
symbol_if_header,
|
|
||||||
symbol_for_header,
|
|
||||||
symbol_while_header,
|
|
||||||
symbol_begin_header,
|
|
||||||
symbol_function_header,
|
|
||||||
symbol_boolean_statement,
|
|
||||||
symbol_decorated_statement,
|
|
||||||
symbol_plain_statement,
|
|
||||||
symbol_arguments_or_redirections_list,
|
|
||||||
symbol_argument_or_redirection,
|
|
||||||
|
|
||||||
// Terminal types
|
|
||||||
parse_token_type_string,
|
|
||||||
parse_token_type_pipe,
|
|
||||||
parse_token_type_redirection,
|
|
||||||
parse_token_background,
|
|
||||||
parse_token_type_end,
|
|
||||||
parse_token_type_terminate,
|
|
||||||
|
|
||||||
FIRST_PARSE_TOKEN_TYPE = parse_token_type_string
|
|
||||||
};
|
|
||||||
|
|
||||||
static wcstring token_type_description(parse_token_type_t type)
|
static wcstring token_type_description(parse_token_type_t type)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
|
@ -75,25 +37,11 @@ static wcstring token_type_description(parse_token_type_t type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum parse_keyword_t
|
wcstring parse_node_t::describe(void) const
|
||||||
{
|
{
|
||||||
parse_keyword_none,
|
wcstring result = token_type_description(type);
|
||||||
parse_keyword_if,
|
return result;
|
||||||
parse_keyword_else,
|
}
|
||||||
parse_keyword_for,
|
|
||||||
parse_keyword_in,
|
|
||||||
parse_keyword_while,
|
|
||||||
parse_keyword_begin,
|
|
||||||
parse_keyword_function,
|
|
||||||
parse_keyword_switch,
|
|
||||||
parse_keyword_end,
|
|
||||||
parse_keyword_and,
|
|
||||||
parse_keyword_or,
|
|
||||||
parse_keyword_not,
|
|
||||||
parse_keyword_command,
|
|
||||||
parse_keyword_builtin
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct parse_token_t
|
struct parse_token_t
|
||||||
{
|
{
|
||||||
|
@ -135,41 +83,6 @@ static parse_token_t parse_token_from_tokenizer_token(enum token_type tokenizer_
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Base class for nodes of a parse tree */
|
|
||||||
class parse_node_t
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/* Start in the source code */
|
|
||||||
size_t source_start;
|
|
||||||
|
|
||||||
/* Length of our range in the source code */
|
|
||||||
size_t source_length;
|
|
||||||
|
|
||||||
/* Children */
|
|
||||||
node_offset_t child_start;
|
|
||||||
node_offset_t child_count;
|
|
||||||
|
|
||||||
/* Type-dependent data */
|
|
||||||
uint32_t tag;
|
|
||||||
|
|
||||||
/* Type of the node */
|
|
||||||
enum parse_token_type_t type;
|
|
||||||
|
|
||||||
|
|
||||||
/* Description */
|
|
||||||
wcstring describe(void) const
|
|
||||||
{
|
|
||||||
wcstring result = token_type_description(type);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Constructor */
|
|
||||||
explicit parse_node_t(parse_token_type_t ty) : type(ty), source_start(0), source_length(0), child_start(0), child_count(0), tag(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static void dump_tree_recursive(const parse_node_tree_t &nodes, const wcstring &src, size_t start, size_t indent, wcstring *result, size_t *line)
|
static void dump_tree_recursive(const parse_node_tree_t &nodes, const wcstring &src, size_t start, size_t indent, wcstring *result, size_t *line)
|
||||||
{
|
{
|
||||||
assert(start < nodes.size());
|
assert(start < nodes.size());
|
||||||
|
@ -222,30 +135,6 @@ struct parse_stack_element_t
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class parse_execution_context_t
|
|
||||||
{
|
|
||||||
wcstring src;
|
|
||||||
const parse_node_tree_t nodes;
|
|
||||||
size_t node_idx;
|
|
||||||
|
|
||||||
public:
|
|
||||||
parse_execution_context_t(const parse_node_tree_t &n, const wcstring &s) : src(s), nodes(n), node_idx(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
wcstring simulate(void);
|
|
||||||
};
|
|
||||||
|
|
||||||
wcstring parse_execution_context_t::simulate()
|
|
||||||
{
|
|
||||||
if (nodes.empty())
|
|
||||||
return L"(empty!");
|
|
||||||
|
|
||||||
PARSE_ASSERT(node_idx < nodes.size());
|
|
||||||
PARSE_ASSERT(nodes.at(node_idx).type == symbol_statement_list);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class parse_ll_t
|
class parse_ll_t
|
||||||
{
|
{
|
||||||
friend class parse_t;
|
friend class parse_t;
|
||||||
|
|
90
parse_tree.h
90
parse_tree.h
|
@ -12,6 +12,10 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "tokenizer.h"
|
#include "tokenizer.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#define PARSE_ASSERT(a) assert(a)
|
||||||
|
#define PARSER_DIE() assert(0)
|
||||||
|
|
||||||
|
|
||||||
class parse_ll_t;
|
class parse_ll_t;
|
||||||
|
@ -25,6 +29,92 @@ class parse_t
|
||||||
void parse(const wcstring &str);
|
void parse(const wcstring &str);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class parse_node_t;
|
||||||
|
typedef std::vector<parse_node_t> parse_node_tree_t;
|
||||||
|
typedef size_t node_offset_t;
|
||||||
|
|
||||||
|
|
||||||
|
enum parse_token_type_t
|
||||||
|
{
|
||||||
|
token_type_invalid,
|
||||||
|
|
||||||
|
// Non-terminal tokens
|
||||||
|
symbol_statement_list,
|
||||||
|
symbol_statement,
|
||||||
|
symbol_block_statement,
|
||||||
|
symbol_block_header,
|
||||||
|
symbol_if_header,
|
||||||
|
symbol_for_header,
|
||||||
|
symbol_while_header,
|
||||||
|
symbol_begin_header,
|
||||||
|
symbol_function_header,
|
||||||
|
symbol_boolean_statement,
|
||||||
|
symbol_decorated_statement,
|
||||||
|
symbol_plain_statement,
|
||||||
|
symbol_arguments_or_redirections_list,
|
||||||
|
symbol_argument_or_redirection,
|
||||||
|
|
||||||
|
// Terminal types
|
||||||
|
parse_token_type_string,
|
||||||
|
parse_token_type_pipe,
|
||||||
|
parse_token_type_redirection,
|
||||||
|
parse_token_background,
|
||||||
|
parse_token_type_end,
|
||||||
|
parse_token_type_terminate,
|
||||||
|
|
||||||
|
FIRST_PARSE_TOKEN_TYPE = parse_token_type_string
|
||||||
|
};
|
||||||
|
|
||||||
|
enum parse_keyword_t
|
||||||
|
{
|
||||||
|
parse_keyword_none,
|
||||||
|
parse_keyword_if,
|
||||||
|
parse_keyword_else,
|
||||||
|
parse_keyword_for,
|
||||||
|
parse_keyword_in,
|
||||||
|
parse_keyword_while,
|
||||||
|
parse_keyword_begin,
|
||||||
|
parse_keyword_function,
|
||||||
|
parse_keyword_switch,
|
||||||
|
parse_keyword_end,
|
||||||
|
parse_keyword_and,
|
||||||
|
parse_keyword_or,
|
||||||
|
parse_keyword_not,
|
||||||
|
parse_keyword_command,
|
||||||
|
parse_keyword_builtin
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Base class for nodes of a parse tree */
|
||||||
|
class parse_node_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/* Type of the node */
|
||||||
|
enum parse_token_type_t type;
|
||||||
|
|
||||||
|
/* Start in the source code */
|
||||||
|
size_t source_start;
|
||||||
|
|
||||||
|
/* Length of our range in the source code */
|
||||||
|
size_t source_length;
|
||||||
|
|
||||||
|
/* Children */
|
||||||
|
node_offset_t child_start;
|
||||||
|
node_offset_t child_count;
|
||||||
|
|
||||||
|
/* Type-dependent data */
|
||||||
|
uint32_t tag;
|
||||||
|
|
||||||
|
|
||||||
|
/* Description */
|
||||||
|
wcstring describe(void) const;
|
||||||
|
|
||||||
|
/* Constructor */
|
||||||
|
explicit parse_node_t(parse_token_type_t ty) : type(ty), source_start(0), source_length(0), child_start(0), child_count(0), tag(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Fish grammar:
|
/* Fish grammar:
|
||||||
|
|
Loading…
Reference in a new issue