Make default user error &'static str instead of ()

Because () doesn't implement fmt::Display, which is inconvenient.
This commit is contained in:
Joeri van Ruth 2017-09-13 15:08:18 +02:00
parent e51a157122
commit f71329d454
6 changed files with 30 additions and 19 deletions

View File

@ -3,7 +3,7 @@ use std::cell::RefCell;
use util::tok::Tok;
use lalrpop_util::ErrorRecovery;
grammar<'e>(errors: &'e RefCell<Vec<ErrorRecovery<(), Tok, ()>>>);
grammar<'e>(errors: &'e RefCell<Vec<ErrorRecovery<(), Tok, &'static str>>>);
extern {
enum Tok {

View File

@ -2,7 +2,7 @@
use util::tok::Tok;
use lalrpop_util::ErrorRecovery;
grammar<'input, 'e>(errors: &'e mut Vec<ErrorRecovery<(), Tok, ()>>);
grammar<'input, 'e>(errors: &'e mut Vec<ErrorRecovery<(), Tok, &'static str>>);
extern {
enum Tok {

View File

@ -155,24 +155,30 @@ fn expr_intern_tok_test_err() {
}
#[test]
fn expr_intern_tok_display_err() {
fn parse_error_map() {
let expr = "(1+\n(2++3))";
let result = expr_intern_tok::parse_Expr(1, expr);
let err : lalrpop_util::ParseError<usize, (usize, &str),()>
let err : lalrpop_util::ParseError<usize, (usize, &str),&'static str>
= result.unwrap_err();
// The problem is that (usize,&str) and () do not implement fmt::Display,
// so neither does the ParseError.
// We can fix that by rewriting them to something that has fmt::Display
let disp = err.map_token(|(_,t)|t).map_error(|_| "error");
let message = disp.to_string();
assert!(message.contains("Unrecognized token `+`"));
let message = err
.map_token(|(_,t)| format!("TOKEN {}", t))
.map_location(|offset| format!("line {}", expr[0..offset].lines().count()))
.to_string();
assert!(message.contains("Unrecognized token `TOKEN +`"));
assert!(message.contains("at line 2"));
}
// We can even convert the locations to a line number
let line_based = disp.map_location(|offset| {
format!("line {}", expr[0..offset].lines().count())
});
assert!(line_based.to_string().contains("line 2"));
#[test]
fn parse_error_map_err() {
let err : lalrpop_util::ParseError<usize, util::tok::Tok, char>
= util::test_err_gen(error::parse_Items, "---+").unwrap_err();
let modified_err = err.map_error(|c| c.to_string());
if let ParseError::User { error: user_error_value } = modified_err {
assert_eq!(user_error_value, "+");
} else {
panic!("Expected a User error")
}
}
#[test]

View File

@ -9,7 +9,7 @@ use util::tok::Tok;
pub mod tok;
pub fn test<R: Debug + Eq, F>(parse_fn: F, input: &str, expected: R)
where F: FnOnce(Vec<Tok>) -> Result<R, ParseError<(), Tok, ()>>
where F: FnOnce(Vec<Tok>) -> Result<R, ParseError<(), Tok, &'static str>>
{
// create tokens
let tokens = tok::tokenize(input);
@ -29,7 +29,7 @@ pub fn test<R: Debug + Eq, F>(parse_fn: F, input: &str, expected: R)
}
pub fn test_loc<R: Debug + Eq, F>(parse_fn: F, input: &str, expected: R)
where F: FnOnce(Vec<(usize, Tok, usize)>) -> Result<R, ParseError<usize, Tok, ()>>
where F: FnOnce(Vec<(usize, Tok, usize)>) -> Result<R, ParseError<usize, Tok, &'static str>>
{
// create tokens
let tokens = tok::tokenize(input);

View File

@ -263,6 +263,7 @@ impl Types {
terminal_token_type: terminal_token_type,
terminal_types: map(),
nonterminal_types: map(),
// the following two will be overwritten later
parse_error_type: TypeRepr::Tuple(vec![]),
error_recovery_type: TypeRepr::Tuple(vec![]) };
@ -314,7 +315,11 @@ impl Types {
pub fn error_type(&self) -> TypeRepr {
self.error_type.clone()
.unwrap_or_else(|| TypeRepr::Tuple(vec![]))
.unwrap_or_else(|| TypeRepr::Ref {
lifetime: Some(intern("'static")),
mutable: false,
referent: Box::new(TypeRepr::str()),
})
}
pub fn terminal_type(&self, id: TerminalString) -> &TypeRepr {

View File

@ -220,6 +220,6 @@ fn error() {
grammar;
Z = !;
"#, vec![
("Z", "__lalrpop_util::ParseError<usize, (usize, &'input str), ()>")
("Z", "__lalrpop_util::ParseError<usize, (usize, &'input str), &'static str>")
])
}