mirror of
https://github.com/tree-sitter/tree-sitter.git
synced 2026-09-10 07:26:23 -04:00
perf(generate): build Seq and Repeat child ranges without temporaries
`try_seq` reserves a `Seq`'s child range up front and fills slots as recursion produces each member. The `Repeat` arm builds `Choice(repeat(x), blank)` directly, skipping the `choice` helper. Slightly faster and less memory used.
This commit is contained in:
parent
efa0dd9a36
commit
03592e8288
|
|
@ -402,13 +402,9 @@ impl RulePool {
|
|||
.collect::<ParseGrammarResult<Vec<_>>>()?;
|
||||
Ok(self.choice(&members))
|
||||
}
|
||||
RuleJSON::SEQ { members } => {
|
||||
let members = members
|
||||
.into_iter()
|
||||
.map(|m| self.parse_rule(m, is_token, diagnostics))
|
||||
.collect::<ParseGrammarResult<Vec<_>>>()?;
|
||||
Ok(self.seq(&members))
|
||||
}
|
||||
RuleJSON::SEQ { members } => self.try_seq(members.into_iter(), |pool, m| {
|
||||
pool.parse_rule(m, is_token, diagnostics)
|
||||
}),
|
||||
RuleJSON::FIELD { name, content } => {
|
||||
let content = self.parse_rule(*content, is_token, diagnostics)?;
|
||||
let name = self.intern(&name);
|
||||
|
|
@ -418,7 +414,10 @@ impl RulePool {
|
|||
let content = self.parse_rule(*content, is_token, diagnostics)?;
|
||||
let repeat = self.repeat(content);
|
||||
let blank = self.blank();
|
||||
Ok(self.choice(&[repeat, blank]))
|
||||
// Neither element is a `Choice` or equal to one another, so we
|
||||
// can skip `self.choice`'s flattening loop.
|
||||
let range = self.push_children(&[repeat, blank]);
|
||||
Ok(self.push_node(Rule::Choice(range)))
|
||||
}
|
||||
RuleJSON::REPEAT1 { content } => {
|
||||
let content = self.parse_rule(*content, is_token, diagnostics)?;
|
||||
|
|
|
|||
|
|
@ -304,13 +304,34 @@ impl RulePool {
|
|||
self.push_node(Rule::Eof)
|
||||
}
|
||||
|
||||
#[cfg_attr(not(test), expect(dead_code))]
|
||||
pub fn seq(&mut self, ids: &[RuleId]) -> RuleId {
|
||||
let range = self.push_children(ids);
|
||||
self.push_node(Rule::Seq(range))
|
||||
}
|
||||
|
||||
pub fn try_seq<T, E>(
|
||||
&mut self,
|
||||
items: impl ExactSizeIterator<Item = T>,
|
||||
mut f: impl FnMut(&mut Self, T) -> Result<RuleId, E>,
|
||||
) -> Result<RuleId, E> {
|
||||
let len = items.len();
|
||||
let start = self.children.len();
|
||||
self.children.resize(start + len, RuleId(0));
|
||||
for (i, item) in items.enumerate() {
|
||||
let id = f(self, item)?;
|
||||
self.children[start + i] = id;
|
||||
}
|
||||
|
||||
let range = RuleIdRange {
|
||||
start: start as u32,
|
||||
len: len as u32,
|
||||
};
|
||||
Ok(self.push_node(Rule::Seq(range)))
|
||||
}
|
||||
|
||||
/// Flatten nested choices and de-dup structurally, keeping a `Choice` node
|
||||
/// event for a single element
|
||||
/// even for a single element
|
||||
pub fn choice(&mut self, ids: &[RuleId]) -> RuleId {
|
||||
let mut elements: Vec<RuleId> = Vec::with_capacity(ids.len());
|
||||
let mut stack: Vec<RuleId> = Vec::with_capacity(ids.len());
|
||||
|
|
|
|||
Loading…
Reference in a new issue