extern crate gramatica; use std::cmp::Ordering; use std::io::BufRead; use gramatica::{Associativity,EarleyKind,State,Parser,ParsingTablesTrait,AmbiguityInfo}; // see https://www.gnu.org/software/bison/manual/html_node/Infix-Calc.html#Infix-Calc //terminal Num(f64) //{ // fn match(parser: &mut Parser, source:&str) -> Option<(usize,f64)> // { // match parser.re("[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?", source) // { // None => None, // Some(size,string) => Some(size,string.parse::().unwrap()), // } // } //} re_terminal!(Num(f64),"[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?"); //terminal Plus(()) //{ // fn match(parser: &mut Parser, source:&str) -> Option<(usize,())> // { // match parser.re("\\+", source) // { // None => None, // Some(size,string) => Some(size,()), // } // } //} re_terminal!(Plus,"\\+"); //terminal Minus(()) //{ // fn match(parser: &mut Parser, source:&str) -> Option<(usize,())> // { // match parser.re("-", source) // { // None => None, // Some(size,string) => Some(size,()), // } // } //} re_terminal!(Minus,"-"); //terminal Star(()) //{ // fn match(parser: &mut Parser, source:&str) -> Option<(usize,())> // { // match parser.re("\\*", source) // { // None => None, // Some(size,string) => Some(size,()), // } // } //} re_terminal!(Star,"\\*"); //terminal Slash(()) //{ // fn match(parser: &mut Parser, source:&str) -> Option<(usize,())> // { // match parser.re("/", source) // { // None => None, // Some(size,string) => Some(size,()), // } // } //} re_terminal!(Slash,"/"); //terminal Caret(()) //{ // fn match(parser: &mut Parser, source:&str) -> Option<(usize,())> // { // match parser.re("\\^", source) // { // None => None, // Some(size,string) => Some(size,()), // } // } //} re_terminal!(Caret,"\\^"); //terminal LPar(()) //{ // fn match(parser: &mut Parser, source:&str) -> Option<(usize,())> // { // match parser.re("\\(", source) // { // None => None, // Some(size,string) => Some(size,()), // } // } //} re_terminal!(LPar,"\\("); //terminal RPar(()) //{ // fn match(parser: &mut Parser, source:&str) -> Option<(usize,())> // { // match parser.re("\\)", source) // { // None => None, // Some(size,string) => Some(size,()), // } // } //} re_terminal!(RPar,"\\)"); //terminal NewLine(()) //{ // fn match(parser: &mut Parser, source:&str) -> Option<(usize,())> // { // match parser.re("\\n", source) // { // None => None, // Some(size,string) => Some(size,()), // } // } //} re_terminal!(NewLine,"\\n"); re_terminal!(_,"\\s+");//Otherwise skip spaces #[start_symbol] nonterminal Input { () => (), (Input,Line) => (), } nonterminal Line { (NewLine) => (), (Expression(value), NewLine) => { println!("{}",value); }, } nonterminal Expression(f64) { (Num(value)) => value, //#[priority(addition),associativity(left)] #[priority(addition)] #[associativity(left)] (Expression(l),Plus,Expression(r)) => l+r, //#[priority(addition),associativity(left)] #[priority(addition)] #[associativity(left)] (Expression(l),Minus,Expression(r)) => l-r, //#[priority(multiplication),associativity(left)] #[priority(multiplication)] #[associativity(left)] (Expression(l),Star,Expression(r)) => l*r, //#[priority(multiplication),associativity(left)] #[priority(multiplication)] #[associativity(left)] (Expression(l),Slash,Expression(r)) => l/r, //#[priority(addition),associativity(left)] #[priority(addition)] #[associativity(left)] (Minus,Expression(value)) => -value, //#[priority(exponentiation),associativity(right)] #[priority(exponentiation)] #[associativity(right)] (Expression(l),Caret,Expression(r)) => l.powf(r), (LPar,Expression(value),RPar) => value, } ordering!(exponentiation,multiplication,addition); fn parse_from_stdin() { let stdin=std::io::stdin(); for rline in stdin.lock().lines() { let line=rline.unwrap()+"\n"; println!("line={}",line); match Parser::::parse(&line,None) { Err(x) => println!("error parsing: {:?}",x), Ok(x) => println!("parsed correctly: {:?}",x), }; } } fn main() { //let text="1+2*3^4\n"; //let text=""; //let text="1+2+3\n4 * 5 * 6\n"; //Parser::parse(&text,None); parse_from_stdin(); }