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