Skip to content

Commit

Permalink
Add (Rule)Node::reconstruct that recreates the source code
Browse files Browse the repository at this point in the history
  • Loading branch information
Xanewok committed Nov 20, 2023
1 parent 639547b commit db14452
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 2 deletions.
34 changes: 34 additions & 0 deletions crates/codegen/parser/runtime/src/cst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,42 @@ impl Node {
Cursor::new(self.clone(), text_offset)
}

/// Reconstructs the original source code from the parse tree.
pub fn reconstruct(self) -> String {
match self {
Self::Rule(rule) => rule.reconstruct(),
Self::Token(token) => token.text.clone(),
}
}

pub fn as_rule(&self) -> Option<&Rc<RuleNode>> {
match self {
Self::Rule(node) => Some(node),
_ => None,
}
}

pub fn into_rule(self) -> Option<Rc<RuleNode>> {
match self {
Self::Rule(node) => Some(node),
_ => None,
}
}

pub fn as_token(&self) -> Option<&Rc<TokenNode>> {
match self {
Self::Token(node) => Some(node),
_ => None,
}
}

pub fn into_token(self) -> Option<Rc<TokenNode>> {
match self {
Self::Token(node) => Some(node),
_ => None,
}
}

pub fn as_token_with_kind(&self, kinds: &[TokenKind]) -> Option<&Rc<TokenNode>> {
self.as_token_matching(|token| kinds.contains(&token.kind))
}
Expand Down Expand Up @@ -111,4 +133,16 @@ impl RuleNode {
pub fn cursor_with_offset(self: Rc<Self>, text_offset: TextIndex) -> Cursor {
Cursor::new(Node::Rule(self), text_offset)
}

/// Reconstructs the original source code from the parse tree.
pub fn reconstruct(self: Rc<Self>) -> String {
let acc = String::with_capacity(self.text_len.utf8);

self.cursor_with_offset(TextIndex::ZERO)
.filter_map(Node::into_token)
.fold(acc, |mut acc, token| {
acc.push_str(&token.text);
acc
})
}
}
9 changes: 9 additions & 0 deletions crates/codegen/parser/runtime/src/text_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ pub struct TextIndex {
pub char: usize,
}

impl TextIndex {
/// Shorthand for `TextIndex { utf8: 0, utf16: 0, char: 0 }`.
pub const ZERO: TextIndex = TextIndex {
utf8: 0,
utf16: 0,
char: 0,
};
}

impl PartialOrd for TextIndex {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.utf8.partial_cmp(&other.utf8)
Expand Down
34 changes: 34 additions & 0 deletions 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.

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

Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ fn simple_contract() -> Result<()> {

let parse_tree = parse_output.tree();

let children = if let Node::Rule(rule) = &parse_tree {
let rule = if let Node::Rule(rule) = parse_tree {
assert_eq!(rule.kind, RuleKind::ContractDefinition);
&rule.children
rule
} else {
panic!("Unexpected parse_tree");
};
let children = &rule.children;

assert_eq!(children.len(), 6);

Expand All @@ -30,5 +31,7 @@ fn simple_contract() -> Result<()> {
assert!(matches!(&children[4], Node::Token(token) if token.kind == TokenKind::OpenBrace));
assert!(matches!(&children[5], Node::Token(token) if token.kind == TokenKind::CloseBrace));

assert_eq!(rule.reconstruct(), "contract Foo {}");

return Ok(());
}
34 changes: 34 additions & 0 deletions crates/solidity/outputs/npm/crate/src/generated/cst.rs

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

9 changes: 9 additions & 0 deletions crates/solidity/outputs/npm/crate/src/generated/text_index.rs

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

0 comments on commit db14452

Please sign in to comment.