change: add raw input for parser error

Signed-off-by: Pakin <pakin.t@forth.co.th>
This commit is contained in:
Pakin 2026-05-25 12:32:44 +07:00
parent 63b809dcf3
commit 2ed4d1dcc3

View file

@ -1,5 +1,5 @@
use lalrpop_util::ParseError as LalrpopParseError;
use crate::xml::parser::grammar::Token;
use lalrpop_util::ParseError as LalrpopParseError;
pub type ParserResult<T> = Result<T, ParseError>;
@ -13,6 +13,7 @@ pub enum ParseError {
position: Position,
message: String,
expected: Vec<String>,
raw: String,
},
SemanticError {
position: Position,
@ -31,13 +32,30 @@ impl std::fmt::Display for ParseError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ParseError::LexerError { position, message } => {
write!(f, "Lexer error at {}:{}: {}", position.line, position.column, message)
write!(
f,
"Lexer error at {}:{}: {}",
position.line, position.column, message
)
}
ParseError::ParserError { position, message, expected } => {
write!(f, "Parser error at {}:{}: {} (expected one of: {:?})", position.line, position.column, message, expected)
ParseError::ParserError {
position,
message,
expected,
raw,
} => {
write!(
f,
"Parser error at {}:{}: {} (expected one of: {:?}) while input: {raw:?}",
position.line, position.column, message, expected
)
}
ParseError::SemanticError { position, message } => {
write!(f, "Semantic error at {}:{}: {}", position.line, position.column, message)
write!(
f,
"Semantic error at {}:{}: {}",
position.line, position.column, message
)
}
}
}
@ -46,41 +64,67 @@ impl std::fmt::Display for ParseError {
impl std::error::Error for ParseError {}
impl ParseError {
pub fn from_lalrpop_error(source: &str, e: LalrpopParseError<usize, Token<'_>, &'static str>) -> Self {
pub fn from_lalrpop_error(
source: &str,
e: LalrpopParseError<usize, Token<'_>, &'static str>,
) -> Self {
match e {
LalrpopParseError::InvalidToken { location } => {
let (line, col) = line_col_from_offset(source, location);
ParseError::LexerError {
position: Position { line, column: col, file: None },
position: Position {
line,
column: col,
file: None,
},
message: format!("Invalid token at location {}", location),
}
}
LalrpopParseError::UnrecognizedEof { location, expected } => {
let (line, col) = line_col_from_offset(source, location);
ParseError::ParserError {
position: Position { line, column: col, file: None },
position: Position {
line,
column: col,
file: None,
},
message: "Unexpected end of input".to_string(),
expected: expected.into_iter().map(|s| s.to_string()).collect(),
raw: source.to_string(),
}
}
LalrpopParseError::UnrecognizedToken { token, expected } => {
let (line, col) = line_col_from_offset(source, token.0);
ParseError::ParserError {
position: Position { line, column: col, file: None },
position: Position {
line,
column: col,
file: None,
},
message: format!("Unrecognized token: {:?}", token.1),
expected: expected.into_iter().map(|s| s.to_string()).collect(),
raw: source.to_string(),
}
}
LalrpopParseError::ExtraToken { token } => {
let (line, col) = line_col_from_offset(source, token.0);
ParseError::ParserError {
position: Position { line, column: col, file: None },
position: Position {
line,
column: col,
file: None,
},
message: format!("Extra token: {:?}", token.1),
expected: Vec::new(),
raw: source.to_string(),
}
}
LalrpopParseError::User { error } => ParseError::SemanticError {
position: Position { line: 0, column: 0, file: None },
position: Position {
line: 0,
column: 0,
file: None,
},
message: error.to_string(),
},
}
@ -102,4 +146,4 @@ fn line_col_from_offset(source: &str, offset: usize) -> (usize, usize) {
}
}
(line, col)
}
}