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
#![deny(warnings)]
extern crate earlgrey;
use ebnf::ParserBuilder;
use self::earlgrey::{EarleyParser, EarleyForest, Error};
#[derive(Clone,Debug)]
pub enum Sexpr {
Atom(String),
List(Vec<Sexpr>),
}
#[derive(Debug,Clone,PartialEq)]
pub enum Tree {
Leaf(String, String),
Node(String, Vec<Tree>),
}
impl Sexpr {
pub fn print(&self) { self.print_helper("") }
fn print_helper(&self, level: &str) {
match *self {
Sexpr::Atom(ref lexeme) => println!("{}`-- {:?}", level, lexeme),
Sexpr::List(ref subn) => {
println!("{}`--", level);
if let Some((last, rest)) = subn.split_last() {
let l = format!("{} |", level);
for n in rest { n.print_helper(&l); }
let l = format!("{} ", level);
last.print_helper(&l);
}
}
}
}
}
impl ParserBuilder {
pub fn treeficator<S, SI>(self, grammar: &str, start: &str)
-> impl Fn(SI) -> Result<Vec<Tree>, Error>
where S: AsRef<str>, SI: Iterator<Item=S>
{
let grammar = ParserBuilder::parse_grammar(self.0, grammar)
.unwrap_or_else(|e| panic!("treeficator error: {:?}", e))
.into_grammar(start)
.unwrap_or_else(|e| panic!("treeficator error: {:?}", e));
let mut tree_builder = EarleyForest::new(
|sym, tok| Tree::Leaf(sym.to_string(), tok.to_string()));
for rule in grammar.str_rules() {
tree_builder.action(&rule.to_string(),
move |nodes| Tree::Node(rule.to_string(), nodes));
}
let parser = EarleyParser::new(grammar);
move |tokenizer| tree_builder.eval_all(&parser.parse(tokenizer)?)
}
pub fn sexprificator<S, SI>(self, grammar: &str, start: &str)
-> impl Fn(SI) -> Result<Vec<Sexpr>, Error>
where S: AsRef<str>, SI: Iterator<Item=S>
{
let grammar = ParserBuilder::parse_grammar(self.0, grammar)
.unwrap_or_else(|e| panic!("treeficator error: {:?}", e))
.into_grammar(start)
.unwrap_or_else(|e| panic!("treeficator error: {:?}", e));
let mut tree_builder = EarleyForest::new(
|_, tok| Sexpr::Atom(tok.to_string()));
for rule in grammar.str_rules() {
tree_builder.action(&rule, move |mut nodes| match nodes.len() {
1 => nodes.swap_remove(0),
_ => Sexpr::List(nodes),
});
}
let parser = EarleyParser::new(grammar);
move |tokenizer| tree_builder.eval_all(&parser.parse(tokenizer)?)
}
}