GithubHelp home page GithubHelp logo

Comments (16)

Marwes avatar Marwes commented on July 20, 2024

You can look at the json parser and gluon parser. Though if you do not need to share state between the parsers you can omit the structure passed as &self.

fn parse_ident(&self, input: I) -> ParseResult<Id, I> {
    self.parser(ParserEnv::<I, F>::parse_ident2)
        .map(|x| x.0)
        .parse_stream(input)
}

Basically just wrap the parser in a function with the signature for parser and within that function just call parse_stream. With some extra work do it like integer in the json parser. By calling parse_lazy you tell the parser to delay emitting error messages so the integer wraps the parser(integer_) (which does not emit an error) into parser(integer_).expected("integer") to ensure that the error message actual displays what was expected. I can try to explain parse_lazy in a better way if you want but most of the time you don't need to worry about it. It should just be relevant in hot loops.

from combine.

Marwes avatar Marwes commented on July 20, 2024

This is something impl Trait will make much nicer eventually (and with maximum performance as well). It might be possible to add some macros to make this nicer as well.

from combine.

Yamakaky avatar Yamakaky commented on July 20, 2024

I see. Will there be performance difference with using local variables like in the example?

    let integer = spaces()
        //parse a string of digits into an i32
        .with(many1(digit()).map(|string: String| string.parse::<i32>().unwrap()));

    //Parse integers separated by commas, skipping whitespace
    let mut integer_list = sep_by(integer, spaces().skip(char(',')));

I didn't need shared state for the nom parser, so free functions should be fine.

from combine.

Marwes avatar Marwes commented on July 20, 2024

Nope, there should be no difference at all.

from combine.

Yamakaky avatar Yamakaky commented on July 20, 2024

Cool!

from combine.

Yamakaky avatar Yamakaky commented on July 20, 2024

I started the implementation: https://github.com/Yamakaky/dcpu/blob/combine/src/assembler/parser/combine_parser.rs
It doesn't compile and PN and SN are dummy type declarations. Could you quickly review it?

from combine.

Marwes avatar Marwes commented on July 20, 2024

Since you take a &str as input you may want to consider using range (zero-copy) parsers https://docs.rs/combine/2.0.0/combine/range/index.html (which I now realize I have forgotten to add doc comments on, they have examples at least) . Also, since you use boxed parsers you may want to be careful so you don't recreate the parser to often (harming performance). But of course always profile before optimizing. Otherwise it looks as I would expect! 👍

from combine.

Yamakaky avatar Yamakaky commented on July 20, 2024

I tried boxed parser since I didn't really know how to return one otherwise...

from combine.

Marwes avatar Marwes commented on July 20, 2024

Ah, sorry. The way to "return" a parser without boxing right now is to write roughly

fn pos_number(input: &str) -> ParseResult<&str, int> {
    raw_number().and_then(|(digits, base)| u16::from_str_radix(digits,
                                                                    base)).parse_stream(input)
}

// Use pos_number
parser(pos_number).parse("abc");

That way the type is hidden by the function.

from combine.

Yamakaky avatar Yamakaky commented on July 20, 2024

Does your pos_number work with Or?

from combine.

Marwes avatar Marwes commented on July 20, 2024

Yep, parser is just a way to make a Parser from a function.

from combine.

Marwes avatar Marwes commented on July 20, 2024

Alternatively, with a bit more boilerplate you could write this.

fn pos_number() -> Expected<FnParser<fn (&str) -> ParseResult<&str, int>>> {
    parser(pos_number_).expected("positive number")
}
fn pos_number_(input: &str) -> ParseResult<&str, int> {
    raw_number().and_then(|(digits, base)| u16::from_str_radix(digits,
                                                                    base)).parse_lazy(input)
}

pos_number().parse("abc");

By calling parse_lazy over parse_stream it becomes slightly more efficient if pos_number are used in or. This is because the parser holds off on generating error information for as long as possible until an entire chain of or parsers has failed.

Making a note to properly explain how this works somewhere in the documentation

from combine.

Yamakaky avatar Yamakaky commented on July 20, 2024

Make an other note: generate pos_number using a macro ^^

from combine.

Marwes avatar Marwes commented on July 20, 2024

Perhaps. That would work in this case but it would not be possible to define a parser that was generic if it were a macro. Most of my own parsers are generic which is why I haven't added it.

fn pos_number<I>() -> Expected<FnParser<fn (I) -> ParseResult<I, int>>> where I : Stream<Item = char> {
    parser(pos_number_).expected("positive number")
}
fn pos_number_<I>(input: I) -> ParseResult<I, int> where I : Stream<Item = char> {
    raw_number().and_then(|(digits, base)| u16::from_str_radix(digits,
                                                                    base)).parse_lazy(input)
}

from combine.

Marwes avatar Marwes commented on July 20, 2024

Had a thought, as long as the parsers are not incredibly complex or mutually recursive an easy way to get re-usability could be to use macros which produce parsers.

macro_rules! pos_number {
    () => { raw_number().and_then(|(digits, base)| u16::from_str_radix(digits, base)) }
}

pos_number!().parse_*(input)

from combine.

Yamakaky avatar Yamakaky commented on July 20, 2024

why not ^^

from combine.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.