Rework tree generation mode and API
Store tree nodes in congruent, compact arena array. Define handle types to refer to tree nodes rather than pointers to structure instances. Free tree with context.
This commit is contained in:
1 parent
dddb1b5089
commit
5fc712c6ee
39 files changed
+1349
-811
No files matched your search
+136
-91
@@ -68,6 +68,18 @@ const char * <%= @grammar.prefix %>token_names[] = {
|
||||
context->text_position.row = 1u;
|
||||
context->text_position.col = 1u;
|
||||
context->mode = <%= @lexer.mode_id("default") %>;
|
||||
<% if @grammar.tree %>
|
||||
|
||||
/* Reserve node ID 0 as the null tree node. */
|
||||
<% if @cpp %>
|
||||
context-><%= @grammar.prefix %>tree_nodes.resize(1);
|
||||
<% else %>
|
||||
context-><%= @grammar.prefix %>tree_nodes_capacity = 16u;
|
||||
context-><%= @grammar.prefix %>tree_nodes = (<%= @grammar.prefix %>node_data_t *)malloc(16u * sizeof(<%= @grammar.prefix %>node_data_t));
|
||||
memset(&context-><%= @grammar.prefix %>tree_nodes[0], 0, sizeof(<%= @grammar.prefix %>node_data_t));
|
||||
context-><%= @grammar.prefix %>tree_nodes_length = 1u;
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
return context;
|
||||
}
|
||||
@@ -84,9 +96,27 @@ const char * <%= @grammar.prefix %>token_names[] = {
|
||||
*/
|
||||
void <%= @grammar.prefix %>context_delete(<%= @grammar.prefix %>context_t * context)
|
||||
{
|
||||
<% if @grammar.tree && @grammar.free_token_node != "" %>
|
||||
<% if @cpp %>
|
||||
for (size_t i = 0u; i < context-><%= @grammar.prefix %>tree_nodes.size(); i++)
|
||||
<% else %>
|
||||
for (size_t i = 0u; i < context-><%= @grammar.prefix %>tree_nodes_length; i++)
|
||||
<% end %>
|
||||
{
|
||||
if (context-><%= @grammar.prefix %>tree_nodes[i].is_token)
|
||||
{
|
||||
<%= @grammar.prefix %>node_data_t * token_tree_node = &context-><%= @grammar.prefix %>tree_nodes[i];
|
||||
<%= expand_code(@grammar.free_token_node, false, nil, nil) %>
|
||||
}
|
||||
}
|
||||
<% end %>
|
||||
<% if @cpp %>
|
||||
delete context;
|
||||
<% else %>
|
||||
<% if @grammar.tree %>
|
||||
free(context-><%= @grammar.prefix %>tree_nodes);
|
||||
free(context-><%= @grammar.prefix %>tree_children);
|
||||
<% end %>
|
||||
free(context);
|
||||
<% end %>
|
||||
}
|
||||
@@ -713,8 +743,8 @@ typedef struct
|
||||
size_t state_id;
|
||||
|
||||
<% if @grammar.tree %>
|
||||
/** tree node. */
|
||||
void * tree_node;
|
||||
/** Tree node ID. */
|
||||
<%= @grammar.prefix %>node_id_t node_id;
|
||||
<% else %>
|
||||
<%= @grammar.prefix %>position_t position;
|
||||
<%= @grammar.prefix %>position_t end_position;
|
||||
@@ -723,18 +753,6 @@ typedef struct
|
||||
<% end %>
|
||||
} state_value_t;
|
||||
|
||||
<% if @grammar.tree %>
|
||||
/** Common tree node structure. */
|
||||
typedef struct TreeNode_s
|
||||
{
|
||||
<%= @grammar.prefix %>position_t position;
|
||||
<%= @grammar.prefix %>position_t end_position;
|
||||
uint16_t n_fields;
|
||||
uint8_t is_token;
|
||||
struct TreeNode_s * fields[];
|
||||
} TreeNode;
|
||||
<% end %>
|
||||
|
||||
/** Parser shift table. */
|
||||
static const shift_t parser_shift_table[] = {
|
||||
<% @parser.shift_table.each do |shift| %>
|
||||
@@ -872,6 +890,77 @@ static void state_values_stack_free(state_values_stack_t * stack)
|
||||
free(stack->entries);
|
||||
}
|
||||
|
||||
<% if @grammar.tree %>
|
||||
/* Tree arena helpers. */
|
||||
|
||||
/**
|
||||
* Allocate a new (zeroed) tree node in the context arena.
|
||||
*
|
||||
* @return The new node ID.
|
||||
*/
|
||||
static <%= @grammar.prefix %>node_id_t tree_new_node(<%= @grammar.prefix %>context_t * context)
|
||||
{
|
||||
<% if @cpp %>
|
||||
<%= @grammar.prefix %>node_id_t id = (<%= @grammar.prefix %>node_id_t)context-><%= @grammar.prefix %>tree_nodes.size();
|
||||
context-><%= @grammar.prefix %>tree_nodes.emplace_back();
|
||||
return id;
|
||||
<% else %>
|
||||
if (context-><%= @grammar.prefix %>tree_nodes_length >= context-><%= @grammar.prefix %>tree_nodes_capacity)
|
||||
{
|
||||
size_t new_capacity = context-><%= @grammar.prefix %>tree_nodes_capacity * 2u;
|
||||
<%= @grammar.prefix %>node_data_t * new_nodes = (<%= @grammar.prefix %>node_data_t *)malloc(new_capacity * sizeof(<%= @grammar.prefix %>node_data_t));
|
||||
memcpy(new_nodes, context-><%= @grammar.prefix %>tree_nodes, context-><%= @grammar.prefix %>tree_nodes_length * sizeof(<%= @grammar.prefix %>node_data_t));
|
||||
free(context-><%= @grammar.prefix %>tree_nodes);
|
||||
context-><%= @grammar.prefix %>tree_nodes = new_nodes;
|
||||
context-><%= @grammar.prefix %>tree_nodes_capacity = new_capacity;
|
||||
}
|
||||
<%= @grammar.prefix %>node_id_t id = (<%= @grammar.prefix %>node_id_t)context-><%= @grammar.prefix %>tree_nodes_length;
|
||||
memset(&context-><%= @grammar.prefix %>tree_nodes[id], 0, sizeof(<%= @grammar.prefix %>node_data_t));
|
||||
context-><%= @grammar.prefix %>tree_nodes_length += 1u;
|
||||
return id;
|
||||
<% end %>
|
||||
}
|
||||
|
||||
/**
|
||||
* Reserve n contiguous (zeroed) child slots in the shared children array.
|
||||
*
|
||||
* @return The offset of the first reserved slot.
|
||||
*/
|
||||
static <%= @grammar.prefix %>node_id_t tree_reserve_children(<%= @grammar.prefix %>context_t * context, size_t n)
|
||||
{
|
||||
<% if @cpp %>
|
||||
<%= @grammar.prefix %>node_id_t offset = (<%= @grammar.prefix %>node_id_t)context-><%= @grammar.prefix %>tree_children.size();
|
||||
context-><%= @grammar.prefix %>tree_children.resize(context-><%= @grammar.prefix %>tree_children.size() + n);
|
||||
return offset;
|
||||
<% else %>
|
||||
size_t offset = context-><%= @grammar.prefix %>tree_children_length;
|
||||
size_t needed = offset + n;
|
||||
if (needed > context-><%= @grammar.prefix %>tree_children_capacity)
|
||||
{
|
||||
size_t new_capacity = context-><%= @grammar.prefix %>tree_children_capacity ? context-><%= @grammar.prefix %>tree_children_capacity : 1u;
|
||||
while (new_capacity < needed)
|
||||
{
|
||||
new_capacity *= 2u;
|
||||
}
|
||||
<%= @grammar.prefix %>node_id_t * new_children = (<%= @grammar.prefix %>node_id_t *)malloc(new_capacity * sizeof(<%= @grammar.prefix %>node_id_t));
|
||||
if (context-><%= @grammar.prefix %>tree_children != NULL)
|
||||
{
|
||||
memcpy(new_children, context-><%= @grammar.prefix %>tree_children, context-><%= @grammar.prefix %>tree_children_length * sizeof(<%= @grammar.prefix %>node_id_t));
|
||||
free(context-><%= @grammar.prefix %>tree_children);
|
||||
}
|
||||
context-><%= @grammar.prefix %>tree_children = new_children;
|
||||
context-><%= @grammar.prefix %>tree_children_capacity = new_capacity;
|
||||
}
|
||||
memset(&context-><%= @grammar.prefix %>tree_children[offset], 0, n * sizeof(<%= @grammar.prefix %>node_id_t));
|
||||
context-><%= @grammar.prefix %>tree_children_length = needed;
|
||||
return (<%= @grammar.prefix %>node_id_t)offset;
|
||||
<% end %>
|
||||
}
|
||||
|
||||
/* Tree node field accessor functions. */
|
||||
<%= c_tree_accessor_defs %>
|
||||
<% end %>
|
||||
|
||||
<% unless @grammar.tree %>
|
||||
/**
|
||||
* Get the rule position (start or end) for the currently matched rule.
|
||||
@@ -936,7 +1025,7 @@ static <%= @grammar.prefix %>position_t get_rule_position(state_values_stack_t *
|
||||
* @retval P_USER_TERMINATED
|
||||
* User requested to terminate parsing.
|
||||
*/
|
||||
static size_t parser_user_code(<%= @grammar.tree ? "void" : "#{@grammar.prefix}value_t" %> * _pvalue, uint32_t rule, state_values_stack_t * statevalues, uint32_t n_states, <%= @grammar.prefix %>context_t * context)
|
||||
static size_t parser_user_code(<%= @grammar.tree ? "#{@grammar.prefix}node_id_t _node_id" : "#{@grammar.prefix}value_t * _pvalue" %>, uint32_t rule, state_values_stack_t * statevalues, uint32_t n_states, <%= @grammar.prefix %>context_t * context)
|
||||
{
|
||||
switch (rule)
|
||||
{
|
||||
@@ -1041,7 +1130,7 @@ static size_t parse_from(<%= @grammar.prefix %>context_t * context, size_t start
|
||||
size_t reduced_rule_set = INVALID_ID;
|
||||
size_t last_shifted_rule_set_id = INVALID_ID;
|
||||
<% if @grammar.tree %>
|
||||
void * reduced_parser_node;
|
||||
<%= @grammar.prefix %>node_id_t reduced_parser_node;
|
||||
<% else %>
|
||||
<%= @grammar.prefix %>position_t reduced_position;
|
||||
<%= @grammar.prefix %>position_t reduced_end_position;
|
||||
@@ -1087,7 +1176,7 @@ static size_t parse_from(<%= @grammar.prefix %>context_t * context, size_t start
|
||||
{
|
||||
/* Successful parse. */
|
||||
<% if @grammar.tree %>
|
||||
context->parse_result = state_values_stack_index(&statevalues, -1)->tree_node;
|
||||
context->parse_result = state_values_stack_index(&statevalues, -1)->node_id;
|
||||
<% else %>
|
||||
context->parse_result = state_values_stack_index(&statevalues, -1)->pvalue;
|
||||
<% end %>
|
||||
@@ -1114,7 +1203,7 @@ static size_t parse_from(<%= @grammar.prefix %>context_t * context, size_t start
|
||||
context->input_index -= token_info.length;
|
||||
context->text_position = token_info.position;
|
||||
<% if @grammar.tree %>
|
||||
context->parse_result = state_values_stack_index(&statevalues, -1)->tree_node;
|
||||
context->parse_result = state_values_stack_index(&statevalues, -1)->node_id;
|
||||
<% else %>
|
||||
context->parse_result = state_values_stack_index(&statevalues, -1)->pvalue;
|
||||
<% end %>
|
||||
@@ -1137,11 +1226,8 @@ static size_t parse_from(<%= @grammar.prefix %>context_t * context, size_t start
|
||||
{
|
||||
/* We shifted a token, mark it consumed. */
|
||||
<% if @grammar.tree %>
|
||||
<% if @cpp %>
|
||||
<%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %> * token_tree_node = new <%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %>();
|
||||
<% else %>
|
||||
<%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %> * token_tree_node = (<%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %> *)malloc(sizeof(<%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %>));
|
||||
<% end %>
|
||||
<%= @grammar.prefix %>node_id_t token_node_id = tree_new_node(context);
|
||||
<%= @grammar.prefix %>node_data_t * token_tree_node = &context-><%= @grammar.prefix %>tree_nodes[token_node_id];
|
||||
token_tree_node->position = token_info.position;
|
||||
token_tree_node->end_position = token_info.end_position;
|
||||
token_tree_node->n_fields = 0u;
|
||||
@@ -1149,7 +1235,7 @@ static size_t parse_from(<%= @grammar.prefix %>context_t * context, size_t start
|
||||
token_tree_node->token = token;
|
||||
token_tree_node->pvalue = token_info.pvalue;
|
||||
<%= expand_code(@grammar.on_token_node, false, nil, nil) %>
|
||||
new_state_info->tree_node = token_tree_node;
|
||||
new_state_info->node_id = token_node_id;
|
||||
<% else %>
|
||||
new_state_info->position = token_info.position;
|
||||
new_state_info->end_position = token_info.end_position;
|
||||
@@ -1161,7 +1247,7 @@ static size_t parse_from(<%= @grammar.prefix %>context_t * context, size_t start
|
||||
{
|
||||
/* We shifted a RuleSet. */
|
||||
<% if @grammar.tree %>
|
||||
new_state_info->tree_node = reduced_parser_node;
|
||||
new_state_info->node_id = reduced_parser_node;
|
||||
<% else %>
|
||||
new_state_info->pvalue = reduced_parser_value;
|
||||
new_state_info->position = reduced_position;
|
||||
@@ -1191,50 +1277,54 @@ static size_t parse_from(<%= @grammar.prefix %>context_t * context, size_t start
|
||||
<% if @grammar.tree %>
|
||||
if (parser_reduce_table[reduce_index].propagate_optional_target)
|
||||
{
|
||||
reduced_parser_node = state_values_stack_index(&statevalues, -1)->tree_node;
|
||||
reduced_parser_node = state_values_stack_index(&statevalues, -1)->node_id;
|
||||
}
|
||||
else if (parser_reduce_table[reduce_index].n_states > 0)
|
||||
{
|
||||
size_t n_fields = parser_reduce_table[reduce_index].rule_set_node_field_array_size;
|
||||
size_t bytes = sizeof(TreeNode) + n_fields * sizeof(void *);
|
||||
TreeNode * node = (TreeNode *)malloc(bytes);
|
||||
memset(node, 0, bytes);
|
||||
node->position = INVALID_POSITION;
|
||||
node->end_position = INVALID_POSITION;
|
||||
node->n_fields = n_fields;
|
||||
uint16_t n_fields = parser_reduce_table[reduce_index].rule_set_node_field_array_size;
|
||||
/* Reserve child slots. New slots are zero-initialized
|
||||
* (null node ID) so absent optional children remain null. */
|
||||
<%= @grammar.prefix %>node_id_t child_offset = tree_reserve_children(context, n_fields);
|
||||
if (parser_reduce_table[reduce_index].rule_set_node_field_index_map == NULL)
|
||||
{
|
||||
for (size_t i = 0; i < parser_reduce_table[reduce_index].n_states; i++)
|
||||
{
|
||||
node->fields[i] = (TreeNode *)state_values_stack_index(&statevalues, -(int)parser_reduce_table[reduce_index].n_states + (int)i)->tree_node;
|
||||
context-><%= @grammar.prefix %>tree_children[child_offset + i] = state_values_stack_index(&statevalues, -(int)parser_reduce_table[reduce_index].n_states + (int)i)->node_id;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < parser_reduce_table[reduce_index].n_states; i++)
|
||||
{
|
||||
node->fields[parser_reduce_table[reduce_index].rule_set_node_field_index_map[i]] = (TreeNode *)state_values_stack_index(&statevalues, -(int)parser_reduce_table[reduce_index].n_states + (int)i)->tree_node;
|
||||
context-><%= @grammar.prefix %>tree_children[child_offset + parser_reduce_table[reduce_index].rule_set_node_field_index_map[i]] = state_values_stack_index(&statevalues, -(int)parser_reduce_table[reduce_index].n_states + (int)i)->node_id;
|
||||
}
|
||||
}
|
||||
<%= @grammar.prefix %>node_id_t node_id = tree_new_node(context);
|
||||
<%= @grammar.prefix %>node_data_t * node = &context-><%= @grammar.prefix %>tree_nodes[node_id];
|
||||
node->position = INVALID_POSITION;
|
||||
node->end_position = INVALID_POSITION;
|
||||
node->child_offset = child_offset;
|
||||
node->n_fields = n_fields;
|
||||
node->is_token = 0u;
|
||||
bool position_found = false;
|
||||
for (size_t i = 0; i < n_fields; i++)
|
||||
for (uint16_t i = 0; i < n_fields; i++)
|
||||
{
|
||||
TreeNode * child = node->fields[i];
|
||||
if ((child != NULL) && <%= @grammar.prefix %>position_valid(child->position))
|
||||
<%= @grammar.prefix %>node_id_t child_id = context-><%= @grammar.prefix %>tree_children[child_offset + i];
|
||||
if ((child_id != 0u) && <%= @grammar.prefix %>position_valid(context-><%= @grammar.prefix %>tree_nodes[child_id].position))
|
||||
{
|
||||
if (!position_found)
|
||||
{
|
||||
node->position = child->position;
|
||||
node->position = context-><%= @grammar.prefix %>tree_nodes[child_id].position;
|
||||
position_found = true;
|
||||
}
|
||||
node->end_position = child->end_position;
|
||||
node->end_position = context-><%= @grammar.prefix %>tree_nodes[child_id].end_position;
|
||||
}
|
||||
}
|
||||
reduced_parser_node = node;
|
||||
reduced_parser_node = node_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
reduced_parser_node = NULL;
|
||||
reduced_parser_node = 0u;
|
||||
}
|
||||
<% if @grammar.parser_user_code_used? %>
|
||||
if (parser_user_code(reduced_parser_node, parser_reduce_table[reduce_index].rule, &statevalues, parser_reduce_table[reduce_index].n_states, context) == P_USER_TERMINATED)
|
||||
@@ -1310,14 +1400,14 @@ size_t <%= @grammar.prefix %>parse_inner_<%= start_rule %>(<%= @grammar.prefix %
|
||||
* @return Parse result value.
|
||||
*/
|
||||
<% if @grammar.tree %>
|
||||
<%= @grammar.tree_prefix %><%= @grammar.start_rules[0] %><%= @grammar.tree_suffix %> * <%= @grammar.prefix %>result(<%= @grammar.prefix %>context_t * context)
|
||||
<%= h_type(@grammar.start_rules[0]) %> <%= @grammar.prefix %>result(<%= @grammar.prefix %>context_t * context)
|
||||
{
|
||||
return (<%= @grammar.tree_prefix %><%= @grammar.start_rules[0] %><%= @grammar.tree_suffix %> *) context->parse_result;
|
||||
return <%= tree_handle(h_type(@grammar.start_rules[0]), "context->parse_result") %>;
|
||||
}
|
||||
<% @grammar.start_rules.each_with_index do |start_rule, i| %>
|
||||
<%= @grammar.tree_prefix %><%= start_rule %><%= @grammar.tree_suffix %> * <%= @grammar.prefix %>result_<%= start_rule %>(<%= @grammar.prefix %>context_t * context)
|
||||
<%= h_type(start_rule) %> <%= @grammar.prefix %>result_<%= start_rule %>(<%= @grammar.prefix %>context_t * context)
|
||||
{
|
||||
return (<%= @grammar.tree_prefix %><%= start_rule %><%= @grammar.tree_suffix %> *) context->parse_result;
|
||||
return <%= tree_handle(h_type(start_rule), "context->parse_result") %>;
|
||||
}
|
||||
<% end %>
|
||||
<% else %>
|
||||
@@ -1420,48 +1510,3 @@ size_t <%= @grammar.prefix %>user_terminate_code(<%= @grammar.prefix %>context_t
|
||||
{
|
||||
return context->token;
|
||||
}
|
||||
<% if @grammar.tree %>
|
||||
|
||||
static void tree_delete(TreeNode * node)
|
||||
{
|
||||
if (node->is_token)
|
||||
{
|
||||
<%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %> * token_tree_node = (<%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %> *)node;
|
||||
<%= expand_code(@grammar.free_token_node, false, nil, nil) %>
|
||||
<% if @cpp %>
|
||||
delete token_tree_node;
|
||||
<% else %>
|
||||
free(token_tree_node);
|
||||
<% end %>
|
||||
}
|
||||
else if (node->n_fields > 0u)
|
||||
{
|
||||
for (size_t i = 0u; i < node->n_fields; i++)
|
||||
{
|
||||
if (node->fields[i] != NULL)
|
||||
{
|
||||
tree_delete(node->fields[i]);
|
||||
}
|
||||
}
|
||||
free(node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Free all tree node memory.
|
||||
*/
|
||||
void <%= @grammar.prefix %>tree_delete(<%= @grammar.tree_prefix %><%= @grammar.start_rules[0] %><%= @grammar.tree_suffix %> * tree)
|
||||
{
|
||||
tree_delete((TreeNode *)tree);
|
||||
}
|
||||
<% @grammar.start_rules.each_with_index do |start_rule, i| %>
|
||||
|
||||
/**
|
||||
* Free all tree node memory.
|
||||
*/
|
||||
void <%= @grammar.prefix %>tree_delete_<%= start_rule %>(<%= @grammar.tree_prefix %><%= start_rule %><%= @grammar.tree_suffix %> * tree)
|
||||
{
|
||||
tree_delete((TreeNode *)tree);
|
||||
}
|
||||
<% end %>
|
||||
<% end %>
|
||||
+153
-88
@@ -105,22 +105,23 @@ public <%= typestring %> <%= @grammar.prefix %>value_get<%= name == "default" ?
|
||||
<% end %>
|
||||
|
||||
<% if @grammar.tree %>
|
||||
/** Common tree node structure. */
|
||||
private struct TreeNode
|
||||
{
|
||||
<%= @grammar.prefix %>position_t position;
|
||||
<%= @grammar.prefix %>position_t end_position;
|
||||
ushort n_fields;
|
||||
bool is_token;
|
||||
void *[0] fields;
|
||||
}
|
||||
/** Tree node ID type (index into the context node arena). ID 0 is null. */
|
||||
public alias <%= @grammar.prefix %>node_id_t = uint;
|
||||
|
||||
/** Tree node types. @{ */
|
||||
public struct <%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %>
|
||||
/**
|
||||
* Tree node record.
|
||||
*
|
||||
* All tree nodes are stored contiguously in the context node arena. Child
|
||||
* links are stored in a shared children array: a node's children
|
||||
* occupy children[child_offset .. child_offset + n_fields]. Token payload
|
||||
* fields (token, pvalue, and any user fields) are only meaningful when
|
||||
* is_token is true.
|
||||
*/
|
||||
private struct <%= @grammar.prefix %>node_data_t
|
||||
{
|
||||
/* TreeNode fields must be present in the same order here. */
|
||||
<%= @grammar.prefix %>position_t position;
|
||||
<%= @grammar.prefix %>position_t end_position;
|
||||
<%= @grammar.prefix %>node_id_t child_offset;
|
||||
ushort n_fields;
|
||||
bool is_token;
|
||||
<%= @grammar.prefix %>token_t token;
|
||||
@@ -128,22 +129,84 @@ public struct <%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %>
|
||||
<%= @grammar.token_user_fields %>
|
||||
}
|
||||
|
||||
<% @parser.rule_sets.each do |name, rule_set| %>
|
||||
<% next if name.start_with?("$") %>
|
||||
<% next if rule_set.optional? %>
|
||||
public struct <%= @grammar.tree_prefix %><%= name %><%= @grammar.tree_suffix %>
|
||||
/** Tree node handle types. @{ */
|
||||
|
||||
/** Token tree node handle. */
|
||||
public struct <%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %>
|
||||
{
|
||||
<%= @grammar.prefix %>position_t position;
|
||||
<%= @grammar.prefix %>position_t end_position;
|
||||
ushort n_fields;
|
||||
bool is_token;
|
||||
<% rule_set.tree_fields.each do |fields| %>
|
||||
union
|
||||
private <%= @grammar.prefix %>context_t * __context;
|
||||
private <%= @grammar.prefix %>node_id_t __id;
|
||||
|
||||
this(<%= @grammar.prefix %>context_t * context, <%= @grammar.prefix %>node_id_t id)
|
||||
{
|
||||
<% fields.each do |field_name, type| %>
|
||||
<%= type %> * <%= field_name %>;
|
||||
<% end %>
|
||||
this.__context = context;
|
||||
this.__id = id;
|
||||
}
|
||||
|
||||
/** Return whether this handle refers to a valid (non-null) node. */
|
||||
@property bool valid()
|
||||
{
|
||||
return __id != 0u;
|
||||
}
|
||||
|
||||
/** Access the underlying node record (token, pvalue, and user fields). */
|
||||
@property ref <%= @grammar.prefix %>node_data_t __node()
|
||||
{
|
||||
return __context.<%= @grammar.prefix %>tree_nodes[__id];
|
||||
}
|
||||
|
||||
alias __node this;
|
||||
}
|
||||
|
||||
<% tree_node_rule_sets.each do |rule_set| %>
|
||||
/** <%= rule_set.name %> tree node handle. */
|
||||
public struct <%= @grammar.tree_prefix %><%= rule_set.name %><%= @grammar.tree_suffix %>
|
||||
{
|
||||
private <%= @grammar.prefix %>context_t * __context;
|
||||
private <%= @grammar.prefix %>node_id_t __id;
|
||||
|
||||
this(<%= @grammar.prefix %>context_t * context, <%= @grammar.prefix %>node_id_t id)
|
||||
{
|
||||
this.__context = context;
|
||||
this.__id = id;
|
||||
}
|
||||
|
||||
/** Return whether this handle refers to a valid (non-null) node. */
|
||||
@property bool valid()
|
||||
{
|
||||
return __id != 0u;
|
||||
}
|
||||
|
||||
/** Text position of the first code point spanned by this node. */
|
||||
@property <%= @grammar.prefix %>position_t position()
|
||||
{
|
||||
return __context.<%= @grammar.prefix %>tree_nodes[__id].position;
|
||||
}
|
||||
|
||||
/** Text position of the last code point spanned by this node. */
|
||||
@property <%= @grammar.prefix %>position_t end_position()
|
||||
{
|
||||
return __context.<%= @grammar.prefix %>tree_nodes[__id].end_position;
|
||||
}
|
||||
|
||||
/** Number of child fields in this node. */
|
||||
@property ushort n_fields()
|
||||
{
|
||||
return __id ? __context.<%= @grammar.prefix %>tree_nodes[__id].n_fields : cast(ushort)0u;
|
||||
}
|
||||
<% rule_set.tree_fields.each_with_index do |fields, i| %>
|
||||
<% fields.each do |field_name, type| %>
|
||||
|
||||
/** Access the <%= field_name %> child node. */
|
||||
@property <%= type %> <%= field_name %>()
|
||||
{
|
||||
if (__id == 0u)
|
||||
{
|
||||
return <%= type %>(__context, 0u);
|
||||
}
|
||||
return <%= type %>(__context, __context.<%= @grammar.prefix %>tree_children[__context.<%= @grammar.prefix %>tree_nodes[__id].child_offset + <%= i %>u]);
|
||||
}
|
||||
<% end %>
|
||||
<% end %>
|
||||
}
|
||||
|
||||
@@ -196,7 +259,13 @@ public struct <%= @grammar.prefix %>context_t
|
||||
|
||||
/** Parse result value. */
|
||||
<% if @grammar.tree %>
|
||||
void * parse_result;
|
||||
<%= @grammar.prefix %>node_id_t parse_result;
|
||||
|
||||
/** Tree node arena. Node ID 0 is reserved as the null node. */
|
||||
<%= @grammar.prefix %>node_data_t[] <%= @grammar.prefix %>tree_nodes;
|
||||
|
||||
/** Shared tree child links. */
|
||||
<%= @grammar.prefix %>node_id_t[] <%= @grammar.prefix %>tree_children;
|
||||
<% else %>
|
||||
<%= @grammar.prefix %>value_t parse_result;
|
||||
<% end %>
|
||||
@@ -268,6 +337,11 @@ private enum size_t INVALID_ID = cast(size_t)-1;
|
||||
context.text_position.row = 1u;
|
||||
context.text_position.col = 1u;
|
||||
context.mode = <%= @lexer.mode_id("default") %>;
|
||||
<% if @grammar.tree %>
|
||||
|
||||
/* Reserve node ID 0 as the null tree node. */
|
||||
context.<%= @grammar.prefix %>tree_nodes = new <%= @grammar.prefix %>node_data_t[](1);
|
||||
<% end %>
|
||||
|
||||
return context;
|
||||
}
|
||||
@@ -280,6 +354,16 @@ private enum size_t INVALID_ID = cast(size_t)-1;
|
||||
*/
|
||||
void <%= @grammar.prefix %>context_delete(<%= @grammar.prefix %>context_t * context)
|
||||
{
|
||||
<% if @grammar.tree && @grammar.free_token_node != "" %>
|
||||
foreach (ref node; context.<%= @grammar.prefix %>tree_nodes)
|
||||
{
|
||||
if (node.is_token)
|
||||
{
|
||||
<%= @grammar.prefix %>node_data_t * token_tree_node = &node;
|
||||
<%= expand_code(@grammar.free_token_node, false, nil, nil) %>
|
||||
}
|
||||
}
|
||||
<% end %>
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
@@ -888,8 +972,8 @@ private struct state_value_t
|
||||
size_t state_id;
|
||||
|
||||
<% if @grammar.tree %>
|
||||
/** Tree node. */
|
||||
void * tree_node;
|
||||
/** Tree node ID. */
|
||||
<%= @grammar.prefix %>node_id_t node_id;
|
||||
<% else %>
|
||||
<%= @grammar.prefix %>position_t position;
|
||||
<%= @grammar.prefix %>position_t end_position;
|
||||
@@ -1007,7 +1091,7 @@ private <%= @grammar.prefix %>position_t get_rule_position(state_value_t[] state
|
||||
* @retval P_USER_TERMINATED
|
||||
* User requested to terminate parsing.
|
||||
*/
|
||||
private size_t parser_user_code(<%= @grammar.tree ? "void" : "#{@grammar.prefix}value_t" %> * _pvalue, uint rule, state_value_t[] statevalues, uint n_states, <%= @grammar.prefix %>context_t * context)
|
||||
private size_t parser_user_code(<%= @grammar.tree ? "#{@grammar.prefix}node_id_t _node_id" : "#{@grammar.prefix}value_t * _pvalue" %>, uint rule, state_value_t[] statevalues, uint n_states, <%= @grammar.prefix %>context_t * context)
|
||||
{
|
||||
switch (rule)
|
||||
{
|
||||
@@ -1112,7 +1196,7 @@ private size_t parse_from(<%= @grammar.prefix %>context_t * context, size_t star
|
||||
size_t reduced_rule_set = INVALID_ID;
|
||||
size_t last_shifted_rule_set_id = INVALID_ID;
|
||||
<% if @grammar.tree %>
|
||||
void * reduced_parser_node;
|
||||
<%= @grammar.prefix %>node_id_t reduced_parser_node;
|
||||
<% else %>
|
||||
<%= @grammar.prefix %>position_t reduced_position;
|
||||
<%= @grammar.prefix %>position_t reduced_end_position;
|
||||
@@ -1153,7 +1237,7 @@ private size_t parse_from(<%= @grammar.prefix %>context_t * context, size_t star
|
||||
{
|
||||
/* Successful parse. */
|
||||
<% if @grammar.tree %>
|
||||
context.parse_result = statevalues[$-1].tree_node;
|
||||
context.parse_result = statevalues[$-1].node_id;
|
||||
<% else %>
|
||||
context.parse_result = statevalues[$-1].pvalue;
|
||||
<% end %>
|
||||
@@ -1179,7 +1263,7 @@ private size_t parse_from(<%= @grammar.prefix %>context_t * context, size_t star
|
||||
context.input_index -= token_info.length;
|
||||
context.text_position = token_info.position;
|
||||
<% if @grammar.tree %>
|
||||
context.parse_result = statevalues[$-1].tree_node;
|
||||
context.parse_result = statevalues[$-1].node_id;
|
||||
<% else %>
|
||||
context.parse_result = statevalues[$-1].pvalue;
|
||||
<% end %>
|
||||
@@ -1199,9 +1283,17 @@ private size_t parse_from(<%= @grammar.prefix %>context_t * context, size_t star
|
||||
{
|
||||
/* We shifted a token, mark it consumed. */
|
||||
<% if @grammar.tree %>
|
||||
<%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %> * token_tree_node = new <%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %>(token_info.position, token_info.end_position, 0u, true, token, token_info.pvalue);
|
||||
<%= @grammar.prefix %>node_id_t token_node_id = cast(<%= @grammar.prefix %>node_id_t)context.<%= @grammar.prefix %>tree_nodes.length;
|
||||
context.<%= @grammar.prefix %>tree_nodes ~= <%= @grammar.prefix %>node_data_t.init;
|
||||
<%= @grammar.prefix %>node_data_t * token_tree_node = &context.<%= @grammar.prefix %>tree_nodes[token_node_id];
|
||||
token_tree_node.position = token_info.position;
|
||||
token_tree_node.end_position = token_info.end_position;
|
||||
token_tree_node.n_fields = 0u;
|
||||
token_tree_node.is_token = true;
|
||||
token_tree_node.token = token;
|
||||
token_tree_node.pvalue = token_info.pvalue;
|
||||
<%= expand_code(@grammar.on_token_node, false, nil, nil) %>
|
||||
statevalues[$-1].tree_node = token_tree_node;
|
||||
statevalues[$-1].node_id = token_node_id;
|
||||
<% else %>
|
||||
statevalues[$-1].position = token_info.position;
|
||||
statevalues[$-1].end_position = token_info.end_position;
|
||||
@@ -1213,7 +1305,7 @@ private size_t parse_from(<%= @grammar.prefix %>context_t * context, size_t star
|
||||
{
|
||||
/* We shifted a RuleSet. */
|
||||
<% if @grammar.tree %>
|
||||
statevalues[$-1].tree_node = reduced_parser_node;
|
||||
statevalues[$-1].node_id = reduced_parser_node;
|
||||
<% else %>
|
||||
statevalues[$-1].pvalue = reduced_parser_value;
|
||||
statevalues[$-1].position = reduced_position;
|
||||
@@ -1242,55 +1334,56 @@ private size_t parse_from(<%= @grammar.prefix %>context_t * context, size_t star
|
||||
<% if @grammar.tree %>
|
||||
if (parser_reduce_table[reduce_index].propagate_optional_target)
|
||||
{
|
||||
reduced_parser_node = statevalues[$ - 1].tree_node;
|
||||
reduced_parser_node = statevalues[$ - 1].node_id;
|
||||
}
|
||||
else if (parser_reduce_table[reduce_index].n_states > 0)
|
||||
{
|
||||
size_t n_fields = parser_reduce_table[reduce_index].rule_set_node_field_array_size;
|
||||
size_t node_size = TreeNode.sizeof + n_fields * (void *).sizeof;
|
||||
TreeNode * node = cast(TreeNode *)malloc(node_size);
|
||||
GC.addRange(node, node_size);
|
||||
node.position = <%= @grammar.prefix %>position_t.INVALID;
|
||||
node.end_position = <%= @grammar.prefix %>position_t.INVALID;
|
||||
node.n_fields = cast(ushort)n_fields;
|
||||
node.is_token = false;
|
||||
foreach (i; 0..n_fields)
|
||||
{
|
||||
node.fields[i] = null;
|
||||
}
|
||||
ushort n_fields = parser_reduce_table[reduce_index].rule_set_node_field_array_size;
|
||||
/* Reserve child slots. New slots are zero-initialized
|
||||
* (null node ID) so absent optional children remain null. */
|
||||
<%= @grammar.prefix %>node_id_t child_offset = cast(<%= @grammar.prefix %>node_id_t)context.<%= @grammar.prefix %>tree_children.length;
|
||||
context.<%= @grammar.prefix %>tree_children.length += n_fields;
|
||||
if (parser_reduce_table[reduce_index].rule_set_node_field_index_map is null)
|
||||
{
|
||||
foreach (i; 0..parser_reduce_table[reduce_index].n_states)
|
||||
{
|
||||
node.fields[i] = statevalues[$ - parser_reduce_table[reduce_index].n_states + i].tree_node;
|
||||
context.<%= @grammar.prefix %>tree_children[child_offset + i] = statevalues[$ - parser_reduce_table[reduce_index].n_states + i].node_id;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (i; 0..parser_reduce_table[reduce_index].n_states)
|
||||
{
|
||||
node.fields[parser_reduce_table[reduce_index].rule_set_node_field_index_map[i]] = statevalues[$ - parser_reduce_table[reduce_index].n_states + i].tree_node;
|
||||
context.<%= @grammar.prefix %>tree_children[child_offset + parser_reduce_table[reduce_index].rule_set_node_field_index_map[i]] = statevalues[$ - parser_reduce_table[reduce_index].n_states + i].node_id;
|
||||
}
|
||||
}
|
||||
<%= @grammar.prefix %>node_id_t node_id = cast(<%= @grammar.prefix %>node_id_t)context.<%= @grammar.prefix %>tree_nodes.length;
|
||||
context.<%= @grammar.prefix %>tree_nodes ~= <%= @grammar.prefix %>node_data_t.init;
|
||||
<%= @grammar.prefix %>node_data_t * node = &context.<%= @grammar.prefix %>tree_nodes[node_id];
|
||||
node.position = <%= @grammar.prefix %>position_t.INVALID;
|
||||
node.end_position = <%= @grammar.prefix %>position_t.INVALID;
|
||||
node.child_offset = child_offset;
|
||||
node.n_fields = n_fields;
|
||||
node.is_token = false;
|
||||
bool position_found = false;
|
||||
foreach (i; 0..n_fields)
|
||||
{
|
||||
TreeNode * child = cast(TreeNode *)node.fields[i];
|
||||
if (child && child.position.valid)
|
||||
<%= @grammar.prefix %>node_id_t child_id = context.<%= @grammar.prefix %>tree_children[child_offset + i];
|
||||
if (child_id != 0u && context.<%= @grammar.prefix %>tree_nodes[child_id].position.valid)
|
||||
{
|
||||
if (!position_found)
|
||||
{
|
||||
node.position = child.position;
|
||||
node.position = context.<%= @grammar.prefix %>tree_nodes[child_id].position;
|
||||
position_found = true;
|
||||
}
|
||||
node.end_position = child.end_position;
|
||||
node.end_position = context.<%= @grammar.prefix %>tree_nodes[child_id].end_position;
|
||||
}
|
||||
}
|
||||
reduced_parser_node = node;
|
||||
reduced_parser_node = node_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
reduced_parser_node = null;
|
||||
reduced_parser_node = 0u;
|
||||
}
|
||||
<% if @grammar.parser_user_code_used? %>
|
||||
if (parser_user_code(reduced_parser_node, parser_reduce_table[reduce_index].rule, statevalues, parser_reduce_table[reduce_index].n_states, context) == P_USER_TERMINATED)
|
||||
@@ -1360,14 +1453,14 @@ public size_t <%= @grammar.prefix %>parse_inner_<%= start_rule %>(<%= @grammar.p
|
||||
* @return Parse result value.
|
||||
*/
|
||||
<% if @grammar.tree %>
|
||||
public <%= @grammar.tree_prefix %><%= @grammar.start_rules[0] %><%= @grammar.tree_suffix %> * <%= @grammar.prefix %>result(<%= @grammar.prefix %>context_t * context)
|
||||
public <%= @grammar.tree_prefix %><%= @grammar.start_rules[0] %><%= @grammar.tree_suffix %> <%= @grammar.prefix %>result(<%= @grammar.prefix %>context_t * context)
|
||||
{
|
||||
return cast(<%= @grammar.tree_prefix %><%= @grammar.start_rules[0] %><%= @grammar.tree_suffix %> *)context.parse_result;
|
||||
return <%= @grammar.tree_prefix %><%= @grammar.start_rules[0] %><%= @grammar.tree_suffix %>(context, context.parse_result);
|
||||
}
|
||||
<% @grammar.start_rules.each_with_index do |start_rule, i| %>
|
||||
public <%= @grammar.tree_prefix %><%= start_rule %><%= @grammar.tree_suffix %> * <%= @grammar.prefix %>result_<%= start_rule %>(<%= @grammar.prefix %>context_t * context)
|
||||
public <%= @grammar.tree_prefix %><%= start_rule %><%= @grammar.tree_suffix %> <%= @grammar.prefix %>result_<%= start_rule %>(<%= @grammar.prefix %>context_t * context)
|
||||
{
|
||||
return cast(<%= @grammar.tree_prefix %><%= start_rule %><%= @grammar.tree_suffix %> *)context.parse_result;
|
||||
return <%= @grammar.tree_prefix %><%= start_rule %><%= @grammar.tree_suffix %>(context, context.parse_result);
|
||||
}
|
||||
<% end %>
|
||||
<% else %>
|
||||
@@ -1383,34 +1476,6 @@ public <%= start_rule_type(i)[1] %> <%= @grammar.prefix %>result_<%= start_rule
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% if @grammar.tree %>
|
||||
private void tree_delete(TreeNode * node)
|
||||
{
|
||||
if (!node.is_token)
|
||||
{
|
||||
for (size_t i = 0u; i < node.n_fields; i++)
|
||||
{
|
||||
if (node.fields[i])
|
||||
{
|
||||
tree_delete(cast(TreeNode *)node.fields[i]);
|
||||
}
|
||||
}
|
||||
GC.removeRange(node);
|
||||
free(node);
|
||||
}
|
||||
}
|
||||
|
||||
void <%= @grammar.prefix %>tree_delete(<%= @grammar.tree_prefix %><%= @grammar.start_rules[0] %><%= @grammar.tree_suffix %> * tree)
|
||||
{
|
||||
tree_delete(cast(TreeNode *)tree);
|
||||
}
|
||||
<% @grammar.start_rules.each_with_index do |start_rule, i| %>
|
||||
void <%= @grammar.prefix %>tree_delete_<%= start_rule %>(<%= @grammar.tree_prefix %><%= start_rule %><%= @grammar.tree_suffix %> * tree)
|
||||
{
|
||||
tree_delete(cast(TreeNode *)tree);
|
||||
}
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
/**
|
||||
* Get the current text input position.
|
||||
|
||||
+44
-44
@@ -8,6 +8,9 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
<% if @cpp %>
|
||||
#include <vector>
|
||||
<% end %>
|
||||
|
||||
/**************************************************************************
|
||||
* Public types
|
||||
@@ -88,47 +91,29 @@ static inline <%= typestring %> <%= @grammar.prefix %>value_get<%= name == "defa
|
||||
<% end %>
|
||||
|
||||
<% if @grammar.tree %>
|
||||
/** Tree node types. @{ */
|
||||
typedef struct <%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %>
|
||||
/** Tree node ID type (index into the context node arena). ID 0 is null. */
|
||||
typedef uint32_t <%= @grammar.prefix %>node_id_t;
|
||||
|
||||
/**
|
||||
* Tree node record.
|
||||
*
|
||||
* All tree nodes are stored contiguously in the context node arena. Child
|
||||
* links are stored in a shared children array: a node's children
|
||||
* occupy children[child_offset .. child_offset + n_fields]. Token payload
|
||||
* fields (token, pvalue, and any user fields) are only meaningful when
|
||||
* is_token is nonzero.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
<% # TreeNode fields must be present in the same order here. # %>
|
||||
<%= @grammar.prefix %>position_t position;
|
||||
<%= @grammar.prefix %>position_t end_position;
|
||||
<%= @grammar.prefix %>node_id_t child_offset;
|
||||
uint16_t n_fields;
|
||||
uint8_t is_token;
|
||||
<%= @grammar.token_user_fields %>
|
||||
<%= @grammar.prefix %>token_t token;
|
||||
<%= @grammar.prefix %>value_t pvalue;
|
||||
} <%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %>;
|
||||
|
||||
<% @parser.rule_sets.each do |name, rule_set| %>
|
||||
<% next if name.start_with?("$") %>
|
||||
<% next if rule_set.optional? %>
|
||||
struct <%= @grammar.tree_prefix %><%= name %><%= @grammar.tree_suffix %>;
|
||||
<% end %>
|
||||
|
||||
<% @parser.rule_sets.each do |name, rule_set| %>
|
||||
<% next if name.start_with?("$") %>
|
||||
<% next if rule_set.optional? %>
|
||||
typedef struct <%= @grammar.tree_prefix %><%= name %><%= @grammar.tree_suffix %>
|
||||
{
|
||||
<% # TreeNode fields must be present in the same order here. # %>
|
||||
<%= @grammar.prefix %>position_t position;
|
||||
<%= @grammar.prefix %>position_t end_position;
|
||||
uint16_t n_fields;
|
||||
uint8_t is_token;
|
||||
<% rule_set.tree_fields.each do |fields| %>
|
||||
union
|
||||
{
|
||||
<% fields.each do |field_name, type| %>
|
||||
struct <%= type %> * <%= field_name %>;
|
||||
<% end %>
|
||||
};
|
||||
<% end %>
|
||||
} <%= @grammar.tree_prefix %><%= name %><%= @grammar.tree_suffix %>;
|
||||
|
||||
<% end %>
|
||||
/** @} */
|
||||
<%= @grammar.token_user_fields %>
|
||||
} <%= @grammar.prefix %>node_data_t;
|
||||
<% end %>
|
||||
|
||||
/** Lexed token information. */
|
||||
@@ -179,7 +164,25 @@ typedef struct
|
||||
|
||||
/** Parse result value. */
|
||||
<% if @grammar.tree %>
|
||||
void * parse_result;
|
||||
<%= @grammar.prefix %>node_id_t parse_result;
|
||||
|
||||
<% if @cpp %>
|
||||
/** Tree node arena. Node ID 0 is reserved as the null node. */
|
||||
std::vector<<%= @grammar.prefix %>node_data_t> <%= @grammar.prefix %>tree_nodes;
|
||||
|
||||
/** Shared tree child links. */
|
||||
std::vector<<%= @grammar.prefix %>node_id_t> <%= @grammar.prefix %>tree_children;
|
||||
<% else %>
|
||||
/** Tree node arena. Node ID 0 is reserved as the null node. */
|
||||
<%= @grammar.prefix %>node_data_t * <%= @grammar.prefix %>tree_nodes;
|
||||
size_t <%= @grammar.prefix %>tree_nodes_length;
|
||||
size_t <%= @grammar.prefix %>tree_nodes_capacity;
|
||||
|
||||
/** Shared tree child links. */
|
||||
<%= @grammar.prefix %>node_id_t * <%= @grammar.prefix %>tree_children;
|
||||
size_t <%= @grammar.prefix %>tree_children_length;
|
||||
size_t <%= @grammar.prefix %>tree_children_capacity;
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= @grammar.prefix %>value_t parse_result;
|
||||
<% end %>
|
||||
@@ -193,6 +196,10 @@ typedef struct
|
||||
<%= @grammar.context_user_fields %>
|
||||
} <%= @grammar.prefix %>context_t;
|
||||
|
||||
<% if @grammar.tree %>
|
||||
<%= c_tree_types_header %>
|
||||
<% end %>
|
||||
|
||||
/**************************************************************************
|
||||
* Public data
|
||||
*************************************************************************/
|
||||
@@ -217,9 +224,9 @@ size_t <%= @grammar.prefix %>parse_inner_<%= start_rule %>(<%= @grammar.prefix %
|
||||
<% end %>
|
||||
|
||||
<% if @grammar.tree %>
|
||||
<%= @grammar.tree_prefix %><%= @grammar.start_rules[0] %><%= @grammar.tree_suffix %> * <%= @grammar.prefix %>result(<%= @grammar.prefix %>context_t * context);
|
||||
<%= h_type(@grammar.start_rules[0]) %> <%= @grammar.prefix %>result(<%= @grammar.prefix %>context_t * context);
|
||||
<% @grammar.start_rules.each_with_index do |start_rule, i| %>
|
||||
<%= @grammar.tree_prefix %><%= start_rule %><%= @grammar.tree_suffix %> * <%= @grammar.prefix %>result_<%= start_rule %>(<%= @grammar.prefix %>context_t * context);
|
||||
<%= h_type(start_rule) %> <%= @grammar.prefix %>result_<%= start_rule %>(<%= @grammar.prefix %>context_t * context);
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= start_rule_type[1] %> <%= @grammar.prefix %>result(<%= @grammar.prefix %>context_t * context);
|
||||
@@ -228,13 +235,6 @@ size_t <%= @grammar.prefix %>parse_inner_<%= start_rule %>(<%= @grammar.prefix %
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% if @grammar.tree %>
|
||||
void <%= @grammar.prefix %>tree_delete(<%= @grammar.tree_prefix %><%= @grammar.start_rules[0] %><%= @grammar.tree_suffix %> * tree);
|
||||
<% @grammar.start_rules.each_with_index do |start_rule, i| %>
|
||||
void <%= @grammar.prefix %>tree_delete_<%= start_rule %>(<%= @grammar.tree_prefix %><%= start_rule %><%= @grammar.tree_suffix %> * tree);
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<%= @grammar.prefix %>position_t <%= @grammar.prefix %>position(<%= @grammar.prefix %>context_t * context);
|
||||
|
||||
void <%= @grammar.prefix %>set_position(<%= @grammar.prefix %>context_t * context, <%= @grammar.prefix %>position_t position);
|
||||
|
||||
Reference in new issue
Block a user