extended expression
This commit is contained in:
@@ -65,7 +65,7 @@ pub enum Pattern {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
pub enum Postfix {
|
pub enum Postfix {
|
||||||
FieldAccess(Identifier, Option<Generics>), // Updated to support method turbofish chains
|
FieldAccess(Identifier, Option<Generics>),
|
||||||
Call(Vec<Expression>),
|
Call(Vec<Expression>),
|
||||||
MacroCall(String),
|
MacroCall(String),
|
||||||
StructCall(Vec<(Identifier, Expression)>),
|
StructCall(Vec<(Identifier, Expression)>),
|
||||||
|
|||||||
@@ -447,8 +447,12 @@ macro_inner_v = {
|
|||||||
// PRIMARY EXPRESSIONS
|
// PRIMARY EXPRESSIONS
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
|
|
||||||
|
expr_path_segment = {
|
||||||
|
identifier ~ ("::" ~ generics)?
|
||||||
|
}
|
||||||
|
|
||||||
expr_path = {
|
expr_path = {
|
||||||
identifier ~ ("::" ~ generics)? ~ ("::" ~ identifier ~ ("::" ~ generics)?)*
|
expr_path_segment ~ ("::" ~ expr_path_segment)*
|
||||||
}
|
}
|
||||||
|
|
||||||
primary = {
|
primary = {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
Rule,
|
Rule,
|
||||||
ast::*,
|
ast::*,
|
||||||
ast_expr,
|
ast_ensure, ast_expr,
|
||||||
error::{AstError, AstResult, GetLength, IntoErr, collect_recovered, collect_recovered_map},
|
error::{AstError, AstResult, GetLength, IntoErr, collect_recovered, collect_recovered_map},
|
||||||
};
|
};
|
||||||
use pest::pratt_parser::PrattParser;
|
use pest::pratt_parser::PrattParser;
|
||||||
@@ -15,34 +15,37 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Expression {
|
|||||||
let inner = pair.clone().into_inner();
|
let inner = pair.clone().into_inner();
|
||||||
|
|
||||||
match rule {
|
match rule {
|
||||||
// 1. The top level expressions are now processed via the Pratt Parser
|
|
||||||
Rule::expr => {
|
Rule::expr => {
|
||||||
static PRATT_PARSER: OnceLock<PrattParser<Rule>> = OnceLock::new();
|
static PRATT_PARSER: OnceLock<PrattParser<Rule>> = OnceLock::new();
|
||||||
let pratt = PRATT_PARSER.get_or_init(|| {
|
let pratt = PRATT_PARSER.get_or_init(|| {
|
||||||
use Rule::*;
|
use Rule::*;
|
||||||
use pest::pratt_parser::{Assoc::*, Op};
|
use pest::pratt_parser::{Assoc::*, Op};
|
||||||
|
|
||||||
// Precedence defined from lowest to highest
|
|
||||||
PrattParser::new()
|
PrattParser::new()
|
||||||
|
.op(Op::infix(range_inc, Left) | Op::infix(range_exc, Left))
|
||||||
.op(Op::infix(or, Left))
|
.op(Op::infix(or, Left))
|
||||||
.op(Op::infix(and, Left))
|
.op(Op::infix(and, Left))
|
||||||
.op(Op::infix(eq, Left)
|
.op(Op::infix(bitor, Left))
|
||||||
| Op::infix(neq, Left)
|
.op(Op::infix(bitxor, Left))
|
||||||
| Op::infix(lt, Left)
|
.op(Op::infix(bitand, Left))
|
||||||
| Op::infix(gt, Left)
|
.op(Op::infix(eq, Left) | Op::infix(neq, Left))
|
||||||
|
.op(Op::infix(lt, Left)
|
||||||
| Op::infix(lte, Left)
|
| Op::infix(lte, Left)
|
||||||
|
| Op::infix(gt, Left)
|
||||||
| Op::infix(gte, Left))
|
| Op::infix(gte, Left))
|
||||||
|
.op(Op::infix(shl, Left) | Op::infix(shr, Left))
|
||||||
.op(Op::infix(add, Left) | Op::infix(sub, Left))
|
.op(Op::infix(add, Left) | Op::infix(sub, Left))
|
||||||
.op(Op::infix(mul, Left) | Op::infix(div, Left) | Op::infix(rem, Left))
|
.op(Op::infix(mul, Left) | Op::infix(div, Left) | Op::infix(rem, Left))
|
||||||
});
|
});
|
||||||
|
|
||||||
pratt
|
pratt
|
||||||
.map_primary(|primary_pair| {
|
.map_primary(|primary_pair| Expression::try_from(primary_pair))
|
||||||
// Elements handled by map_primary are either sub-expressions or 'term' rules
|
|
||||||
Expression::try_from(primary_pair)
|
|
||||||
})
|
|
||||||
.map_infix(|lhs, op, rhs| {
|
.map_infix(|lhs, op, rhs| {
|
||||||
let bin_op = match op.as_rule() {
|
let bin_op = match op.as_rule() {
|
||||||
|
Rule::shl => BinaryOp::ShiftLeft,
|
||||||
|
Rule::shr => BinaryOp::ShiftRight,
|
||||||
|
Rule::range_inc => BinaryOp::RangeInclusive,
|
||||||
|
Rule::range_exc => BinaryOp::RangeExclusive,
|
||||||
Rule::lte => BinaryOp::LessThanOrEqual,
|
Rule::lte => BinaryOp::LessThanOrEqual,
|
||||||
Rule::gte => BinaryOp::GreaterThanOrEqual,
|
Rule::gte => BinaryOp::GreaterThanOrEqual,
|
||||||
Rule::eq => BinaryOp::Equal,
|
Rule::eq => BinaryOp::Equal,
|
||||||
@@ -56,6 +59,9 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Expression {
|
|||||||
Rule::rem => BinaryOp::Modulo,
|
Rule::rem => BinaryOp::Modulo,
|
||||||
Rule::lt => BinaryOp::LessThan,
|
Rule::lt => BinaryOp::LessThan,
|
||||||
Rule::gt => BinaryOp::GreaterThan,
|
Rule::gt => BinaryOp::GreaterThan,
|
||||||
|
Rule::bitand => BinaryOp::BitAnd,
|
||||||
|
Rule::bitor => BinaryOp::BitOr,
|
||||||
|
Rule::bitxor => BinaryOp::BitXor,
|
||||||
_ => return AstError::bug_unimplemented(op),
|
_ => return AstError::bug_unimplemented(op),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -130,6 +136,9 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Prefix {
|
|||||||
Rule::ref_px => Self::Ref,
|
Rule::ref_px => Self::Ref,
|
||||||
Rule::new_px => Self::New,
|
Rule::new_px => Self::New,
|
||||||
Rule::not_px => Self::Not,
|
Rule::not_px => Self::Not,
|
||||||
|
Rule::neg_px => Self::Neg,
|
||||||
|
Rule::range_start_inc_px => Self::RangeInclusive,
|
||||||
|
Rule::range_start_exc_px => Self::RangeExclusive,
|
||||||
|
|
||||||
_ => return AstError::bug_unimplemented(pair),
|
_ => return AstError::bug_unimplemented(pair),
|
||||||
})
|
})
|
||||||
@@ -147,7 +156,10 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Postfix {
|
|||||||
Rule::postfix => Postfix::try_from(inner.next().unwrap()),
|
Rule::postfix => Postfix::try_from(inner.next().unwrap()),
|
||||||
|
|
||||||
Rule::field_px => {
|
Rule::field_px => {
|
||||||
ast_expr!(Postfix::FieldAccess(inner.next().unwrap().try_into()))
|
ast_expr!(Postfix::FieldAccess(
|
||||||
|
inner.next().unwrap().try_into(),
|
||||||
|
inner.next().map(Generics::try_from).transpose()
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
Rule::call_px => ast_expr!(Postfix::Call(collect_recovered(inner))),
|
Rule::call_px => ast_expr!(Postfix::Call(collect_recovered(inner))),
|
||||||
@@ -166,9 +178,34 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Postfix {
|
|||||||
|
|
||||||
Rule::macro_call_px => Ok(Postfix::MacroCall(inner.as_str().to_string())),
|
Rule::macro_call_px => Ok(Postfix::MacroCall(inner.as_str().to_string())),
|
||||||
|
|
||||||
// Note: Rule::binary_px has been completely decoupled from postfix rules
|
|
||||||
// as it is now safely managed inside the top-level Pratt execution above.
|
|
||||||
_ => AstError::bug_unimplemented(pair),
|
_ => AstError::bug_unimplemented(pair),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for ExprPath {
|
||||||
|
type Error = AstError<'a, Self>;
|
||||||
|
|
||||||
|
fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
|
||||||
|
ast_ensure!(pair, Rule::expr_path => {
|
||||||
|
ast_expr!(ExprPath {
|
||||||
|
segments: collect_recovered(pair.into_inner()),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for ExprPathSegment {
|
||||||
|
type Error = AstError<'a, Self>;
|
||||||
|
|
||||||
|
fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
|
||||||
|
let mut inner = pair.clone().into_inner();
|
||||||
|
|
||||||
|
ast_ensure!(pair, Rule::expr_path_segment => {
|
||||||
|
ast_expr!(ExprPathSegment {
|
||||||
|
ident: Identifier::try_from(inner.next().unwrap()),
|
||||||
|
generics: inner.next().map(Generics::try_from).transpose(),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user