Skip to content

Instantly share code, notes, and snippets.

@lmammino
Last active January 9, 2023 22:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lmammino/0c3e7e6dbaf41303d1059c6a279c59d1 to your computer and use it in GitHub Desktop.
Save lmammino/0c3e7e6dbaf41303d1059c6a279c59d1 to your computer and use it in GitHub Desktop.
Simple example of using nom, Rust parser combinator
[package]
name = "learning-nom"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nom = "7.1.2"
// src/main.rs
use nom::{
branch::permutation,
bytes::complete::tag_no_case,
character::complete::{alpha1, digit1, space0},
combinator::{map_res, opt},
sequence::tuple,
IResult,
};
#[derive(Debug)]
struct Person {
name: String,
age: u8,
language: String,
}
fn and_parser(input: &str) -> IResult<&str, ()> {
let (input, _) = opt(tag_no_case(" and "))(input)?;
Ok((input, ()))
}
fn age_parser(input: &str) -> IResult<&str, u8> {
let (input, _) = and_parser(input)?;
let (input, _) = tuple((space0, tag_no_case("i am ")))(input)?;
let (input, age) = map_res(digit1, |x: &str| x.parse::<u8>())(input)?;
let (input, _) = tag_no_case(" years old")(input)?;
Ok((input, age))
}
fn language_parse(input: &str) -> IResult<&str, String> {
let (input, _) = and_parser(input)?;
let (input, _) = tuple((space0, tag_no_case("i like ")))(input)?;
let (input, language) = alpha1(input)?;
Ok((input, language.to_string()))
}
fn name_parser(input: &str) -> IResult<&str, String> {
let (input, _) = and_parser(input)?;
let (input, _) = tuple((space0, tag_no_case("my name is ")))(input)?;
let (input, name) = alpha1(input)?;
Ok((input, name.to_string()))
}
fn parse_person(input: &str) -> IResult<&str, Person> {
let (input, _) = tag_no_case("Hello, ")(input)?;
let (input, (name, age, language)) =
permutation((name_parser, age_parser, language_parse))(input)?;
Ok((
input,
Person {
name,
age,
language,
},
))
}
fn main() {
let testdata = [
"Hello, my name is Tommaso and i am 32 years old and I like Rust",
"Hello, my name is Roberto and i like Python and I am 44 years old",
"Hello, I like JavaScript my name is Luciano I am 35 years old",
];
for input in testdata.iter() {
let (_, person) = parse_person(input).unwrap();
println!("{:?}", person);
}
// Outputs:
// Person { name: "Tommaso", age: 32, language: "Rust" }
// Person { name: "Roberto", age: 44, language: "Python" }
// Person { name: "Luciano", age: 35, language: "JavaScript" }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment