Skip to content

Instantly share code, notes, and snippets.

@ducaale
Last active March 1, 2021 23:09
Show Gist options
  • Save ducaale/5d3a3df08a39d128eedab362aac34850 to your computer and use it in GitHub Desktop.
Save ducaale/5d3a3df08a39d128eedab362aac34850 to your computer and use it in GitHub Desktop.
Using nom for parsing Json path
[package]
name = "nom-test"
version = "0.1.0"
authors = ["ducaale <sharaf.13@hotmail.com>"]
edition = "2018"
[dependencies]
nom="6"
use nom::{IResult, combinator::map};
use nom::combinator::recognize;
use nom::bytes::complete::{take_while, take_till1, tag};
use nom::sequence::{preceded, pair, delimited};
use nom::character::complete::{satisfy, char};
use nom::multi::many0;
use nom::branch::alt;
fn main() {
let input = "key.abc[hello.everyone.3.2][].world";
json_path(input).unwrap();
println!("Hello, world!");
}
fn start_identifier(c: char) -> bool {
c.is_ascii_alphabetic() || c == '$' || c == '_'
}
fn part_identifier(c: char) -> bool {
c.is_ascii_alphanumeric() || c == '$' || c == '_'
}
fn valid_identifier(input: &str) -> IResult<&str, &str> {
recognize(
pair(
satisfy(start_identifier),
take_while(part_identifier)
)
)
(input)
}
fn dot_access(input: &str) -> IResult<&str, &str> {
preceded(char('.'), valid_identifier)(input)
}
fn bracket_access(input: &str) -> IResult<&str, &str> {
delimited(char('['), take_till1(|c| c == ']'), char(']'))(input)
}
fn array_access(input: &str) -> IResult<&str, &str> {
tag("[]")(input)
}
fn json_path(input: &str) -> IResult<&str, Vec<&str>> {
let parser = pair(
valid_identifier,
many0(alt((dot_access, bracket_access, array_access)))
);
map(parser, |(head, mut tail)| {
let mut t = vec![head];
t.append(&mut tail);
t
})(input)
}
#[test]
fn test_bool() {
let input = "key.abc[hello\\=world][].world";
assert_eq!(
json_path(input),
Ok(("", vec!["key", "abc", "hello\\=world", "[]", "world"]))
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment