Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'lib/ungrammar/ungrammar2json/src/main.rs')
-rw-r--r--lib/ungrammar/ungrammar2json/src/main.rs78
1 files changed, 78 insertions, 0 deletions
diff --git a/lib/ungrammar/ungrammar2json/src/main.rs b/lib/ungrammar/ungrammar2json/src/main.rs
new file mode 100644
index 0000000000..3b8588c086
--- /dev/null
+++ b/lib/ungrammar/ungrammar2json/src/main.rs
@@ -0,0 +1,78 @@
+#![allow(clippy::print_stderr, clippy::print_stdout)]
+use std::{
+ env,
+ io::{self, Read},
+ process,
+};
+
+use ungrammar::{Grammar, Rule};
+
+fn main() {
+ if let Err(err) = try_main() {
+ eprintln!("{}", err);
+ process::exit(101);
+ }
+}
+
+fn try_main() -> io::Result<()> {
+ if env::args().count() != 1 {
+ eprintln!("Usage: ungrammar2json < grammar.ungram > grammar.json");
+ return Ok(());
+ }
+ let grammar = read_stdin()?;
+ let grammar = grammar
+ .parse::<Grammar>()
+ .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
+
+ let mut buf = String::new();
+ grammar_to_json(&grammar, write_json::object(&mut buf));
+ println!("{}", buf);
+ Ok(())
+}
+
+fn read_stdin() -> io::Result<String> {
+ let mut buf = String::new();
+ io::stdin().lock().read_to_string(&mut buf)?;
+ Ok(buf)
+}
+
+fn grammar_to_json(grammar: &Grammar, mut obj: write_json::Object<'_>) {
+ for node in grammar.iter() {
+ let node = &grammar[node];
+ rule_to_json(grammar, &node.rule, obj.object(&node.name));
+ }
+}
+
+fn rule_to_json(grammar: &Grammar, rule: &Rule, mut obj: write_json::Object<'_>) {
+ match rule {
+ Rule::Labeled { label, rule } => {
+ obj.string("label", label);
+ rule_to_json(grammar, rule, obj.object("rule"))
+ }
+ Rule::Node(node) => {
+ obj.string("node", &grammar[*node].name);
+ }
+ Rule::Token(token) => {
+ obj.string("token", &grammar[*token].name);
+ }
+ Rule::Seq(rules) | Rule::Alt(rules) => {
+ let tag = match rule {
+ Rule::Seq(_) => "seq",
+ Rule::Alt(_) => "alt",
+ _ => unreachable!(),
+ };
+ let mut array = obj.array(tag);
+ for rule in rules {
+ rule_to_json(grammar, rule, array.object());
+ }
+ }
+ Rule::Opt(arg) | Rule::Rep(arg) => {
+ let tag = match rule {
+ Rule::Opt(_) => "opt",
+ Rule::Rep(_) => "rep",
+ _ => unreachable!(),
+ };
+ rule_to_json(grammar, arg, obj.object(tag));
+ }
+ }
+}