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::<f64>().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::<Token,ParsingTables>::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();
}