home ~ projects ~ socials

Selecting nom Parsers Dynamically

That's probably not the best title. What I'm looking to do is have couple name parsers that I can send a set of values to that will be used as part of the match.

This is very much a work in progress trying to figure this out. This does what I want without ErrorTree next step is to try to add that in

```cargo
[dependencies]
nom = "7.1.3"
nom-supreme = "0.8.0"
```
#![allow(warnings)]
use nom::branch::alt;
use nom_supreme::error::ErrorTree;
use nom_supreme::ParserExt;
use nom::IResult;
use nom::Parser;
use nom::bytes::complete::tag;
use nom::bytes::complete::take_until;
use nom::error::Error;
use nom::error::ErrorKind;
use nom::Err;


fn main() {
  let lists = vec!["list", "notes"];
  let results = section("the list quick brown fox", &lists);
  dbg!(results);
}

fn section<'a>(source: &'a str, lists: &'a Vec<&'a str>) 
  -> IResult<&'a str, &'a str> {
  let (source, result) = list(source, lists[0])?;
  Ok((source, result))
}

fn list<'a>(source: &'a str, key: &'a str)
  -> IResult<&'a str, &'a str> {
  let lists = vec!["list", "notes"];
  let (source, result) = lists.iter().fold(
    Err(Err::Error(Error::new("initilizing-loop", ErrorKind::Tag))), 
    |acc, item| {
      match acc {
        Ok(v) => Ok(v),
        _ => list_finder(source, item)
      }
    })?;
  Ok((source, result))
}

fn list_finder<'a>(source: &'a str, key: &'a str)
  -> IResult<&'a str, &'a str> {
  let (source, _) = tag("the ").context("list_finder").parse(source)?;
  let (source, result) = tag(key).context("list_finder").parse(source)?;
  Ok((source, result))
}
Output:
[/Users/alan/.cargo/target/55/19854259915251/_active_nvim_run:22:3] results = Ok(
    (
        " quick brown fox",
        "list",
    ),
)
```cargo
[dependencies]
nom = "7.1.3"
nom-supreme = "0.8.0"
```
#![allow(warnings)]
use nom::branch::alt;
use nom_supreme::error::ErrorTree;
use nom_supreme::ParserExt;
use nom::IResult;
use nom::Parser;
use nom::bytes::complete::tag;
use nom::bytes::complete::take_until;
use nom::error::Error;
use nom::error::ErrorKind;
use nom::Err;


fn main() {
  let lists = vec!["list", "notes"];
  let results = section("the list quick brown fox", &lists);
  dbg!(results);
}

fn section<'a>(source: &'a str, lists: &'a Vec<&'a str>) 
  -> IResult<&'a str, &'a str, ErrorTree<&'a str>> {
  let (source, result) = list(source, lists[0])?;
  Ok((source, result))
}

fn list<'a>(source: &'a str, key: &'a str)
  -> IResult<&'a str, &'a str, ErrorTree<&'a str>> {
  let lists = vec!["list", "notes"];
  let (source, result) = lists.iter().fold(
  initial_error(),
    |acc, item| {
      match acc {
        Ok(v) => Ok(v),
        _ => list_finder(source, item)
      }
    })?;
  Ok((source, result))
}

fn list_finder<'a>(source: &'a str, key: &'a str)
  -> IResult<&'a str, &'a str, ErrorTree<&'a str>> {
  let (source, _) = tag("the ").context("list_finder").parse(source)?;
  let (source, result) = tag(key).context("list_finder").parse(source)?;
  Ok((source, result))
}


fn initial_error<'a>() -> IResult<&'a str, &'a str, ErrorTree<&'a str>> {
   // the purpose of this function is just to put an
   // error in the accumulator. There's a way to do that
   // with just making an error, but I haven't solved all 
   // the parts to that yet.
   let (_, _) = tag("asdf").parse("fdsa")?;
   Ok(("", ""))
}
Output:
[/Users/alan/.cargo/target/55/19854259915251/_active_nvim_run:22:3] results = Ok(
    (
        " quick brown fox",
        "list",
    ),
)
-- end of line --