Reputation: 43
I'm trying to learn NOM for a project in Rust. I have a text file that consists of:
[tag="#43674"]char[/tag]
with multiple tags back to back on each line. I'm trying to pull the '#43674' and 'char', store them in a tuple (x, y)
and then push those into a vector Vec<(x, y)>
for each line of the text file.
So far I have successfully combined parsers into two functions; one for the '#43674' and one for 'char' which I then combine together to return <IResult<&str, (String, String)>
. Here is the code:
fn color_tag(i: &str) -> IResult<&str, &str> {
delimited(tag("[color="), take_until("]"), tag("]"))(i)
}
fn char_take(i: &str) -> IResult<&str, &str> {
terminated(take_until("[/color]"), tag("[/color]"))(i)
}
pub fn color_char(i: &str) -> IResult<&str, (String, String)> {
let (i, color) = color_tag(i)?;
let (i, chara) = char_take(i)?;
let colors = color.to_string();
let charas = chara.to_string();
let tuple = (colors, charas);
Ok((i, tuple))
}
How can I iterate this function over a given line of the text file? I already have a function that iterates the text file into lines, but I need color_char
to repeat for each closure in that line. Am I missing the point entirely?
Upvotes: 4
Views: 2123
Reputation: 1660
You'll probably want to use the nom::multi::many0
combinator to match a parser multiple times, and you can also use the nom::sequence::tuple
combinator to combine your color_tag and char_take parsers
// Match color_tag followed by char_take
fn color_char(i: &str) -> IResult<&str, (&str, &str)> {
tuple((color_tag, char_take))(i)
}
// Match 0 or more times on the same line
fn color_char_multiple(i: &str) -> IResult<&str, Vec<(String, String)>> {
many0(color_char)(i)
}
To parse multiple lines, you can modify color_char() to match a trailing newline character with one of the character parsers provided by nom, such as nom::character::complete::line_ending
, make it optional using nom::combinator::opt
, and combine it with something like nom::sequence::terminated
:
terminated(tuple((color_tag, char_take)), opt(line_ending))(i)
Upvotes: 5