commit 242584f470897d51dae5b68e1525cffdb2718cbf Author: Logan Date: Wed Jul 24 13:15:58 2024 -0500 Initial diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..0561a19 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "maud" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..db9aed5 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "maud" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..d03de6a --- /dev/null +++ b/src/main.rs @@ -0,0 +1,94 @@ +// Explicit tag +// a#id."a b c" href="/" [disabled rowspan=2] {"foo"} + +// Implicit tag +// h1 a#id."a b c" href="/" {"foo"}; + +type Offset = usize; +type Parse<'a> = (&'a str, &'a str, Offset); +type MaybeParse<'a> = Option>; + +fn parse_until(i: &str, condition: impl Fn(char) -> bool) -> Parse { + i.chars() + .position(condition) + .map(|pos| (&i[..pos], &i[pos..], pos)) + .unwrap_or((&i, "", i.len())) +} + +fn parse_ws(i: &str) -> Parse { parse_until(i, |c| !c.is_whitespace()) } + +fn parse_char(i: &str, matches: char) -> MaybeParse { + if let Some(c) = i.chars().next() { + if c == matches { + return Some((&i[0..1], &i[1..], 1)); + } + } + None +} + +fn not_empty(parse: Parse) -> MaybeParse { + if !parse.0.is_empty() { + Some(parse) + } else { + None + } +} + +fn parse_string(i: &str) -> MaybeParse { + let mut skip = false; + let (_, i, o1) = parse_char(i, '"')?; + let mut o2 = 0; + for c in i.chars() { + if skip { + skip = false; + } else if c == '\\' { + skip = true; + } else if c == '"' { + let off = o1 + o2 - 1; + return Some((&i[..off], &i[off..], off)); + } + o2 += 1; + } + None +} + +fn parse_name(i: &str) -> MaybeParse { + let (name, i, o1) = not_empty(parse_until(i, |c| c.is_whitespace()))?; + let (_, i, o2) = parse_ws(i); + Some((name, i, o1 + o2)) +} + +fn parse_id(i: &str) -> MaybeParse { + let (_, i, o1) = parse_char(i, '#')?; + let (_, i, o2) = parse_ws(i); + let (id, i, o3) = parse_name(i)?; + let (_, i, o4) = parse_ws(i); + Some((id, i, o1 + o2 + o3 + o4)) +} + +fn parse_classes(i: &str) -> MaybeParse { + let (_, i, o1) = parse_char(i, '.')?; + let (_, i, o2) = parse_ws(i); + let (classes, i, o3) = parse_string(i)?; + let (_, i, o4) = parse_ws(i); + Some((classes, i, o1 + o2 + o3 + o4)) +} + +fn parse_tag(i: &str) -> Option<()> { + let (name, i, o1) = parse_name(i)?; + let (id, i, o2) = parse_id(i).unwrap_or(("", i, 0)); + let (classes, i, o3) = parse_classes(i).unwrap_or(("", i, 0)); + Some(()) +} + +fn parse(i: &str) { + let mut explicit_stack: Vec<&str> = vec![]; + let mut inline_stack: Vec<&str> = vec![]; + let mut out = String::new(); + let mut off = 0; +} + +fn main() { + let p = parse_classes(".\"a b c\""); + println!("{:?}", p); +}