Skip to content

Conversation

tisonkun
Copy link
Contributor

@tisonkun tisonkun commented Jan 6, 2025

This refers to #4.

Signed-off-by: tison <wander4096@gmail.com>
Signed-off-by: tison <wander4096@gmail.com>
Signed-off-by: tison <wander4096@gmail.com>
Signed-off-by: tison <wander4096@gmail.com>
Signed-off-by: tison <wander4096@gmail.com>
Signed-off-by: tison <wander4096@gmail.com>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @epage! I ever try to use winnow for parsing the JSONPath expression with a customized token kind from Logos output. But it's really hard to understand how to finish this integration.

  1. How to bridge the Span/Located functions so that we can report failed position accurately?
  2. My Token type is with span, while the equality is only related to compare the Kind, and possibly the text() result. The demo from this page assume Token is an owned struct without source/span like logos typically have.

I'm fine yet with the handmade parser. And this is not a request. Just share a user case where I failed to use winnow while I think it may be fit. If you have some time, maybe you can try to figure out an integration demo for winnow + logos. It can help with the goal that winnow wants to support customized token type.

Copy link
Contributor Author

@tisonkun tisonkun Jan 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, I ever work out a solution to integrate logos with nom. Something like:

#[derive(Debug, Clone, Copy)]
pub struct Input<'a> {
    pub tokens: &'a [Token<'a>],
}

impl<'a> std::ops::Deref for Input<'a> {
    type Target = [Token<'a>];

    fn deref(&self) -> &Self::Target {
        self.tokens
    }
}

impl nom::InputLength for Input<'_> {
    fn input_len(&self) -> usize {
        self.tokens.input_len()
    }
}

impl nom::Offset for Input<'_> {
    fn offset(&self, second: &Self) -> usize {
        let fst = self.tokens.as_ptr();
        let snd = second.tokens.as_ptr();

        (snd as usize - fst as usize) / size_of::<Token>()
    }
}

impl nom::Slice<Range<usize>> for Input<'_> {
    fn slice(&self, range: Range<usize>) -> Self {
        Input {
            tokens: &self.tokens[range],
        }
    }
}

impl nom::Slice<RangeTo<usize>> for Input<'_> {
    fn slice(&self, range: RangeTo<usize>) -> Self {
        Input {
            tokens: &self.tokens[range],
        }
    }
}

impl nom::Slice<RangeFrom<usize>> for Input<'_> {
    fn slice(&self, range: RangeFrom<usize>) -> Self {
        Input {
            tokens: &self.tokens[range],
        }
    }
}

impl nom::Slice<RangeFull> for Input<'_> {
    fn slice(&self, _: RangeFull) -> Self {
        *self
    }
}

pub fn match_text(text: &'static str) -> impl FnMut(Input) -> IResult<&Token> {
    move |i| match i.tokens.first().filter(|token| token.text() == text) {
        Some(token) => Ok((i.slice(1..), token)),
        _ => Err(nom::Err::Error(Error::from_error_kind(
            i,
            ErrorKind::ExpectText(text),
        ))),
    }
}

pub fn match_token(kind: TokenKind) -> impl FnMut(Input) -> IResult<&Token> {
    move |i| match i.tokens.first().filter(|token| token.kind == kind) {
        Some(token) => Ok((i.slice(1..), token)),
        _ => Err(nom::Err::Error(Error::from_error_kind(
            i,
            ErrorKind::ExpectToken(kind),
        ))),
    }
}

Rest follows nom-rule.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How to bridge the Span/Located functions so that we can report failed position accurately?

This has had some discussion at winnow-rs/winnow#591 (comment) (and the discussion linked to from that). I've already merged the first part of the fix for the 0.7.0 release which I'm actively working on.

My Token type is with span, while the equality is only related to compare the Kind, and possibly the text() result. The demo from this page assume Token is an owned struct without source/span like logos typically have.

This is discussed at winnow-rs/winnow#591 (comment) and I'll be working on this soon for 0.7

I will note that your solution for Nom will work just as well with Winnow until those changes are made. I hadn't considered the need for match_text. I'll need to keep that in mind.

Signed-off-by: tison <wander4096@gmail.com>
Signed-off-by: tison <wander4096@gmail.com>
Signed-off-by: tison <wander4096@gmail.com>
Signed-off-by: tison <wander4096@gmail.com>
Signed-off-by: tison <wander4096@gmail.com>
Signed-off-by: tison <wander4096@gmail.com>
Signed-off-by: tison <wander4096@gmail.com>
Signed-off-by: tison <wander4096@gmail.com>
Signed-off-by: tison <wander4096@gmail.com>
Signed-off-by: tison <wander4096@gmail.com>
@tisonkun tisonkun merged commit 0e66b80 into main Jan 6, 2025
9 checks passed
@tisonkun tisonkun deleted the impl-parser branch January 6, 2025 07:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants