//#![feature(slice_patterns)] extern crate gramatica; use std::cmp::Ordering; use std::io::BufRead; use gramatica::{Associativity,EarleyKind,State,Parser,ParsingTablesTrait}; #[derive(Clone,Debug,PartialEq)] enum Token { DummyStart,//0 reserved for dummy start Num(f64),//1 Plus,//2 Minus,//3 Star,//4 Slash,//5 Caret,//6 LPar,//7 RPar,//8 NewLine,//9 Input,//10 Line,//11 Expression(f64),//12 } impl Default for Token { fn default() -> Self { Token::DummyStart } } struct ParsingTables { } impl ParsingTablesTrait for ParsingTables { fn initial()->usize { 10 } //fn match_some(&mut self) -> Option<(usize,Token)> fn match_some(parser: &mut Parser) -> Option<(usize,Token)> { //let parser=&mut self; let source=&parser.source[parser.source_index..]; match { //match parser.re("[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?", source) //parser.re("[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?", source); //let rr:Option<(usize,String)>=None; //match rr //match self.re("[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?", source) match parser.re("[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?", source) { None => None, Some((size,string)) => Some((size,string.parse::().unwrap())), } } { None => (), Some((size,result)) => return Some((size,Token::Num(result))), }; match { match parser.re("\\+", source) { None => None, Some((size,_string)) => Some((size,())), } } { None => (), Some((size,_result)) => return Some((size,Token::Plus)), }; match { match parser.re("-", source) { None => None, Some((size,_string)) => Some((size,())), } } { None => (), Some((size,_result)) => return Some((size,Token::Minus)), }; match { match parser.re("\\*", source) { None => None, Some((size,_string)) => Some((size,())), } } { None => (), Some((size,_result)) => return Some((size,Token::Star)), }; match { match parser.re("/", source) { None => None, Some((size,_string)) => Some((size,())), } } { None => (), Some((size,_result)) => return Some((size,Token::Slash)), }; match { match parser.re("\\^", source) { None => None, Some((size,_string)) => Some((size,())), } } { None => (), Some((size,_result)) => return Some((size,Token::Caret)), }; match { match parser.re("\\(", source) { None => None, Some((size,_string)) => Some((size,())), } } { None => (), Some((size,_result)) => return Some((size,Token::LPar)), }; match { match parser.re("\\)", source) { None => None, Some((size,_string)) => Some((size,())), } } { None => (), Some((size,_result)) => return Some((size,Token::RPar)), }; match { match parser.re("\n", source) { None => None, Some((size,_string)) => Some((size,())), } } { None => (), Some((size,_result)) => return Some((size,Token::NewLine)), }; match { match parser.re("\\s+", source) { None => None, Some((size,_string)) => Some((size,())), } } { None => (), Some((size,_result)) => return Some((size,Token::DummyStart)), }; None } fn predict(parser:&mut Parser,index:usize,state_index:usize,token:usize) { match token { 10 => //input { parser.sets[index].predict(State{rule:1,left:10,right:vec![],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![],computed_value:Token::DummyStart});//Input -> () parser.sets[index].predict(State{rule:2,left:10,right:vec![10,11],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart;2],computed_value:Token::DummyStart});//Input -> Input,Line }, 11 => //Line { parser.sets[index].predict(State{rule:3,left:11,right:vec![9],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart;1],computed_value:Token::DummyStart});//Line -> NewLine parser.sets[index].predict(State{rule:4,left:11,right:vec![12,9],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart;2],computed_value:Token::DummyStart});//Line -> Expression,NewLine }, 12 => //Expression { parser.sets[index].predict(State{rule:5,left:12,right:vec![1],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart;1],computed_value:Token::DummyStart});//Expression -> Num parser.sets[index].predict(State{rule:6,left:12,right:vec![12,2,12],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart;3],computed_value:Token::DummyStart});//Expression -> Expression Plus Expression parser.sets[index].predict(State{rule:7,left:12,right:vec![12,3,12],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart;3],computed_value:Token::DummyStart});//Expression -> Expression Minus Expression parser.sets[index].predict(State{rule:8,left:12,right:vec![12,4,12],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart;3],computed_value:Token::DummyStart});//Expression -> Expression Star Expression parser.sets[index].predict(State{rule:9,left:12,right:vec![12,5,12],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart;3],computed_value:Token::DummyStart});//Expression -> Expression Slash Expression parser.sets[index].predict(State{rule:10,left:12,right:vec![3,12],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart;2],computed_value:Token::DummyStart});//Expression -> Minus Expression parser.sets[index].predict(State{rule:11,left:12,right:vec![12,6,12],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart;3],computed_value:Token::DummyStart});//Expression -> Expression Caret Expression parser.sets[index].predict(State{rule:12,left:12,right:vec![7,12,8],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart;3],computed_value:Token::DummyStart});//Expression -> LPar Expression RPar }, _ => panic!("nonterminal?"), }; } fn compute_value(state:&mut State) { //println!("compute_value {:?}",state); state.computed_value = match state.rule { 0 => state.values[0].clone(), 1 => Token::Input, 2 => Token::Input, 3 => Token::Line, 4 => match state.values[0] { Token::Expression(value) => { println!("{}",value); Token::Line }, _ => panic!(""), }, 5 => match state.values[0] { Token::Num(value) => Token::Expression(value), _ => panic!("NO NUM"), }, //This almost work //6 => match state.values //{ // [Token::Expression(l),Token::Plus,Token::Expression(r)] => Token::Expression(l+r), // _ => panic!(""), //} 6 => match state.values[0] { Token::Expression(l) => match state.values[2] { Token::Expression(r) => Token::Expression(l+r), _ => panic!(""), }, _ => panic!(""), } 7 => match state.values[0] { Token::Expression(l) => match state.values[2] { Token::Expression(r) => Token::Expression(l-r), _ => panic!(""), }, _ => panic!(""), } 8 => match state.values[0] { Token::Expression(l) => match state.values[2] { Token::Expression(r) => Token::Expression(l*r), _ => panic!(""), }, _ => panic!(""), } 9 => match state.values[0] { Token::Expression(l) => match state.values[2] { Token::Expression(r) => Token::Expression(l/r), _ => panic!(""), }, _ => panic!(""), } 10 => match state.values[1] { Token::Expression(value) => Token::Expression(-value), _ => panic!(""), } 11 => match state.values[0] { Token::Expression(l) => match state.values[2] { Token::Expression(r) => Token::Expression(l.powf(r)), _ => panic!(""), }, _ => panic!(""), } 12 => match state.values[1] { Token::Expression(value) => Token::Expression(value), _ => panic!(""), } _ => panic!("Not a rule"), } } fn table_terminal(token_index:usize)->bool { match token_index { 1|2|3|4|5|6|7|8|9 => true, 0|10|11|12 => false, _ => panic!("table_terminal"), } } fn table_priority(a:usize, b:usize) -> Option { //(6,7,10) > (8,9) > 11 match (a,b) { (6,6) => Some(Ordering::Equal), (6,7) => Some(Ordering::Equal), (6,8) => Some(Ordering::Greater), (6,9) => Some(Ordering::Greater), (6,10) => Some(Ordering::Equal), (6,11) => Some(Ordering::Greater), (7,6) => Some(Ordering::Equal), (7,7) => Some(Ordering::Equal), (7,8) => Some(Ordering::Greater), (7,9) => Some(Ordering::Greater), (7,10) => Some(Ordering::Equal), (7,11) => Some(Ordering::Greater), (8,6) => Some(Ordering::Less), (8,7) => Some(Ordering::Less), (8,8) => Some(Ordering::Equal), (8,9) => Some(Ordering::Equal), (8,10) => Some(Ordering::Less), (8,11) => Some(Ordering::Greater), (9,6) => Some(Ordering::Less), (9,7) => Some(Ordering::Less), (9,8) => Some(Ordering::Equal), (9,9) => Some(Ordering::Equal), (9,10) => Some(Ordering::Less), (9,11) => Some(Ordering::Greater), (10,6) => Some(Ordering::Equal), (10,7) => Some(Ordering::Equal), (10,8) => Some(Ordering::Greater), (10,9) => Some(Ordering::Greater), (10,10) => Some(Ordering::Equal), (10,11) => Some(Ordering::Greater), (11,6) => Some(Ordering::Less), (11,7) => Some(Ordering::Less), (11,8) => Some(Ordering::Less), (11,9) => Some(Ordering::Less), (11,10) => Some(Ordering::Less), (11,11) => Some(Ordering::Equal), _ => None, } } fn table_associativity(rule:usize) -> Option { match rule { 6 => Some(Associativity::Left), 7 => Some(Associativity::Left), 8 => Some(Associativity::Left), 9 => Some(Associativity::Left), 10 => Some(Associativity::Left), 11 => Some(Associativity::Right), _ => None, } } fn to_usize(token:&Token) -> usize { token.to_usize() } } impl Token { //fn is_terminal(&self) -> bool //{ // match self // { // &Token::DummyStart => false, // &Token::Num(_) => true, // &Token::Plus => true, // &Token::Minus => true, // &Token::Star => true, // &Token::Slash => true, // &Token::Caret => true, // &Token::LPar => true, // &Token::RPar => true, // &Token::NewLine => true, // &Token::Input => false, // &Token::Line => false, // &Token::Expression(_) => false, // } //} fn to_usize(&self) -> usize { match self { &Token::DummyStart => 0, &Token::Num(_) => 1, &Token::Plus => 2, &Token::Minus => 3, &Token::Star => 4, &Token::Slash => 5, &Token::Caret => 6, &Token::LPar => 7, &Token::RPar => 8, &Token::NewLine => 9, &Token::Input => 10, &Token::Line => 11, &Token::Expression(_) => 12, } } } 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(); }