-
Notifications
You must be signed in to change notification settings - Fork 19
Open
Labels
Description
I have a usecase where I'd like to somehow pass numbering::InputPosition::position to an Error type as a way of reporting parsing errors at a location (e.g. line/column location).
The issue is that I'm unable to access numbering::InputPosition::position from within chomp::types::ParseResult::map_err function.
I adapted map_err into map_err2 as follows: dashed@3f1998b
This enables me to do this:
type ESParseResult<I, T> = ParseResult<I, T, ParseError>;
fn some_parser<I: U8Input>(i: InputPosition<I, CurrentPosition>)
-> ESParseResult<InputPosition<I, CurrentPosition>, ()> {
parse!{i;
let _var = (i -> {
string(i, b"var")
.map_err2(|_, i| {
let loc = i.position();
ParseError::Expected(loc, "Expected var here.")
})
});
// ...
ret {()}
}
}I'd love to hear any feedback on this, especially for any better alternative approaches. 👍
Appendix
CurrentPosition type for reference:
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub struct CurrentPosition(
// The current line, zero-indexed.
u64,
// The current col, zero-indexed.
u64
);
impl CurrentPosition {
// Creates a new (line, col) counter with zero.
pub fn new() -> Self {
CurrentPosition(0, 0)
}
}
impl Numbering for CurrentPosition {
type Token = u8;
fn update<'a, B>(&mut self, b: &'a B)
where B: Buffer<Token=Self::Token> {
b.iterate(|c| if c == b'\n' {
self.0 += 1; // line num
self.1 = 0; // col num
} else {
self.1 += 1; // col num
});
}
fn add(&mut self, t: Self::Token) {
if t == b'\n' {
self.0 += 1; // line num
self.1 = 0; // col num
} else {
self.1 += 1; // col num
}
}
}pub trait Input: Sized {
// ...
#[inline]
pub fn map_err2<V, F>(self, f: F) -> ParseResult<I, T, V>
where F: FnOnce(E, &I) -> V {
match self {
ParseResult(i, Ok(t)) => ParseResult(i, Ok(t)),
ParseResult(i, Err(e)) => {
let err = f(e, &i);
ParseResult(i, Err(err))
},
}
}
// ...
}Reactions are currently unavailable