2019-01-07 17:57:36 -08:00
|
|
|
use super::error::Result;
|
2019-01-08 21:03:51 -08:00
|
|
|
use super::util;
|
2019-01-07 17:57:36 -08:00
|
|
|
use std::fs;
|
|
|
|
|
use std::io::{self, Write};
|
2019-01-08 21:03:51 -08:00
|
|
|
use std::path::Path;
|
|
|
|
|
use tree_sitter::{Language, LogType, Parser};
|
2019-01-07 17:57:36 -08:00
|
|
|
|
2019-01-08 21:03:51 -08:00
|
|
|
pub fn parse_file_at_path(
|
|
|
|
|
language: Language,
|
|
|
|
|
path: &Path,
|
|
|
|
|
debug: bool,
|
|
|
|
|
debug_graph: bool,
|
|
|
|
|
) -> Result<()> {
|
2019-01-07 17:57:36 -08:00
|
|
|
let mut parser = Parser::new();
|
|
|
|
|
parser.set_language(language)?;
|
|
|
|
|
let source_code = fs::read_to_string(path)?;
|
2019-01-08 21:03:51 -08:00
|
|
|
|
|
|
|
|
let mut log_session = None;
|
|
|
|
|
|
|
|
|
|
if debug_graph {
|
|
|
|
|
log_session = Some(util::start_logging_graphs(&mut parser, "log.html")?);
|
|
|
|
|
} else if debug {
|
|
|
|
|
parser.set_logger(Some(Box::new(|log_type, message| {
|
|
|
|
|
if log_type == LogType::Lex {
|
|
|
|
|
io::stderr().write(b" ").unwrap();
|
|
|
|
|
}
|
|
|
|
|
write!(&mut io::stderr(), "{}\n", message).unwrap();
|
|
|
|
|
})));
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-07 17:57:36 -08:00
|
|
|
let tree = parser
|
|
|
|
|
.parse_str(&source_code, None)
|
|
|
|
|
.expect("Incompatible language version");
|
|
|
|
|
|
2019-01-08 21:03:51 -08:00
|
|
|
if let Some(log_session) = log_session {
|
|
|
|
|
util::stop_logging_graphs(&mut parser, log_session)?;
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-07 17:57:36 -08:00
|
|
|
let stdout = io::stdout();
|
|
|
|
|
let mut stdout = stdout.lock();
|
|
|
|
|
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 {
|
|
|
|
|
stdout.write(b")")?;
|
|
|
|
|
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 {
|
|
|
|
|
stdout.write(b"\n")?;
|
|
|
|
|
}
|
|
|
|
|
for _ in 0..indent_level {
|
|
|
|
|
stdout.write(b" ")?;
|
|
|
|
|
}
|
|
|
|
|
let start = node.start_position();
|
|
|
|
|
let end = node.end_position();
|
|
|
|
|
write!(
|
|
|
|
|
&mut stdout,
|
|
|
|
|
"({} [{}, {}] - [{}, {}]",
|
|
|
|
|
node.kind(),
|
|
|
|
|
start.row,
|
|
|
|
|
start.column,
|
|
|
|
|
end.row,
|
|
|
|
|
end.column
|
|
|
|
|
)?;
|
|
|
|
|
needs_newline = true;
|
|
|
|
|
}
|
|
|
|
|
if cursor.goto_first_child() {
|
|
|
|
|
did_visit_children = false;
|
|
|
|
|
indent_level += 1;
|
|
|
|
|
} else {
|
|
|
|
|
did_visit_children = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
println!("");
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|