Skip to content

Instantly share code, notes, and snippets.

@sshine
Last active September 26, 2022 22:36
Show Gist options
  • Save sshine/f43fb1b6d497d3f845e4a0d0cfc91fc2 to your computer and use it in GitHub Desktop.
Save sshine/f43fb1b6d497d3f845e4a0d0cfc91fc2 to your computer and use it in GitHub Desktop.
use nom::bytes::complete::*;
use nom::error::ParseError;
use nom::sequence::tuple;
use nom::InputTakeAtPosition;
use nom::{error::VerboseError, IResult};
fn main() {
let a: ParseResult<()> = skip_whitespace(" hello");
println!("Parse result: {:?}", a);
}
/// Given two parsers, `parser_a` and `parser_b`, the parser `before(parser_a, parser_b)`
/// first runs `parser_a` and stores its result, runs `parser_b` and discards its result,
/// and then returns `parser_a`'s result.
fn before<I, OA, PA, OB, PB, E>(parser_a: PA, parser_b: PB) -> impl Fn(I) -> IResult<I, OA, E>
where
PA: Fn(I) -> IResult<I, OA, E>,
PB: Fn(I) -> IResult<I, OB, E>,
{
move |s: I| {
let (s, a) = parser_a(s)?;
let (s, _) = parser_b(s)?;
Ok((s, a))
}
}
/// Given two parsers, `parser_a` and `parser_b`, the parser `before(parser_a, parser_b)`
/// first runs `parser_a` and discards its result, runs `parser_b` and returns its result.
fn after<I, OA, PA, OB, PB, E>(parser_a: PA, parser_b: PB) -> impl Fn(I) -> IResult<I, OB, E>
where
PA: Fn(I) -> IResult<I, OA, E>,
PB: Fn(I) -> IResult<I, OB, E>,
{
move |s: I| {
let (s, _) = parser_a(s)?;
let (s, b) = parser_b(s)?;
Ok((s, b))
}
}
/// Given a parser, `parser`, the parser `lexeme(parser)` first runs `parser`, then skips
/// whitespace, and then returns `parser`'s result.
fn lexeme<I, O, P, E>(parser: P) -> impl Fn(I) -> IResult<I, O, E>
where
P: Fn(I) -> IResult<I, O, E>,
E: ParseError<I>,
I: InputTakeAtPosition<Item = char>,
{
before(parser, skip_whitespace)
}
fn discard<I, O, P, E>(parser: P) -> impl Fn(I) -> IResult<I, (), E>
where
P: Fn(I) -> IResult<I, O, E>,
E: ParseError<I>,
I: InputTakeAtPosition<Item = char>,
{
after(parser, |s: I| Ok((s, ())))
}
type ParseResult<'a, T> = IResult<&'a str, T, VerboseError<&'a str>>;
fn skip_whitespace<I, E>(s: I) -> IResult<I, (), E>
where
I: InputTakeAtPosition<Item = char>,
E: ParseError<I>,
{
let (s, _) = take_while(|c: char| c.is_whitespace())(s)?;
Ok((s, ()))
}
fn parse_comment(s: &str) -> IResult<&str, (), nom::Err<nom::error::Error<&str>>> {
before(tag("#"), skip_whitespace)
// let (s, _) = tag("#")(s)?;
// let (s, _) = take_until(|c: char| c == '\n')(s)?;
// let (s, _) = tag("\n")?;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment