diff options
author | ridiculousfish <corydoras@ridiculousfish.com> | 2014-01-01 15:29:56 -0800 |
---|---|---|
committer | ridiculousfish <corydoras@ridiculousfish.com> | 2014-01-01 15:29:56 -0800 |
commit | fb882f0b695d88a3211cdae97f18d955427b0b18 (patch) | |
tree | 8be6a6b1f55489165adeca0179bfc0a55cc936c1 /parse_tree.cpp | |
parent | 27cba56761de987c778937521987759475e27051 (diff) |
Support for stack overflow and infinite recursion detection in new
parser
Diffstat (limited to 'parse_tree.cpp')
-rw-r--r-- | parse_tree.cpp | 62 |
1 files changed, 61 insertions, 1 deletions
diff --git a/parse_tree.cpp b/parse_tree.cpp index 222af8af..81973c61 100644 --- a/parse_tree.cpp +++ b/parse_tree.cpp @@ -1405,7 +1405,7 @@ enum token_type parse_node_tree_t::type_for_redirection(const parse_node_t &redi return result; } -const parse_node_t *parse_node_tree_t::header_node_for_block_statement(const parse_node_t &node) +const parse_node_t *parse_node_tree_t::header_node_for_block_statement(const parse_node_t &node) const { const parse_node_t *result = NULL; if (node.type == symbol_block_statement) @@ -1418,3 +1418,63 @@ const parse_node_t *parse_node_tree_t::header_node_for_block_statement(const par } return result; } + +parse_node_tree_t::parse_node_list_t parse_node_tree_t::specific_statements_for_job(const parse_node_t &job) const +{ + assert(job.type == symbol_job); + parse_node_list_t result; + + /* Initial statement (non-specific) */ + result.push_back(get_child(job, 0, symbol_statement)); + + /* Our cursor variable. Walk over the list of continuations. */ + const parse_node_t *continuation = get_child(job, 1, symbol_job_continuation); + while (continuation != NULL && continuation->child_count > 0) + { + result.push_back(get_child(*continuation, 1, symbol_statement)); + continuation = get_child(*continuation, 2, symbol_job_continuation); + } + + /* Result now contains a list of statements. But we want a list of specific statements e.g. symbol_switch_statement. So replace them in-place in the vector. */ + for (size_t i=0; i < result.size(); i++) + { + const parse_node_t *statement = result.at(i); + assert(statement->type == symbol_statement); + result.at(i) = this->get_child(*statement, 0); + } + + return result; +} + +const parse_node_t *parse_node_tree_t::next_job_in_job_list(const parse_node_t &top_job_list, const parse_node_t **out_list_tail) const +{ + assert(top_job_list.type == symbol_job_list); + + /* Our cursor variable */ + const parse_node_t *job_list = &top_job_list; + + /* Skip over a run of empty jobs */ + assert(job_list->type == symbol_job_list); + while (job_list->production_idx == 2) + { + job_list = this->get_child(*job_list, 1, symbol_job_list); + } + + /* Should now be at production 0 or 1 */ + assert(job_list->type == symbol_job_list); + assert(job_list->production_idx == 0 || job_list->production_idx == 1); + + /* Pull out the job */ + const parse_node_t *job = NULL; + const parse_node_t *list_tail = NULL; + if (job_list->production_idx == 1) + { + job = this->get_child(*job_list, 0, symbol_job); + list_tail = this->get_child(*job_list, 1, symbol_job_list); + } + + /* Return them */ + if (out_list_tail != NULL) + *out_list_tail = list_tail; + return job; +} |