working on it (slow)

This commit is contained in:
Schrottkatze 2023-05-04 10:02:10 +02:00
parent 834049af18
commit c3642676b2

View file

@ -1,6 +1,12 @@
use std::fmt::Display; use std::{collections::HashMap, str::FromStr};
use winnow::{IResult, bytes::{take_while0, take_until0}, character::{alphanumeric1, multispace0}, error::ParseError, Parser, sequence::{delimited, preceded}, branch, combinator::todo, multi::{fold_many0, many0}}; use winnow::prelude::*;
use crate::parser::el_parser;
mod parser;
mod element;
mod util;
const TEST_IHL: &str = " const TEST_IHL: &str = "
html { html {
@ -12,7 +18,7 @@ html {
p \"this is a test file\" p \"this is a test file\"
p { p {
\"some text followed by \" \"some text followed by \"
a \"a hyperlink\" a [ href = \"https://schrottkatze.de\" ] \"a hyperlink\"
} }
} }
} }
@ -24,98 +30,23 @@ fn main() {
println!("{e}"); println!("{e}");
} }
fn el_parser(input: &str) -> IResult<&str, Element> { type Name<'a> = &'a str;
(
el_name_parser,
el_body_parser
).map(|(name, children)| Element { name, children }).parse_next(input)
}
enum Token<'a> {
fn el_name_parser(input: &str) -> IResult<&str, &str> { Name(Name<'a>),
ws(alphanumeric1).parse_next(input)
}
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)
}
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)
}
fn string_parser(input: &str) -> IResult<&str, &str> {
delimited(
'"',
take_until0("\""),
'"',
).parse_next(input)
}
#[derive(Debug)]
struct Element<'a> {
name: &'a str,
children: ElBody<'a>,
}
impl<'a> Display for Element<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "<{0}>{1}</{0}>", self.name, self.children)
}
}
/// the direct content of `children`, so it can be a plaintext element
#[derive(Debug)]
enum ElBody<'a> {
Elements(Vec<ElContent<'a>>),
Text(&'a str), Text(&'a str),
} Number(i32), // TODO: more complex number type
impl<'a> Display for ElBody<'a> { //
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { BlockBrackets(Vec<Token<'a>>), // [] block
match self { BlockBraces(Vec<Token<'a>>), // {} block
ElBody::Text(s) => f.write_str(s), BlockParentheses(Vec<Token<'a>>), // () block
ElBody::Elements(els) => els.iter().try_for_each(|e| f.write_str(&e.to_string()))
} PunctColon, // :
} PunctSemi, // ;
PunctComma, // ,
PunctDot, // .
KwItem, // `item` defines a new simple ish item type
} }
#[derive(Debug)]
enum ElContent<'a> {
El(Element<'a>),
Text(&'a str),
}
impl<'a> Display for ElContent<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ElContent::Text(s) => f.write_str(s),
ElContent::El(el) => f.write_str(&el.to_string())
}
}
}
#[test]
fn parse_basic() {
}
// whitespace combinator from [winnow docs](https://docs.rs/winnow/latest/winnow/_topic/language/index.html#wrapper-combinators-that-eat-whitespace-before-and-after-a-parser)
fn ws<'a, F, O, E: ParseError<&'a str>>(inner: F) -> impl Parser<&'a str, O, E>
where
F: Parser<&'a str, O, E>,
{
delimited(
multispace0,
inner,
multispace0
)
}