Rust combine::Parser type

  1. This is the code I have so far:
use super::*;


use combine::error::UnexpectedParse;
use combine::parser::char::digit;
use combine::parser::choice::optional;
use combine::parser::item::item;
use combine::parser::range::recognize;
use combine::parser::repeat::{skip_many, skip_many1};
use combine::Parser;
use combine_language::{LanguageEnv, LanguageDef, Identifier};
use combine::char::{letter, alpha_num, string};
use combine::satisfy;
use crate::mma::data::Expr;
use combine::parser::combinator::{Recognize, AndThen};

mod read;

fn main() {
    let mut parser = recognize((
        skip_many1(digit::<&str>()),
        optional((item('.'), skip_many(digit())))))
        .and_then( str_to_bignum);
    let t : Parser<Input = &str, Output = Expr> = parser;
}


pub fn str_to_bignum(s: &str) -> Result<Expr, combine::error::StringStreamError> {
    unimplemented!()
}

  1. I am trying to shove the variable parser into the trait Parser

  2. I'm guessing the values for Input = &str and Output = Expr. I have no idea what to specify ro PartialState. I am getting error of:

   |
24 |     let t : Parser<Input = &str, Output = Expr> = parser;
   |         ^ doesn't have a size known at compile-time
   |
   = help: the trait `std::marker::Sized` is not implemented for `dyn combine::Parser<Output=mma::data::Expr, Input=&str>`
   = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
   = note: all local variables must have a statically known size
   = help: unsized locals are gated as an unstable feature

You're trying to own a trait object without it being behind reference/pointer of some sort. This is not allowed in local scopes. This has nothing to do with the type parameters of Parser as this is about the unsizedness of t. I recommend using a box:

let t: Box<dn Parser<Input = &str, Output = Expr> = Box::new(parser);

And then you can sort out the proper type parameters. Unravel your errors one at a time. If the compiler doesn't mention it, then that means that it hasn't gotten to that stage in compilation yet.

So now we have:

use super::*;


use combine::error::UnexpectedParse;
use combine::parser::char::digit;
use combine::parser::choice::optional;
use combine::parser::item::item;
use combine::parser::range::recognize;
use combine::parser::repeat::{skip_many, skip_many1};
use combine::Parser;
use combine_language::{LanguageEnv, LanguageDef, Identifier};
use combine::char::{letter, alpha_num, string};
use combine::satisfy;
use crate::mma::data::Expr;
use combine::parser::combinator::{Recognize, AndThen};

mod read;

fn main() {
    let mut parser = recognize((
        skip_many1(digit::<&str>()),
        optional((item('.'), skip_many(digit())))))
        .and_then( str_to_bignum);
    let t : Box<Parser<Input = &str, Output = Expr, PartialState = ()>> = Box::new(parser);
}

pub fn str_to_bignum(s: &str) -> Result<Expr, combine::error::StringStreamError> {
    unimplemented!()
}

This gives error:


   |
24 |     let t : Box<Parser<Input = &str, Output = Expr, PartialState = ()>> = Box::new(parser);
   |                                                                           ^^^^^^^^^^^^^^^^ expected tuple, found ()
   |
   = note: expected type `(usize, combine::combinator::PartialState2<combine::combinator::SequenceState<(), (bool, bool, combine::combinator::Sink, ())>, combine::combinator::SequenceState<std::option::Option<(char, ())>, combine::combinator::PartialState2<combine::combinator::SequenceState<char, ()>, combine::combinator::SequenceState<(), (combine::combinator::Sink, ())>>>>)`
              found type `()`
   = note: required for the cast to the object type `dyn combine::Parser<Output=mma::data::Expr, Input=&str, PartialState=()>`

What is going on here? why is it expecting a tuple?

Okay, I've delved into the docs for you:

recognize<T>(T)

returns a Recognize<T>, who is a Parser, and its PartialState is based off of RecognizeWithValue's PartialState which is not ().

1 Like