Help writing rust/combine 'lexeme' combinator

#1
  1. This is what I have so far:
use combine::char::spaces;


pub fn lexeme<'a, O>(p: Parser<Input=&'a str, Output = O>) -> impl Parser<Input = &'a str, Output = O>
{
    let mut parser =
        (p, spaces())
            .and_then(|x, _| x);
    parser
}

  1. This is the error I am getting:
   |
14 | pub fn lexeme<'a, O>(p: Parser<Input=&'a str, Output = O>) -> impl Parser<Input = &'a str, Output = O>
   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing associated type `PartialState` value

error: aborting due to previous error
  1. What I am trying to do is to write “combinator” which (1) takes a Parser as input, (2) runs the Parser, (3) comsumes as much whitespace as it can, and (3) returns result of original Parsedr.

  2. It appears I am running into this “PartialState” problem of figuring out what to feed it.

0 Likes

#2

Okay, two questions:

  1. Is this related to the previous question surrounding PartialState?
  2. Do you really care what the partial state is?

Also, a note, p cannot be the type of a trait, as it is an unsized object and can therefore not be stored on the stack. I’d recommend using a box.

1 Like

#3

I don’t know if it’s related to the previous PartialState. No, I don’t care what the PartialState is.

Here’s the XY problem:

I’m familiar with Parsec. I’m trying to write a basic parser in Combine, and the type checker has beeh fighting me all the way. The only thing I care about is the following (and anyway to solve it is fine).

I want to write a “combinator”. This combinator takes a Parser P as an input, then it returns a new Parser P’. What does P’ do? It runs P, consumes as much whitespace as it can, then returns the value of P.

0 Likes

#4

Well, if you don’t really care, you can just leave it up to the caller:

pub fn lexeme<'a, O, P>(p: Parser<Input=&'a str, Output = O, PartialState = P>) -> impl Parser<Input = &'a str, Output = O>
{
    let mut parser =
        (p, spaces())
            .and_then(|x, _| x);
    parser
}
1 Like

#5

I’m getting error:

   |
29 |             .and_then(|x, _| x);
   |              ^^^^^^^^
   |
   = note: the method `and_then` exists but the following trait bounds were not satisfied:
           `(&dyn combine::parser::Parser<Output=O, Input=&str, PartialState=PS>, combine::parser::char::Spaces<_>) : combine::parser::Parser`
           `&mut (&dyn combine::parser::Parser<Output=O, Input=&'a str, PartialState=PS>, combine::parser::char::Spaces<_>) : combine::parser::Parser`
0 Likes

#6

I’m also not sure what to fill in for the _ in Space<_>

0 Likes

#7

I’m completely inexperienced in combine, but perhaps one of these methods would work?

etc. These can be found under Parser’s definition. They seem to do something like what you want to do, they take a parser, and work with it somehow.

1 Like

#8

@OptimisticPeach : I apprecaite your efforts, but I really need to literally write this lexeme function.

I’m writing a “serious” (probably ~1000 LOC) parser in combine. The problem I have with combine so far is that I can run their examples, but I can’t decompose + recombine them – which prevents me from refactoring / building abstractions.

Thus, it’s really important to me to “bulldonze” through these type errors instead of “dance around” them via writing an expression using builtins.

0 Likes

#9

Ah, then perhaps someone more experienced in combine would be appropriate to help.

1 Like