Skip to content

Accessing numbering::InputPosition::position via map_err #60

@dashed

Description

@dashed

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))
            },
        }
    }

    // ...
}

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions