diff --git a/src/parser/ast.rs b/src/parser/ast.rs index 35bfca5..af4f8b8 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -12,6 +12,14 @@ pub enum TypeExpr { Identifier(String), } +#[derive(Debug, Clone, Serialize)] +pub enum BinaryOp { + Plus, + Minus, + Multiply, + Divide, +} + #[derive(Debug, Clone, Serialize)] #[serde(tag = "type", content = "value")] pub enum TopLevel { @@ -34,7 +42,9 @@ pub enum TopLevel { #[serde(tag = "type", content = "value")] pub enum Postfix { FieldAccess(String), - FunctionCall(Vec), + Call(Vec), + Index(Expression), + Binary(BinaryOp, Expression), } #[derive(Debug, Clone, Serialize)] diff --git a/src/parser/grammar.pest b/src/parser/grammar.pest index a91c38d..08824db 100644 --- a/src/parser/grammar.pest +++ b/src/parser/grammar.pest @@ -95,13 +95,18 @@ primary = { } postfix = { - ("." ~ identifier) - | ("(" ~ (expr ~ ("," ~ expr)*)? ~ ")") - | ("[" ~ expr ~ "]") - | ("++" | "--") - | (("+" | "-" | "*" | "/" | "%") ~ primary) + field_px + | call_px + | index_px + | binary_px } +field_px = { "." ~ identifier } +call_px = { "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" } +index_px = { "[" ~ expr ~ "]" } +binary_px = { bin_op ~ expr } +bin_op = { "+" | "-" | "*" | "/" | "%" } + expr = { primary ~ postfix* } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index f5e2e1e..6b14585 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -320,18 +320,34 @@ impl Expression { impl Postfix { pub fn from_pair(pair: pest::iterators::Pair) -> Self { match pair.as_rule() { - Rule::postfix => { - let inner = pair.into_inner(); - if let Some(field) = inner.peek() { - if field.as_rule() == Rule::identifier { - Postfix::FieldAccess(field.as_str().to_string()) - } else { - Postfix::FunctionCall(inner.map(|p| Expression::from_pair(p)).collect()) - } - } else { - Postfix::FunctionCall(vec![]) - } + Rule::postfix => Postfix::from_pair(pair.into_inner().next().unwrap()), + + Rule::field_px => { + let field_name = pair.into_inner().next().unwrap().as_str().to_string(); + Postfix::FieldAccess(field_name) } + + Rule::call_px => Postfix::Call(pair.into_inner().map(Expression::from_pair).collect()), + + Rule::index_px => { + Postfix::Index(Expression::from_pair(pair.into_inner().next().unwrap())) + } + + Rule::binary_px => { + let mut inner = pair.into_inner(); + let op_pair = inner.next().unwrap(); + let op = match op_pair.as_str() { + "+" => BinaryOp::Plus, + "-" => BinaryOp::Minus, + "*" => BinaryOp::Multiply, + "/" => BinaryOp::Divide, + _ => { + unimplemented!("Binary operator not implemented yet: {}", op_pair.as_str()) + } + }; + Postfix::Binary(op, Expression::from_pair(inner.next().unwrap())) + } + _ => unimplemented!("Postfix parsing not implemented yet {:?}", pair.as_rule()), } }