Skip to content

Commit

Permalink
refactor parser
Browse files Browse the repository at this point in the history
  • Loading branch information
DougAnderson444 committed Nov 3, 2024
1 parent 372fb59 commit 43d5294
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 178 deletions.
14 changes: 7 additions & 7 deletions src/egui_layout.pest
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@ WHITESPACE = _{ " " | "\t" | "\n" | "\r" }
/// Identifier (for tag names and attribute names)
identifier = @{ ASCII_ALPHA ~ (ASCII_ALPHANUMERIC | "_" | "-")* }

/// Function call
functions = { identifier ~ "(" ~ (string)* ~ ")" }

// String literals (without quotes or special chars, especially not "(" or ")")
// without quotes or special chars, especially not "(" or ")"
inner_string = @{ (!("\"" | "<" | ">" | "(" | ")") ~ ANY)+ }

/// String literals (with quotes)
/// _SILENT Rule: Doesn't produce Rule:: token. Str literals (with quotes)
string = _{ "\"" ~ inner_string ~ "\"" }

/// Function call
functions = { identifier ~ "(" ~ (string)* ~ ")" }

// Attribute cn be either a string or a function call, but musy have one of them
attribute = { identifier ~ "=" ~ (string | functions) }

/// Tag name such as "Horizontal" or "Button"
/// Non-element contents
text = { (!("<" | ">") ~ ANY)+ }

/// Open Tag such as <Horizontal>
Expand All @@ -29,4 +29,4 @@ close_tag = { "</" ~ identifier ~ ">" }
/// An entire element, such as <Horizontal> or <Button on_click="increment()">Increment</Button>
element = { open_tag ~ (element | text)* ~ close_tag }

document = { SOI ~ element ~ EOI }
document = _{ SOI ~ element ~ EOI }
209 changes: 99 additions & 110 deletions src/pest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ struct EguiLayoutParser;

#[derive(Debug, PartialEq, Clone)]
pub enum Component {
Document {
children: Vec<Component>,
},
Horizontal {
content: Option<String>,
props: HashMap<String, String>,
Expand Down Expand Up @@ -42,16 +39,6 @@ pub enum Component {
fn parse_element(pair: pest::iterators::Pair<'_, Rule>) -> Result<Component, Error> {
let span = pair.as_span();
match pair.as_rule() {
Rule::document => {
let inner = pair.clone().into_inner();
let children: Vec<Component> = inner
.filter_map(|p| match p.as_rule() {
Rule::element => Some(parse_element(p)),
_ => None,
})
.collect::<Result<_, _>>()?;
Ok(Component::Document { children })
}
Rule::element => {
let mut inner = pair.into_inner();

Expand Down Expand Up @@ -182,10 +169,22 @@ fn parse_element(pair: pest::iterators::Pair<'_, Rule>) -> Result<Component, Err
}
}

pub(crate) fn parse(input: &str) -> Result<Component, Error> {
pub(crate) fn parse(input: &str) -> Result<Vec<Component>, Error> {
let mut ast = vec![];

let pairs =
EguiLayoutParser::parse(Rule::document, input).map_err(|e| Error::Parse(Box::new(e)))?;
parse_element(pairs.peek().unwrap())

for pair in pairs {
match pair.as_rule() {

Check failure on line 179 in src/pest.rs

View workflow job for this annotation

GitHub Actions / Clippy

you seem to be trying to use `match` for an equality check. Consider using `if`
Rule::element => {
ast.push(parse_element(pair)?);
}
_ => {}
}
}

Ok(ast)
}

#[cfg(test)]
Expand All @@ -210,13 +209,11 @@ mod tests {
let res = parse(input).unwrap();
assert_eq!(
res,
Component::Document {
children: vec![Component::Horizontal {
content: None,
props: HashMap::default(),
children: vec![]
}]
}
vec![Component::Horizontal {
content: None,
props: HashMap::default(),
children: vec![]
}]
);
}

Expand All @@ -233,27 +230,25 @@ mod tests {
let res = parse(input).unwrap();
assert_eq!(
res,
Component::Document {
children: vec![Component::Horizontal {
content: None,
props: HashMap::default(),
children: vec![
Component::Button {
content: Some("Click me!".to_string()),
props: HashMap::default(),
functions: HashMap::default(),
},
Component::Vertical {
content: None,
vec![Component::Horizontal {
content: None,
props: HashMap::default(),
children: vec![
Component::Button {
content: Some("Click me!".to_string()),
props: HashMap::default(),
functions: HashMap::default(),
},
Component::Vertical {
content: None,
props: HashMap::default(),
children: vec![Component::Label {
content: "Hello, world!".to_string(),
props: HashMap::default(),
children: vec![Component::Label {
content: "Hello, world!".to_string(),
props: HashMap::default()
}]
}
]
}]
}
}]
}
]
}]
);
}

Expand All @@ -272,29 +267,27 @@ mod tests {
let res = parse(input).unwrap();
assert_eq!(
res,
Component::Document {
children: vec![Component::Horizontal {
content: None,
props: HashMap::default(),
children: vec![
Component::Button {
content: Some("Click me!".to_string()),
props: vec![("color".to_string(), "red".to_string())]
.into_iter()
.collect(),
functions: HashMap::default(),
},
Component::Vertical {
content: None,
props: HashMap::default(),
children: vec![Component::Label {
content: "Hello, world!".to_string(),
props: HashMap::default()
}]
}
]
}]
}
vec![Component::Horizontal {
content: None,
props: HashMap::default(),
children: vec![
Component::Button {
content: Some("Click me!".to_string()),
props: vec![("color".to_string(), "red".to_string())]
.into_iter()
.collect(),
functions: HashMap::default(),
},
Component::Vertical {
content: None,
props: HashMap::default(),
children: vec![Component::Label {
content: "Hello, world!".to_string(),
props: HashMap::default()
}]
}
]
}]
);
}

Expand All @@ -311,29 +304,27 @@ mod tests {
let res = parse(input).unwrap();
assert_eq!(
res,
Component::Document {
children: vec![Component::Horizontal {
content: None,
props: HashMap::default(),
children: vec![
Component::Button {
content: Some("Click me!".to_string()),
props: vec![("on_click".to_string(), "handle_click".to_string())]
.into_iter()
.collect(),
functions: HashMap::default(),
},
Component::Vertical {
content: None,
vec![Component::Horizontal {
content: None,
props: HashMap::default(),
children: vec![
Component::Button {
content: Some("Click me!".to_string()),
props: vec![("on_click".to_string(), "handle_click".to_string())]
.into_iter()
.collect(),
functions: HashMap::default(),
},
Component::Vertical {
content: None,
props: HashMap::default(),
children: vec![Component::Label {
content: "Hello, world!".to_string(),
props: HashMap::default(),
children: vec![Component::Label {
content: "Hello, world!".to_string(),
props: HashMap::default()
}]
}
]
}]
}
}]
}
]
}]
);
}

Expand All @@ -344,36 +335,34 @@ mod tests {
<Horizontal>
<Button on_click=increment()>Increment</Button>
<Vertical>
<Label>{count}</Label>
<Label>{{count}}</Label>
</Vertical>
</Horizontal>
"#;
let res = parse(input).unwrap();
assert_eq!(
res,
Component::Document {
children: vec![Component::Horizontal {
content: None,
props: HashMap::default(),
children: vec![
Component::Button {
content: Some("Increment".to_string()),
props: Default::default(),
functions: vec![("increment".to_string(), vec![])]
.into_iter()
.collect(),
},
Component::Vertical {
content: None,
vec![Component::Horizontal {
content: None,
props: HashMap::default(),
children: vec![
Component::Button {
content: Some("Increment".to_string()),
props: Default::default(),
functions: vec![("increment".to_string(), vec![])]
.into_iter()
.collect(),
},
Component::Vertical {
content: None,
props: HashMap::default(),
children: vec![Component::Label {
content: "{count}".to_string(),
props: HashMap::default(),
children: vec![Component::Label {
content: "{count}".to_string(),
props: HashMap::default()
}]
}
]
}]
}
}]
}
]
}]
);
}
}
Loading

0 comments on commit 43d5294

Please sign in to comment.