Skip to content

Instantly share code, notes, and snippets.

@Lucretiel
Created November 24, 2021 00:12
Show Gist options
  • Save Lucretiel/094c5912ff354e0d7150eb8679fcfaa8 to your computer and use it in GitHub Desktop.
Save Lucretiel/094c5912ff354e0d7150eb8679fcfaa8 to your computer and use it in GitHub Desktop.
An example nom parser for reddit
use nom::{
branch::alt,
character::complete::{alpha1, char, digit1, multispace1},
combinator::eof,
IResult, Parser,
};
use nom_supreme::{error::ErrorTree, multi::collect_separated_terminated, ParserExt};
#[derive(Debug, Clone)]
struct Structure<'a> {
id: i64,
items: Vec<Item<'a>>,
text_content: &'a str,
}
#[derive(Debug, Clone)]
enum Item<'a> {
String(&'a str),
Structure(Structure<'a>),
}
/// Parse a numeric id for a structure
fn parse_id(input: &str) -> IResult<&str, i64, ErrorTree<&str>> {
digit1.parse_from_str().parse(input)
}
/// Parse an alphabetic string item
fn parse_string(input: &str) -> IResult<&str, &str, ErrorTree<&str>> {
alpha1.parse(input)
}
/// Parse any item, which is either a string or a structure
fn parse_item(input: &str) -> IResult<&str, Item<'_>, ErrorTree<&str>> {
alt((
parse_string.map(Item::String),
parse_structure.map(Item::Structure),
))
.parse(input)
}
/// Parse a structure
fn parse_structure(input: &str) -> IResult<&str, Structure<'_>, ErrorTree<&str>> {
parse_id
.preceded_by(char('<'))
.terminated(char('|'))
.and(collect_separated_terminated(
parse_item,
multispace1,
char('>'),
))
.with_recognized()
.map(|(text_content, (id, items))| Structure {
id,
items,
text_content,
})
.parse(input)
}
/// Parse a bunch of items, terminated by eof, separated by whitespace
fn parse_item_list(input: &str) -> IResult<&str, Vec<Item<'_>>, ErrorTree<&str>> {
collect_separated_terminated(parse_item, multispace1, eof).parse(input)
}
fn main() {
let data = "<1|hello <2|foo> world> bar <3|baz>";
let (_tail, parsed) = parse_item_list
.all_consuming()
.complete()
.parse(data)
.unwrap();
println!("{:#?}", parsed);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment