ihl/src/parser.rs
2023-05-04 10:02:34 +02:00

53 lines
1.5 KiB
Rust

use std::collections::HashMap;
use winnow::{IResult, combinator, character::alphanumeric1, branch, sequence::delimited, multi::many0, bytes::take_until0, Parser};
use crate::{element::{Element, ElBody, ElContent}, util::ws};
pub fn el_parser(input: &str) -> IResult<&str, Element> {
(
name_parser,
combinator::opt(el_attrlist_parser),
el_body_parser,
)
.map(|(name, attributes, children)| Element {
name,
attributes,
children,
})
.parse_next(input)
}
pub fn name_parser(input: &str) -> IResult<&str, &str> {
ws(alphanumeric1).parse_next(input)
}
pub fn el_body_parser(input: &str) -> IResult<&str, ElBody> {
ws(branch::alt((
string_parser.map(|s| ElBody::Text(s)),
delimited('{', many0(content_parser).map(|v| ElBody::Elements(v)), '}'),
)))
.parse_next(input)
}
pub fn el_attrlist_parser(input: &str) -> IResult<&str, HashMap<&str, &str>> {
ws(delimited('[', many0(attribute_parser), ']')).parse_next(input)
}
pub fn attribute_parser(input: &str) -> IResult<&str, (&str, &str)> {
(name_parser, '=', ws(string_parser))
.map(|(key, _, value)| (key, value))
.parse_next(input)
}
pub fn content_parser(input: &str) -> IResult<&str, ElContent> {
ws(branch::alt((
string_parser.map(|s| ElContent::Text(s)),
el_parser.map(|e| ElContent::El(e)),
)))
.parse_next(input)
}
pub fn string_parser(input: &str) -> IResult<&str, &str> {
delimited('"', take_until0("\""), '"').parse_next(input)
}