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);
}