This repository was archived by the owner on Sep 9, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 162
Expand file tree
/
Copy pathparse.rs
More file actions
115 lines (106 loc) · 4.03 KB
/
parse.rs
File metadata and controls
115 lines (106 loc) · 4.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// -*- coding: utf-8 -*-
// ------------------------------------------------------------------------------------------------
// Copyright © 2021, stack-graphs authors.
// Licensed under either of Apache License, Version 2.0, or MIT license, at your option.
// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details.
// ------------------------------------------------------------------------------------------------
use anyhow::anyhow;
use anyhow::Context as _;
use clap::Args;
use clap::ValueHint;
use std::path::Path;
use std::path::PathBuf;
use tree_sitter::Parser;
use tree_sitter_graph::parse_error::ParseError;
use crate::cli::util::path_exists;
use crate::loader::FileReader;
use crate::loader::Loader;
use crate::LoadError;
/// Parse file
#[derive(Args)]
pub struct ParseArgs {
/// Input file path.
#[clap(value_name = "FILE_PATH", required = true, value_hint = ValueHint::AnyPath, parse(from_os_str), validator_os = path_exists)]
pub file_path: PathBuf,
}
impl ParseArgs {
pub fn run(&self, loader: &mut Loader) -> anyhow::Result<()> {
self.parse_file(&self.file_path, loader)
.with_context(|| format!("Error parsing file {}", self.file_path.display()))?;
Ok(())
}
fn parse_file(&self, file_path: &Path, loader: &mut Loader) -> anyhow::Result<()> {
let mut file_reader = FileReader::new();
let lang = match loader.load_tree_sitter_language_for_file(file_path, &mut file_reader)? {
Some(sgl) => sgl,
None => return Err(anyhow!("No stack graph language found")),
};
let source = file_reader.get(file_path)?;
let mut parser = Parser::new();
parser.set_language(lang)?;
let tree = parser.parse(source, None).ok_or(LoadError::ParseError)?;
let parse_errors = ParseError::into_all(tree);
if parse_errors.errors().len() > 0 {
return Err(anyhow!(LoadError::ParseErrors(parse_errors)));
}
let tree = parse_errors.into_tree();
self.print_tree(tree);
Ok(())
}
// From: https://github.com/tree-sitter/tree-sitter/blob/master/cli/src/parse.rs
fn print_tree(&self, tree: tree_sitter::Tree) {
let mut cursor = tree.walk();
let mut needs_newline = false;
let mut indent_level = 0;
let mut did_visit_children = false;
loop {
let node = cursor.node();
let is_named = node.is_named();
if did_visit_children {
if is_named {
print!(")");
needs_newline = true;
}
if cursor.goto_next_sibling() {
did_visit_children = false;
} else if cursor.goto_parent() {
did_visit_children = true;
indent_level -= 1;
} else {
break;
}
} else {
if is_named {
if needs_newline {
print!("\n");
}
for _ in 0..indent_level {
print!(" ");
}
let start = node.start_position();
let end = node.end_position();
if let Some(field_name) = cursor.field_name() {
print!("{}: ", field_name);
}
print!(
"({} [{}:{} - {}:{}]",
node.kind(),
start.row + 1,
start.column + 1,
end.row + 1,
end.column + 1
);
needs_newline = true;
}
if cursor.goto_first_child() {
did_visit_children = false;
indent_level += 1;
} else {
did_visit_children = true;
}
}
}
cursor.reset(tree.root_node());
println!("");
}
}