pub fn try_run(args: &mut noargs::RawArgs) -> noargs::Result<bool> {
if !noargs::cmd("parse").take(args).is_present() {
return Ok(false);
}
let path: std::path::PathBuf = noargs::arg("ERL_FILE_PATH")
.example("/path/to/input.erl")
.take(args)
.then(|o| o.value().parse())?;
if args.metadata().help_mode {
return Ok(true);
}
let text = std::fs::read_to_string(&path)?;
let tokens = crate::token::tokenize(&text)?;
let mut parser = crate::parse::Parser::new(&text, tokens);
parser.parse_module()?;
let view = crate::item::ItemView::new(&parser.text, &parser.items, 0);
let json_view = to_json(view, &text);
let output = nojson::json(|f| {
f.set_indent_size(2);
f.set_spacing(true);
f.value(&json_view.0)
});
println!("{}", output);
Ok(true)
}
pub fn to_json<'a>(
view: crate::item::ItemView<'a>,
text: &'a str,
) -> nojson::Json<ItemViewJson<'a>> {
let item_json = ItemViewJson {
kind: format!("{:?}", view.kind()),
text: view.text(),
children: view
.children()
.map(|child| to_json(child, text).0)
.collect(),
};
nojson::Json(item_json)
}
#[derive(Debug)]
pub struct ItemViewJson<'a> {
pub kind: String,
pub text: &'a str,
pub children: Vec<ItemViewJson<'a>>,
}
impl nojson::DisplayJson for ItemViewJson<'_> {
fn fmt(&self, f: &mut nojson::JsonFormatter<'_, '_>) -> std::fmt::Result {
f.object(|f| {
f.member("kind", &self.kind)?;
if self.children.is_empty() {
if !self.text.is_empty() {
f.member("text", self.text)?;
}
} else {
f.member(
"children",
nojson::array(|f| {
for child in &self.children {
f.element(child)?;
}
Ok(())
}),
)?;
}
Ok(())
})
}
}