mirror of
https://github.com/vosen/ZLUDA.git
synced 2025-07-20 10:46:21 +03:00
Improve error recovery (#418)
This commit is contained in:
@ -294,7 +294,8 @@ fn constant<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<ast::Imme
|
|||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}).parse_next(stream)
|
})
|
||||||
|
.parse_next(stream)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn immediate_value<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<ast::ImmediateValue> {
|
fn immediate_value<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<ast::ImmediateValue> {
|
||||||
@ -439,6 +440,8 @@ fn directive<'a, 'input>(
|
|||||||
(module_variable, Token::Semicolon)
|
(module_variable, Token::Semicolon)
|
||||||
.map(|((linking, var), _)| Some(ast::Directive::Variable(linking, var))),
|
.map(|((linking, var), _)| Some(ast::Directive::Variable(linking, var))),
|
||||||
)),
|
)),
|
||||||
|
(
|
||||||
|
any,
|
||||||
take_till(1.., |(token, _)| match token {
|
take_till(1.., |(token, _)| match token {
|
||||||
// visibility
|
// visibility
|
||||||
Token::DotExtern | Token::DotVisible | Token::DotWeak
|
Token::DotExtern | Token::DotVisible | Token::DotWeak
|
||||||
@ -450,6 +453,8 @@ fn directive<'a, 'input>(
|
|||||||
| Token::DotFile | Token::DotSection => true,
|
| Token::DotFile | Token::DotSection => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}),
|
}),
|
||||||
|
)
|
||||||
|
.map(|(_, x)| x),
|
||||||
|text| PtxError::UnrecognizedDirective(text.unwrap_or("")),
|
|text| PtxError::UnrecognizedDirective(text.unwrap_or("")),
|
||||||
)
|
)
|
||||||
.map(Option::flatten)
|
.map(Option::flatten)
|
||||||
@ -708,32 +713,32 @@ fn take_till_inclusive<I: Stream, E: ParserError<I>>(
|
|||||||
backtrack_token: impl Fn(&I::Token) -> bool,
|
backtrack_token: impl Fn(&I::Token) -> bool,
|
||||||
end_token: impl Fn(&I::Token) -> bool,
|
end_token: impl Fn(&I::Token) -> bool,
|
||||||
) -> impl Parser<I, <I as Stream>::Slice, E> {
|
) -> impl Parser<I, <I as Stream>::Slice, E> {
|
||||||
fn get_offset<I: Stream>(
|
fn get_offset<I: Stream, E: ParserError<I>>(
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
backtrack_token: &impl Fn(&I::Token) -> bool,
|
backtrack_token: &impl Fn(&I::Token) -> bool,
|
||||||
end_token: &impl Fn(&I::Token) -> bool,
|
end_token: &impl Fn(&I::Token) -> bool,
|
||||||
should_backtrack: &mut bool,
|
should_backtrack: &mut bool,
|
||||||
) -> usize {
|
) -> Result<usize, E> {
|
||||||
*should_backtrack = false;
|
*should_backtrack = false;
|
||||||
let mut hit = false;
|
let mut hit = false;
|
||||||
for (offset, token) in input.iter_offsets() {
|
for (offset, token) in input.iter_offsets() {
|
||||||
if hit {
|
if hit {
|
||||||
return offset;
|
return Ok(offset);
|
||||||
} else {
|
} else {
|
||||||
if backtrack_token(&token) {
|
if backtrack_token(&token) {
|
||||||
*should_backtrack = true;
|
*should_backtrack = true;
|
||||||
return offset;
|
return Ok(offset);
|
||||||
}
|
}
|
||||||
if end_token(&token) {
|
if end_token(&token) {
|
||||||
hit = true;
|
hit = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
input.eof_offset()
|
Err(ParserError::from_error_kind(input, ErrorKind::Eof))
|
||||||
}
|
}
|
||||||
move |stream: &mut I| {
|
move |stream: &mut I| {
|
||||||
let mut should_backtrack = false;
|
let mut should_backtrack = false;
|
||||||
let offset = get_offset(stream, &backtrack_token, &end_token, &mut should_backtrack);
|
let offset = get_offset(stream, &backtrack_token, &end_token, &mut should_backtrack)?;
|
||||||
let result = stream.next_slice(offset);
|
let result = stream.next_slice(offset);
|
||||||
if should_backtrack {
|
if should_backtrack {
|
||||||
Err(ErrMode::from_error_kind(
|
Err(ErrMode::from_error_kind(
|
||||||
@ -774,7 +779,7 @@ fn with_recovery<'a, 'input: 'a, T>(
|
|||||||
let stream_start = stream.checkpoint();
|
let stream_start = stream.checkpoint();
|
||||||
match parser.parse_next(stream) {
|
match parser.parse_next(stream) {
|
||||||
Ok(value) => Ok(Some(value)),
|
Ok(value) => Ok(Some(value)),
|
||||||
Err(ErrMode::Backtrack(_)) => {
|
Err(_) => {
|
||||||
stream.reset(&stream_start);
|
stream.reset(&stream_start);
|
||||||
let tokens = recovery.parse_next(stream)?;
|
let tokens = recovery.parse_next(stream)?;
|
||||||
let range = match input_start {
|
let range = match input_start {
|
||||||
@ -788,7 +793,6 @@ fn with_recovery<'a, 'input: 'a, T>(
|
|||||||
stream.state.errors.push(error(range));
|
stream.state.errors.push(error(range));
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
Err(err) => Err(err),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1280,7 +1284,7 @@ pub enum PtxError<'input> {
|
|||||||
#[from]
|
#[from]
|
||||||
source: TokenError,
|
source: TokenError,
|
||||||
},
|
},
|
||||||
#[error("")]
|
#[error("{0}")]
|
||||||
Parser(ContextError),
|
Parser(ContextError),
|
||||||
#[error("")]
|
#[error("")]
|
||||||
Todo,
|
Todo,
|
||||||
@ -1531,14 +1535,14 @@ where
|
|||||||
Err(ErrMode::Backtrack(_)) => {
|
Err(ErrMode::Backtrack(_)) => {
|
||||||
input.reset(&start);
|
input.reset(&start);
|
||||||
None
|
None
|
||||||
},
|
}
|
||||||
Err(e) => return Err(e)
|
Err(e) => return Err(e),
|
||||||
};
|
};
|
||||||
|
|
||||||
match required.parse_next(input) {
|
match required.parse_next(input) {
|
||||||
Ok(v) => return Ok((parsed_optional, v)),
|
Ok(v) => return Ok((parsed_optional, v)),
|
||||||
Err(ErrMode::Backtrack(_)) => input.reset(&start),
|
Err(ErrMode::Backtrack(_)) => input.reset(&start),
|
||||||
Err(e) => return Err(e)
|
Err(e) => return Err(e),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((None, required.parse_next(input)?))
|
Ok((None, required.parse_next(input)?))
|
||||||
@ -3611,7 +3615,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn report_unknown_intruction() {
|
fn report_unknown_instruction() {
|
||||||
let text = "
|
let text = "
|
||||||
.version 6.5
|
.version 6.5
|
||||||
.target sm_30
|
.target sm_30
|
||||||
@ -3689,4 +3693,21 @@ mod tests {
|
|||||||
PtxError::UnrecognizedDirective("section foobar }")
|
PtxError::UnrecognizedDirective("section foobar }")
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn report_unknown_type_in_directive() {
|
||||||
|
let text = "
|
||||||
|
.version 4.1
|
||||||
|
.target sm_52
|
||||||
|
.address_size 64
|
||||||
|
.global .bad_type foo;
|
||||||
|
.const .b32 bar;
|
||||||
|
";
|
||||||
|
let errors = parse_module_checked(text).err().unwrap();
|
||||||
|
assert_eq!(errors.len(), 1);
|
||||||
|
assert!(matches!(
|
||||||
|
errors[0],
|
||||||
|
PtxError::UnrecognizedDirective(".global .bad_type foo;")
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user