extern crate frithu; use frithu::grammar; use frithu::parser; fn calc_grammar() -> grammar::Grammar { let mut builder = grammar::GrammarBuilder::new("Sum"); builder.rule("Number").terminal('0').add(); builder.rule("Number").terminal('1').add(); builder.rule("Number").terminal('2').add(); builder.rule("Number").terminal('3').add(); builder.rule("Number").terminal('4').add(); builder.rule("Number").terminal('5').add(); builder.rule("Number").terminal('6').add(); builder.rule("Number").terminal('7').add(); builder.rule("Number").terminal('8').add(); builder.rule("Number").terminal('9').add(); builder .rule("Number") .terminal('0') .nonterminal("Number") .add(); builder .rule("Number") .terminal('1') .nonterminal("Number") .add(); builder .rule("Number") .terminal('2') .nonterminal("Number") .add(); builder .rule("Number") .terminal('3') .nonterminal("Number") .add(); builder .rule("Number") .terminal('4') .nonterminal("Number") .add(); builder .rule("Number") .terminal('5') .nonterminal("Number") .add(); builder .rule("Number") .terminal('6') .nonterminal("Number") .add(); builder .rule("Number") .terminal('7') .nonterminal("Number") .add(); builder .rule("Number") .terminal('8') .nonterminal("Number") .add(); builder .rule("Number") .terminal('9') .nonterminal("Number") .add(); builder.rule("Factor").nonterminal("Number").add(); builder .rule("Factor") .terminal('(') .nonterminal("Sum") .terminal(')') .add(); builder.rule("Product").nonterminal("Factor").add(); builder .rule("Product") .nonterminal("Product") .terminal('*') .nonterminal("Factor") .add(); builder .rule("Product") .nonterminal("Product") .terminal('/') .nonterminal("Factor") .add(); builder.rule("Sum").nonterminal("Product").add(); builder .rule("Sum") .nonterminal("Sum") .terminal('+') .nonterminal("Product") .add(); builder .rule("Sum") .nonterminal("Sum") .terminal('-') .nonterminal("Product") .add(); builder.build().expect("Could not build valid grammar?") } #[test] fn recognise_valid_input() { let grammar = calc_grammar(); let mut parser = parser::Parser::new(&grammar).expect("grammar has bad initial rule?"); let mut trees = Default::default(); for c in "1+(2*3-4)".chars() { trees = parser.feed(c).expect("broken rule reference?"); } for each in trees.iter() { each.dump(0); } assert_eq!(trees.len(), 1); } #[test] fn reject_incomplete_input() { let grammar = calc_grammar(); let mut parser = parser::Parser::new(&grammar).expect("grammar has bad initial rule?"); let mut trees = Default::default(); for c in "1+(2*".chars() { trees = parser.feed(c).expect("broken rule reference?"); } for each in trees.iter() { each.dump(0); } assert_eq!(trees.len(), 0); } #[test] fn reject_invalid_input() { let grammar = calc_grammar(); let mut parser = parser::Parser::new(&grammar).expect("grammar has bad initial rule?"); parser.feed('1').expect("parser rejected a digit?"); let actual = parser .feed('x') .expect_err("parser accepted invalid input?"); let expected = parser::Error::InvalidInput { offset: 1, got: 'x', expected: "0123456789*+-/".chars().collect(), }; assert_eq!(actual, expected); }