use lexington::{Any,Lexer,Match,Matcher,Scanner,Token,Within};
use lexington::{ShiftReduceParser,ShiftReduceRule};
#[derive(Clone,Copy,PartialEq)]
enum Kind { WhiteSpace, Number, LeftBrace, RightBrace }
#[test]
fn shift_reduce_parser_01() {
check("1", Ok(vec![1]));
}
#[test]
fn shift_reduce_parser_02() {
check("x", Err(()));
}
#[test]
fn shift_reduce_parser_03() {
check("(1)", Ok(vec![1]));
}
#[test]
fn shift_reduce_parser_04() {
check("((1))", Ok(vec![1]));
}
#[test]
fn shift_reduce_parser_05() {
check("(1 2)", Ok(vec![1,2]));
}
#[test]
fn shift_reduce_parser_06() {
check("(1 2 3)", Ok(vec![1,2,3]));
}
#[test]
fn shift_reduce_parser_07() {
check("((1) 2 3)", Ok(vec![1,2,3]));
}
#[test]
fn shift_reduce_parser_08() {
check("((1 2) 3)", Ok(vec![1,2,3]));
}
#[test]
fn shift_reduce_parser_09() {
check("(((1) 2) 3)", Ok(vec![1,2,3]));
}
#[test]
fn shift_reduce_parser_10() {
check("((1 2 3))", Ok(vec![1,2,3]));
}
#[test]
fn shift_reduce_parser_11() {
check("(1 (2 3))", Ok(vec![1,2,3]));
}
#[test]
fn shift_reduce_parser_12() {
check("(1 (2 (3)))", Ok(vec![1,2,3]));
}
#[test]
fn shift_reduce_parser_13() {
check("(1 (2) 3)", Ok(vec![1,2,3]));
}
#[test]
fn shift_reduce_parser_14() {
check("(1 2 (3))", Ok(vec![1,2,3]));
}
fn check(input: &str, expected: Result<Vec<usize>,()>) {
let tokens = lex(input);
let reduction_rule = |mut l:Vec<usize>,r:Vec<usize>| { l.extend(r); Ok(l) };
let actual = ShiftReduceParser::new()
.apply(reduction_rule)
.terminate(Kind::Number,|tok| vec![input[tok.range()].parse().unwrap()])
.skip(Kind::WhiteSpace)
.open(Kind::LeftBrace, Vec::new())
.close(Kind::RightBrace)
.parse(tokens);
assert_eq!(actual,expected);
}
fn lex(input: &str) -> Vec<Token<Kind>> {
let whitespace = Any([' ','\n','\t']).one_or_more();
let number = Within('0'..='9').one_or_more();
let scanner = Match(whitespace,Kind::WhiteSpace)
.and_match(number,Kind::Number)
.and_match('(',Kind::LeftBrace)
.and_match(')',Kind::RightBrace);
Lexer::new(input,scanner).collect()
}