use pomelo::*; pomelo! { %extra_token usize; %type One String; %type Two i32; %type Three (char, char); %type line (usize, String); %type lines Vec<(usize, String)>; %type input Vec<(usize, String)>; %syntax_error { let x: usize = token.map(Token::into_extra).unwrap_or(0); Ok(()) } input ::= lines; lines ::= line(L) { vec![L] } lines ::= lines(mut V) Eol(n) line(L) { V.push((n, "/".to_string())); V.push(L); V } line ::= One((n, X)) { (n, X.to_string()) } line ::= Two((n, X)) Two((n1, Y)) { if n != n1 { return Err(()); } (n, format!("{}, {}", X, Y)) } line ::= Three((n, (X1,X2))) Three((n1, (Y1,Y2))) Three((n2, (Z1,Z2))) { if n != n1 || n != n2 { return Err(()); } (n, format!("{}{}{}{}{}{}", X1, X2, Y1, Y2, Z1, Z2)) } } #[test] fn extra_token() -> Result<(), ()> { use parser::*; let mut parse = Parser::new(); parse.parse(Token::One((1, "one".to_string())))?; parse.parse(Token::Eol(1))?; parse.parse(Token::Two((2, 21)))?; parse.parse(Token::Two((2, 42)))?; parse.parse(Token::Eol(2))?; parse.parse(Token::Three((3, ('a', 'b'))))?; parse.parse(Token::Three((3, ('c', 'd'))))?; parse.parse(Token::Three((3, ('e', 'f'))))?; let res = parse.end_of_input()?; assert_eq!(res, vec![ (1, "one"), (1, "/"), (2, "21, 42"), (2, "/"), (3, "abcdef"), ].into_iter().map(|(n, s)| (n, s.to_string())).collect::>()); Ok(()) }