fn build_grammar() -> earlgrey::Grammar { use std::str::FromStr; earlgrey::GrammarBuilder::default() .nonterm("expr") .nonterm("term") .nonterm("factor") .nonterm("power") .nonterm("ufact") .nonterm("group") .nonterm("func") .nonterm("args") .terminal("[n]", |n| f64::from_str(n).is_ok()) .terminal("+", |n| n == "+") .terminal("-", |n| n == "-") .terminal("*", |n| n == "*") .terminal("/", |n| n == "/") .terminal("%", |n| n == "%") .terminal("^", |n| n == "^") .terminal("!", |n| n == "!") .terminal("(", |n| n == "(") .terminal(")", |n| n == ")") .rule("expr", &["term"]) .rule("expr", &["expr", "+", "term"]) .rule("expr", &["expr", "-", "term"]) .rule("term", &["factor"]) .rule("term", &["term", "*", "factor"]) .rule("term", &["term", "/", "factor"]) .rule("term", &["term", "%", "factor"]) .rule("factor", &["power"]) .rule("factor", &["-", "factor"]) .rule("power", &["ufact"]) .rule("power", &["ufact", "^", "factor"]) .rule("ufact", &["group"]) .rule("ufact", &["ufact", "!"]) .rule("group", &["[n]"]) .rule("group", &["(", "expr", ")"]) .into_grammar("expr") .expect("Bad Gramar") } struct Tokenizer>(lexers::Scanner); impl> Iterator for Tokenizer { type Item = String; fn next(&mut self) -> Option { self.0.scan_whitespace(); self.0 .scan_math_op() .or_else(|| self.0.scan_number()) .or_else(|| self.0.scan_identifier()) } } fn tokenizer>(input: I) -> Tokenizer { Tokenizer(lexers::Scanner::new(input)) } fn gamma(x: f64) -> f64 { #[link(name = "m")] extern "C" { fn tgamma(x: f64) -> f64; } unsafe { tgamma(x) } } fn semanter<'a>() -> earlgrey::EarleyForest<'a, f64> { use std::str::FromStr; let mut ev = earlgrey::EarleyForest::new(|symbol, token| match symbol { "[n]" => f64::from_str(token).unwrap(), _ => 0.0, }); ev.action("expr -> term", |n| n[0]); ev.action("expr -> expr + term", |n| n[0] + n[2]); ev.action("expr -> expr - term", |n| n[0] - n[2]); ev.action("term -> factor", |n| n[0]); ev.action("term -> term * factor", |n| n[0] * n[2]); ev.action("term -> term / factor", |n| n[0] / n[2]); ev.action("term -> term % factor", |n| n[0] % n[2]); ev.action("factor -> power", |n| n[0]); ev.action("factor -> - factor", |n| -n[1]); ev.action("power -> ufact", |n| n[0]); ev.action("power -> ufact ^ factor", |n| n[0].powf(n[2])); ev.action("ufact -> group", |n| n[0]); ev.action("ufact -> ufact !", |n| gamma(n[0] + 1.0)); ev.action("group -> [n]", |n| n[0]); ev.action("group -> ( expr )", |n| n[1]); ev } fn main() -> Result<(), String> { let grammar = build_grammar(); let parser = earlgrey::EarleyParser::new(grammar.clone()); let evaler = semanter(); if std::env::args().len() > 1 { let input = std::env::args().skip(1).collect::>().join(" "); match parser.parse(tokenizer(input.chars())) { Err(e) => println!("Parse err: {:?}", e), Ok(state) => println!("{:?}", evaler.eval(&state)), } return Ok(()); } println!("{:?}", grammar); use rustyline::error::ReadlineError; let mut rl = rustyline::DefaultEditor::new().map_err(|e| e.to_string())?; loop { match rl.readline("~> ") { Err(ReadlineError::Interrupted) | Err(ReadlineError::Eof) => return Ok(()), Err(e) => return Err(format!("Readline err: {:?}", e)), Ok(line) => match parser.parse(&mut tokenizer(line.chars())) { Err(e) => println!("Parse err: {:?}", e), Ok(state) => { let _ = rl.add_history_entry(&line); println!("{:?}", evaler.eval(&state)); } }, } } }