Compare commits
No commits in common. "f902c835c9a3aebc8822269b95e7e83fd3b5598e" and "89f1f848573d5ee8d6854a19c6f9279a5220cfb8" have entirely different histories.
f902c835c9
...
89f1f84857
@ -26,24 +26,13 @@
|
|||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
|
|
||||||
/* Result codes. */
|
/* Result codes. */
|
||||||
pub const <%= @grammar.prefix.upcase %>SUCCESS: usize = 0;
|
pub const P_SUCCESS: usize = 0;
|
||||||
pub const <%= @grammar.prefix.upcase %>DECODE_ERROR: usize = 1;
|
pub const P_DECODE_ERROR: usize = 1;
|
||||||
pub const <%= @grammar.prefix.upcase %>UNEXPECTED_INPUT: usize = 2;
|
pub const P_UNEXPECTED_INPUT: usize = 2;
|
||||||
pub const <%= @grammar.prefix.upcase %>UNEXPECTED_TOKEN: usize = 3;
|
pub const P_UNEXPECTED_TOKEN: usize = 3;
|
||||||
pub const <%= @grammar.prefix.upcase %>DROP: usize = 4;
|
pub const P_DROP: usize = 4;
|
||||||
pub const <%= @grammar.prefix.upcase %>EOF: usize = 5;
|
pub const P_EOF: usize = 5;
|
||||||
pub const <%= @grammar.prefix.upcase %>USER_TERMINATED: usize = 6;
|
pub const P_USER_TERMINATED: usize = 6;
|
||||||
<% if @grammar.prefix.upcase != "P_" %>
|
|
||||||
|
|
||||||
/* Internal result code aliases used by the generated implementation below. */
|
|
||||||
const P_SUCCESS: usize = 0;
|
|
||||||
const P_DECODE_ERROR: usize = 1;
|
|
||||||
const P_UNEXPECTED_INPUT: usize = 2;
|
|
||||||
const P_UNEXPECTED_TOKEN: usize = 3;
|
|
||||||
const P_DROP: usize = 4;
|
|
||||||
const P_EOF: usize = 5;
|
|
||||||
const P_USER_TERMINATED: usize = 6;
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
/** Token type. */
|
/** Token type. */
|
||||||
pub type <%= @grammar.prefix %>token_t = <%= get_type_for(@grammar.terminate_token_id) %>;
|
pub type <%= @grammar.prefix %>token_t = <%= get_type_for(@grammar.terminate_token_id) %>;
|
||||||
@ -120,84 +109,7 @@ pub fn <%= @grammar.prefix %>value_get<%= suffix %>(pvalue: &<%= @grammar.prefix
|
|||||||
/** Tree node ID type (index into the context node arena). ID 0 is null. */
|
/** Tree node ID type (index into the context node arena). ID 0 is null. */
|
||||||
pub type <%= @grammar.prefix %>node_id_t = u32;
|
pub type <%= @grammar.prefix %>node_id_t = u32;
|
||||||
|
|
||||||
/**
|
<%= rust_tree_types %>
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
#[derive(Clone, Default)]
|
|
||||||
pub struct <%= @grammar.prefix %>node_data_t {
|
|
||||||
pub position: <%= @grammar.prefix %>position_t,
|
|
||||||
pub end_position: <%= @grammar.prefix %>position_t,
|
|
||||||
pub child_offset: <%= @grammar.prefix %>node_id_t,
|
|
||||||
pub n_fields: u16,
|
|
||||||
pub is_token: bool,
|
|
||||||
pub token: <%= @grammar.prefix %>token_t,
|
|
||||||
pub pvalue: <%= @grammar.prefix %>value_t,
|
|
||||||
<% unless @grammar.token_user_fields.to_s.strip.empty? %>
|
|
||||||
<%= @grammar.token_user_fields %>
|
|
||||||
<% end %>
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Tree node handle types. */
|
|
||||||
|
|
||||||
/** Token tree node handle. */
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
pub struct <%= h_type("Token") %><'a> { context: &'a <%= @grammar.prefix %>context_t, id: <%= @grammar.prefix %>node_id_t }
|
|
||||||
|
|
||||||
impl<'a> <%= h_type("Token") %><'a> {
|
|
||||||
/** Return whether this handle refers to a valid (non-null) node. */
|
|
||||||
pub fn valid(&self) -> bool { self.id != 0 }
|
|
||||||
/** Return the node ID (for identity comparison). */
|
|
||||||
pub fn node_id(&self) -> <%= @grammar.prefix %>node_id_t { self.id }
|
|
||||||
/** Access the underlying node record (token, pvalue, and user fields). */
|
|
||||||
pub fn data(&self) -> &'a <%= @grammar.prefix %>node_data_t { &self.context.<%= @grammar.prefix %>tree_nodes[self.id as usize] }
|
|
||||||
/** Text position of the first code point spanned by this node. */
|
|
||||||
pub fn position(&self) -> <%= @grammar.prefix %>position_t { self.context.<%= @grammar.prefix %>tree_nodes[self.id as usize].position }
|
|
||||||
/** Text position of the last code point spanned by this node. */
|
|
||||||
pub fn end_position(&self) -> <%= @grammar.prefix %>position_t { self.context.<%= @grammar.prefix %>tree_nodes[self.id as usize].end_position }
|
|
||||||
/** Number of child fields in this node. */
|
|
||||||
pub fn n_fields(&self) -> u16 { if self.id != 0 { self.context.<%= @grammar.prefix %>tree_nodes[self.id as usize].n_fields } else { 0 } }
|
|
||||||
/** Token ID for this token node. */
|
|
||||||
pub fn token(&self) -> <%= @grammar.prefix %>token_t { self.context.<%= @grammar.prefix %>tree_nodes[self.id as usize].token }
|
|
||||||
/** Parser value associated with this token node. */
|
|
||||||
pub fn pvalue(&self) -> <%= @grammar.prefix %>value_t { self.context.<%= @grammar.prefix %>tree_nodes[self.id as usize].pvalue.clone() }
|
|
||||||
}
|
|
||||||
<% tree_node_rule_sets.each do |rule_set| %>
|
|
||||||
|
|
||||||
/** <%= rule_set.name %> tree node handle. */
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
pub struct <%= h_type(rule_set.name) %><'a> { context: &'a <%= @grammar.prefix %>context_t, id: <%= @grammar.prefix %>node_id_t }
|
|
||||||
|
|
||||||
impl<'a> <%= h_type(rule_set.name) %><'a> {
|
|
||||||
/** Return whether this handle refers to a valid (non-null) node. */
|
|
||||||
pub fn valid(&self) -> bool { self.id != 0 }
|
|
||||||
/** Return the node ID (for identity comparison). */
|
|
||||||
pub fn node_id(&self) -> <%= @grammar.prefix %>node_id_t { self.id }
|
|
||||||
/** Access the underlying node record. */
|
|
||||||
pub fn data(&self) -> &'a <%= @grammar.prefix %>node_data_t { &self.context.<%= @grammar.prefix %>tree_nodes[self.id as usize] }
|
|
||||||
/** Text position of the first code point spanned by this node. */
|
|
||||||
pub fn position(&self) -> <%= @grammar.prefix %>position_t { self.context.<%= @grammar.prefix %>tree_nodes[self.id as usize].position }
|
|
||||||
/** Text position of the last code point spanned by this node. */
|
|
||||||
pub fn end_position(&self) -> <%= @grammar.prefix %>position_t { self.context.<%= @grammar.prefix %>tree_nodes[self.id as usize].end_position }
|
|
||||||
/** Number of child fields in this node. */
|
|
||||||
pub fn n_fields(&self) -> u16 { if self.id != 0 { self.context.<%= @grammar.prefix %>tree_nodes[self.id as usize].n_fields } else { 0 } }
|
|
||||||
<% each_tree_field(rule_set) do |rt, field_name, child_type, slot| %>
|
|
||||||
|
|
||||||
/** Access the <%= field_name %> child node. */
|
|
||||||
pub fn <%= rust_ident(field_name) %>(&self) -> <%= child_type %><'a> {
|
|
||||||
if self.id == 0 {
|
|
||||||
return <%= child_type %> { context: self.context, id: 0 };
|
|
||||||
}
|
|
||||||
<%= child_type %> { context: self.context, id: self.context.<%= @grammar.prefix %>tree_children[self.context.<%= @grammar.prefix %>tree_nodes[self.id as usize].child_offset as usize + <%= slot %>] }
|
|
||||||
}
|
|
||||||
<% end %>
|
|
||||||
}
|
|
||||||
<% end %>
|
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
/** Lexed token information. */
|
/** Lexed token information. */
|
||||||
|
|||||||
@ -755,6 +755,79 @@ class Propane
|
|||||||
typestring == "void *" ? "()" : typestring
|
typestring == "void *" ? "()" : typestring
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Generate the Rust tree node record and handle types.
|
||||||
|
#
|
||||||
|
# Mirrors the C tree node record plus the C++ handle structs: each rule set
|
||||||
|
# and the Token node get a handle type ({context, id}) with accessor methods.
|
||||||
|
#
|
||||||
|
# @return [String]
|
||||||
|
# Rust tree node type definitions.
|
||||||
|
def rust_tree_types
|
||||||
|
p = @grammar.prefix
|
||||||
|
out = []
|
||||||
|
out << "/** Tree node record. */"
|
||||||
|
out << "#[derive(Clone, Default)]"
|
||||||
|
out << "pub struct #{p}node_data_t {"
|
||||||
|
out << " pub position: #{p}position_t,"
|
||||||
|
out << " pub end_position: #{p}position_t,"
|
||||||
|
out << " pub child_offset: #{p}node_id_t,"
|
||||||
|
out << " pub n_fields: u16,"
|
||||||
|
out << " pub is_token: bool,"
|
||||||
|
out << " pub token: #{p}token_t,"
|
||||||
|
out << " pub pvalue: #{p}value_t,"
|
||||||
|
unless @grammar.token_user_fields.to_s.strip.empty?
|
||||||
|
out << @grammar.token_user_fields
|
||||||
|
end
|
||||||
|
out << "}"
|
||||||
|
out << ""
|
||||||
|
out << "/** Tree node handle types. */"
|
||||||
|
tree_handle_types.each do |t|
|
||||||
|
out << "#[derive(Clone, Copy)]"
|
||||||
|
out << "pub struct #{t}<'a> { context: &'a #{p}context_t, id: #{p}node_id_t }"
|
||||||
|
end
|
||||||
|
out << ""
|
||||||
|
# Common accessors for every handle type.
|
||||||
|
tree_handle_types.each do |t|
|
||||||
|
out << "impl<'a> #{t}<'a> {"
|
||||||
|
out << " /** Return whether this handle refers to a valid (non-null) node. */"
|
||||||
|
out << " pub fn valid(&self) -> bool { self.id != 0 }"
|
||||||
|
out << " /** Return the node ID (for identity comparison). */"
|
||||||
|
out << " pub fn node_id(&self) -> #{p}node_id_t { self.id }"
|
||||||
|
out << " /** Access the underlying node record. */"
|
||||||
|
out << " pub fn data(&self) -> &'a #{p}node_data_t { &self.context.#{p}tree_nodes[self.id as usize] }"
|
||||||
|
out << " /** Text position of the first code point spanned by this node. */"
|
||||||
|
out << " pub fn position(&self) -> #{p}position_t { self.context.#{p}tree_nodes[self.id as usize].position }"
|
||||||
|
out << " /** Text position of the last code point spanned by this node. */"
|
||||||
|
out << " pub fn end_position(&self) -> #{p}position_t { self.context.#{p}tree_nodes[self.id as usize].end_position }"
|
||||||
|
out << " /** Number of child fields in this node. */"
|
||||||
|
out << " pub fn n_fields(&self) -> u16 { if self.id != 0 { self.context.#{p}tree_nodes[self.id as usize].n_fields } else { 0 } }"
|
||||||
|
if t == h_type("Token")
|
||||||
|
out << " /** Token ID for this token node. */"
|
||||||
|
out << " pub fn token(&self) -> #{p}token_t { self.context.#{p}tree_nodes[self.id as usize].token }"
|
||||||
|
out << " /** Parser value associated with this token node. */"
|
||||||
|
out << " pub fn pvalue(&self) -> #{p}value_t { self.context.#{p}tree_nodes[self.id as usize].pvalue.clone() }"
|
||||||
|
end
|
||||||
|
out << "}"
|
||||||
|
end
|
||||||
|
out << ""
|
||||||
|
# Navigation accessors for rule set handles.
|
||||||
|
tree_node_rule_sets.each do |rule_set|
|
||||||
|
rtype = h_type(rule_set.name)
|
||||||
|
out << "impl<'a> #{rtype}<'a> {"
|
||||||
|
each_tree_field(rule_set) do |rt, field_name, child_type, slot|
|
||||||
|
out << " /** Access the #{field_name} child node. */"
|
||||||
|
out << " pub fn #{rust_ident(field_name)}(&self) -> #{child_type}<'a> {"
|
||||||
|
out << " if self.id == 0 {"
|
||||||
|
out << " return #{child_type} { context: self.context, id: 0 };"
|
||||||
|
out << " }"
|
||||||
|
out << " #{child_type} { context: self.context, id: self.context.#{p}tree_children[self.context.#{p}tree_nodes[self.id as usize].child_offset as usize + #{slot}] }"
|
||||||
|
out << " }"
|
||||||
|
end
|
||||||
|
out << "}"
|
||||||
|
end
|
||||||
|
out.join("\n")
|
||||||
|
end
|
||||||
|
|
||||||
# Get the lex function to use.
|
# Get the lex function to use.
|
||||||
#
|
#
|
||||||
# @return [String]
|
# @return [String]
|
||||||
|
|||||||
@ -3,10 +3,10 @@ use testparsermyp2 as m2;
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut context1 = m1::myp1_context_new(b"a\n1");
|
let mut context1 = m1::myp1_context_new(b"a\n1");
|
||||||
assert_eq!(m1::MYP1_SUCCESS, m1::myp1_parse(&mut context1));
|
assert_eq!(m1::P_SUCCESS, m1::myp1_parse(&mut context1));
|
||||||
m1::myp1_context_delete(context1);
|
m1::myp1_context_delete(context1);
|
||||||
|
|
||||||
let mut context2 = m2::myp2_context_new(b"bcb");
|
let mut context2 = m2::myp2_context_new(b"bcb");
|
||||||
assert_eq!(m2::MYP2_SUCCESS, m2::myp2_parse(&mut context2));
|
assert_eq!(m2::P_SUCCESS, m2::myp2_parse(&mut context2));
|
||||||
m2::myp2_context_delete(context2);
|
m2::myp2_context_delete(context2);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user