Last active
May 4, 2024 15:56
-
-
Save jaytaph/02cc00f46499c6c86f90f22d8775e5ba to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern crate nom; | |
use nom::{ | |
branch::alt, | |
bytes::complete::tag, | |
character::complete::{char, multispace0}, | |
combinator::{map, recognize}, | |
multi::separated_list1, | |
sequence::delimited, | |
IResult, | |
}; | |
use nom::character::complete::alphanumeric1; | |
use nom::multi::{many1, separated_list0}; | |
#[derive(Debug)] | |
enum Component { | |
Value(String), | |
List(Vec<Component>), | |
DoubleList(Vec<Component>), | |
Group(Box<Component>), | |
} | |
fn parse_value(input: &str) -> IResult<&str, Component> { | |
println!("-> parse_value: {}", input); | |
let (input, result) = map( | |
recognize(many1(alt((alphanumeric1, tag("_"))))), // Accept alphanumeric characters and underscores | |
|s: &str| Component::Value(s.to_string()) | |
)(input)?; | |
println!("<- parse_value: {:?}", result); | |
Ok((input, result)) | |
} | |
fn parse_list_with_single_separator(input: &str) -> IResult<&str, Component> { | |
println!("-> parse_list_with_single_separator: {}", input); | |
let (input, first) = parse_group_value(input)?; | |
let (input, _) = delimited(multispace0, tag("|"), multispace0)(input)?; | |
let (input, mut rest) = separated_list0(delimited(multispace0, tag("|"), multispace0), parse_group_value)(input)?; | |
rest.insert(0, first); | |
println!("<- parse_list_with_single_separator: {:?}", rest); | |
Ok((input, Component::List(rest))) | |
} | |
fn parse_list_with_double_separator(input: &str) -> IResult<&str, Component> { | |
println!("-> parse_list_with_double_separator: {}", input); | |
let (input, first) = parse_group_value(input)?; | |
let (input, _) = delimited(multispace0, tag("||"), multispace0)(input)?; | |
let (input, mut rest) = separated_list0(delimited(multispace0, tag("||"), multispace0), parse_group_value)(input)?; | |
rest.insert(0, first); | |
println!("<- parse_list_with_double_separator: {:?}", rest); | |
Ok((input, Component::DoubleList(rest))) | |
} | |
fn parse_group(input: &str) -> IResult<&str, Component> { | |
println!("-> parse_group: {}", input); | |
let (input, result) = delimited( | |
delimited(multispace0, char('['), multispace0), | |
map(parse_expression, |c| Component::Group(Box::new(c))), | |
delimited(multispace0, char(']'), multispace0) | |
)(input)?; | |
println!("<- parse_group: {:?}", result); | |
Ok((input, result)) | |
} | |
fn parse_group_value(input: &str) -> IResult<&str, Component> { | |
println!("-> parse_group_value: {}", input); | |
let (input, result) = alt(( | |
parse_group, | |
parse_value, | |
))(input)?; | |
println!("<- parse_group_value: {:?}", result); | |
Ok((input, result)) | |
} | |
fn parse_expression(input: &str) -> IResult<&str, Component> { | |
println!("-> parse_expression: {:?}", input); | |
let (input, result) = alt(( | |
parse_list_with_double_separator, | |
parse_list_with_single_separator, | |
parse_group, | |
parse_value, | |
))(input)?; | |
println!("<- parse_expression: {:?}", result); | |
Ok((input, result)) | |
} | |
fn main() { | |
let inputs = [ | |
"123", // Component::Value("123") | |
"value1", // Component::Value("value1") | |
"value1 | value2", // Component::List([Component::Value("value1"), Component::Value("value2")]) | |
"value1 | value2 | value3", // Component::List([Component::Value("value1"), Component::Value("value2"), Component::Value("value3")]) | |
"value1 || value2 || value3", // Component::DoubleList([Component::Value("value1"), Component::Value("value2"), Component::Value("value3")]) | |
"value1 || value2 | value3", // Fail due to mixed separators | |
"[value1 | value2 ]", // Component::Group([Component::List([Component::Value("value1"), Component::Value("value2")])]) | |
"[value1 | [value2] ]", // Component::Group([Component::List([Component::Value("value1"), Component::Group([Component::Value("value2")])])]) | |
"[value1 | value2 ] || value3", // Component::DoubleList([Component::Group([Component::List([Component::Value("value1"), Component::Value("value2")])]), Component::Value("value3")]) | |
"[ [value1 | value2 ] || value3 ] | value4", | |
// Component::List([ | |
// Component::Group([ | |
// Component::DoubleList([ | |
// Component::Group( | |
// Component::List[ | |
// Component::Value("value1"), | |
// Component::Value("value2") | |
// ]), | |
// ]), | |
// Component::Value("value3")]) | |
// ]), | |
// ]), | |
// Component::Value("value4") | |
// ]) | |
]; | |
for input in inputs.iter() { | |
println!("\n\nParsing: {}", input); | |
match parse_expression(input) { | |
Ok((_, component)) => println!("Parsed successfully: {:?}", component), | |
Err(e) => println!("Failed to parse '{}': {:?}", input, e), | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment