54 lines
1.5 KiB
Rust
54 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)
|
||
|
}
|