Skip to content

Commit

Permalink
Don't store node names as cursor state
Browse files Browse the repository at this point in the history
  • Loading branch information
Xanewok committed Dec 14, 2023
1 parent 0ccf674 commit 1f4e083
Show file tree
Hide file tree
Showing 21 changed files with 132 additions and 104 deletions.
2 changes: 1 addition & 1 deletion crates/codegen/parser/runtime/src/cst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ impl RuleNode {
let acc = String::with_capacity(self.text_len.utf8);

self.cursor_with_offset(TextIndex::ZERO)
.filter_map(|(_, node)| node.into_token())
.filter_map(|node| node.into_token())
.fold(acc, |mut acc, token| {
acc.push_str(&token.text);
acc
Expand Down
61 changes: 35 additions & 26 deletions crates/codegen/parser/runtime/src/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@
use std::rc::Rc;

use crate::cst::{NamedNode, Node, RuleNode};
use crate::cst::{Node, RuleNode};
use crate::kinds::{RuleKind, TokenKind};
use crate::text_index::{TextIndex, TextRange};

/// A [`PathNode`] that points to a [`RuleNode`].
#[derive(Clone, Debug, PartialEq, Eq)]
struct PathRuleNode {
rule_node: (String, Rc<RuleNode>),
rule_node: Rc<RuleNode>,
child_number: usize,
text_offset: TextIndex,
}

impl PathRuleNode {
fn into_path_node(self) -> PathNode {
PathNode {
node: (self.rule_node.0, Node::Rule(self.rule_node.1)),
node: Node::Rule(self.rule_node),
child_number: self.child_number,
text_offset: self.text_offset,
}
Expand All @@ -28,7 +28,7 @@ impl PathRuleNode {
#[derive(Clone, Debug, PartialEq, Eq)]
struct PathNode {
/// The node the cursor is currently pointing to.
node: NamedNode,
node: Node,
/// The index of the current child node in the parent's children.
// Required to go to the next/previous sibling.
child_number: usize,
Expand All @@ -39,14 +39,14 @@ struct PathNode {
impl PathNode {
fn text_range(&self) -> TextRange {
let start = self.text_offset;
let end = start + self.node.1.text_len();
let end = start + self.node.text_len();
start..end
}

fn to_path_rule_node(&self) -> Option<PathRuleNode> {
if let (name, Node::Rule(rule_node)) = &self.node {
if let Node::Rule(rule_node) = &self.node {
Some(PathRuleNode {
rule_node: (name.clone(), rule_node.clone()),
rule_node: rule_node.clone(),
child_number: self.child_number,
text_offset: self.text_offset,
})
Expand All @@ -71,14 +71,15 @@ pub struct Cursor {
}

impl Iterator for Cursor {
type Item = NamedNode;
type Item = Node;

fn next(&mut self) -> Option<Self::Item> {
if self.is_completed {
None
} else {
let cur = self.node();
self.go_to_next();

Some(cur)
}
}
Expand All @@ -89,7 +90,7 @@ impl Cursor {
Self {
path: vec![],
current: PathNode {
node: (String::new(), node),
node,
child_number: 0,
text_offset,
},
Expand Down Expand Up @@ -129,10 +130,20 @@ impl Cursor {
}

/// Returns the currently pointed to [`Node`].
pub fn node(&self) -> NamedNode {
pub fn node(&self) -> Node {
self.current.node.clone()
}

pub fn node_name(&self) -> String {
if let Some(parent) = self.path.last() {
parent.rule_node.children[self.current.child_number]
.0
.clone()
} else {
String::new()
}
}

/// Returns the text offset that corresponds to the beginning of the currently pointed to node.
pub fn text_offset(&self) -> TextIndex {
self.current.text_offset
Expand All @@ -150,7 +161,7 @@ impl Cursor {

/// Returns an iterator over the current node's ancestors, starting from the cursor root node.
pub fn ancestors(&self) -> impl Iterator<Item = &Rc<RuleNode>> {
self.path.iter().map(|elem| &elem.rule_node.1)
self.path.iter().map(|elem| &elem.rule_node)
}

/// Attempts to go to current node's next one, according to the DFS pre-order traversal.
Expand Down Expand Up @@ -225,7 +236,7 @@ impl Cursor {

// If the current cursor is a node and it has children, go to first children
if let Some(parent) = self.current.to_path_rule_node() {
if let Some(child_node) = parent.rule_node.1.children.first().cloned() {
if let Some((_, child_node)) = parent.rule_node.children.first().cloned() {
self.current = PathNode {
node: child_node,
text_offset: parent.text_offset,
Expand All @@ -250,11 +261,11 @@ impl Cursor {
}

if let Some(parent) = self.current.to_path_rule_node() {
let child_number = parent.rule_node.1.children.len() - 1;
if let Some(child_node) = parent.rule_node.1.children.get(child_number).cloned() {
let child_number = parent.rule_node.children.len() - 1;
if let Some((_, child_node)) = parent.rule_node.children.get(child_number).cloned() {
// This is cheaper than summing up the length of the children
let text_offset =
parent.text_offset + parent.rule_node.1.text_len - child_node.1.text_len();
parent.text_offset + parent.rule_node.text_len - child_node.text_len();

self.path.push(parent);

Expand All @@ -280,11 +291,11 @@ impl Cursor {
}

if let Some(parent) = self.current.to_path_rule_node() {
if let Some(child_node) = parent.rule_node.1.children.get(child_number).cloned() {
if let Some((_, child_node)) = parent.rule_node.children.get(child_number).cloned() {
// Sum up the length of the children before this child
// TODO: it might sometimes be quicker to start from the end (like `go_to_last_child`)
let text_offset = parent.text_offset
+ parent.rule_node.1.children[..child_number]
+ parent.rule_node.children[..child_number]
.iter()
.map(|(_name, node)| node.text_len())
.sum();
Expand Down Expand Up @@ -313,15 +324,12 @@ impl Cursor {

if let Some(parent_path_element) = self.path.last() {
let new_child_number = self.current.child_number + 1;
if let Some(new_child) = parent_path_element
.rule_node
.1
.children
.get(new_child_number)
if let Some((_, new_child)) =
parent_path_element.rule_node.children.get(new_child_number)
{
self.current = PathNode {
node: new_child.clone(),
text_offset: self.current.text_offset + self.current.node.1.text_len(),
text_offset: self.current.text_offset + self.current.node.text_len(),
child_number: new_child_number,
};

Expand All @@ -343,11 +351,12 @@ impl Cursor {
if self.current.child_number > 0 {
if let Some(parent_path_element) = self.path.last() {
let new_child_number = self.current.child_number - 1;
let new_child = parent_path_element.rule_node.1.children[new_child_number].clone();
let (_, new_child) =
parent_path_element.rule_node.children[new_child_number].clone();

self.current = PathNode {
node: new_child,
text_offset: self.current.text_offset - self.current.node.1.text_len(),
text_offset: self.current.text_offset - self.current.node.text_len(),
child_number: new_child_number,
};
return true;
Expand Down Expand Up @@ -391,7 +400,7 @@ impl Cursor {

fn go_to_next_matching(&mut self, pred: impl Fn(&Node) -> bool) -> bool {
while self.go_to_next() {
if pred(&self.current.node.1) {
if pred(&self.current.node) {
return true;
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/codegen/parser/runtime/src/napi/napi_cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ impl Cursor {

#[napi(ts_return_type = "cst.Node", catch_unwind)]
pub fn node(&self, env: Env) -> JsObject {
self.0.node().1.to_js(&env)
self.0.node().to_js(&env)
}

#[napi(getter, ts_return_type = "text_index.TextIndex", catch_unwind)]
Expand Down
2 changes: 1 addition & 1 deletion crates/codegen/parser/runtime/src/support/choice_helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ pub fn total_not_skipped_span(result: &ParserResult) -> usize {
nodes
.iter()
.flat_map(|(_name, node)| node.cursor_with_offset(TextIndex::ZERO))
.filter_map(|(_name, node)| match node {
.filter_map(|node| match node {
cst::Node::Token(token) if token.kind != TokenKind::SKIPPED => Some(token.text.len()),
_ => None,
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ where
errors.is_empty(),
parse_tree
.cursor_with_offset(TextIndex::ZERO)
.all(|(_, n)| n.as_token_with_kind(&[TokenKind::SKIPPED]).is_none())
.all(|node| node.as_token_with_kind(&[TokenKind::SKIPPED]).is_none())
);

ParseOutput { parse_tree, errors }
Expand Down
4 changes: 2 additions & 2 deletions crates/codegen/parser/runtime/src/support/parser_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ impl Match {
pub fn is_full_recursive(&self) -> bool {
self.nodes
.iter()
.flat_map(|(_name, node)| node.cursor_with_offset(TextIndex::ZERO))
.all(|(_name, node)| node.as_token_with_kind(&[TokenKind::SKIPPED]).is_none())
.flat_map(|(_, node)| node.cursor_with_offset(TextIndex::ZERO))
.all(|node| node.as_token_with_kind(&[TokenKind::SKIPPED]).is_none())
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/solidity/outputs/cargo/crate/src/generated/cst.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 1f4e083

Please sign in to comment.