mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
REFACTOR: Unify the Binary Operator AST data structures.
This commit is contained in:
parent
2b7c8e65f8
commit
fb292b4684
@ -286,6 +286,7 @@ macro_rules! make_selector {
|
||||
#[derive(PartialEq, Clone)]
|
||||
pub struct SelectorList {
|
||||
pub head: Box<Expression>,
|
||||
// TODO This should now work more like a binary operator. Perhaps move into the precendence parser code?
|
||||
pub tail: Option<Vec<Token>>,
|
||||
}
|
||||
|
||||
@ -579,10 +580,6 @@ impl MacroDef {
|
||||
stack.push(&bexpr.left);
|
||||
stack.push(&bexpr.right);
|
||||
}
|
||||
&Expression::Compare(ref cexpr) => {
|
||||
stack.push(&cexpr.left);
|
||||
stack.push(&cexpr.right);
|
||||
}
|
||||
&Expression::Grouped(ref expr) => {
|
||||
stack.push(expr);
|
||||
}
|
||||
@ -644,26 +641,14 @@ pub enum BinaryExprType {
|
||||
Sub,
|
||||
Mul,
|
||||
Div,
|
||||
}
|
||||
|
||||
/// CompareType signals the type of a comparison for a binary expression.
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum CompareType {
|
||||
// Comparison
|
||||
Equal,
|
||||
GT,
|
||||
LT,
|
||||
NotEqual,
|
||||
GTEqual,
|
||||
LTEqual,
|
||||
}
|
||||
|
||||
/// ComparisonDef Represents a comparison between two expressions.
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct ComparisonDef {
|
||||
pub kind: CompareType,
|
||||
pub left: Box<Expression>,
|
||||
pub right: Box<Expression>,
|
||||
pub pos: Position,
|
||||
// TODO DOT Selector operator
|
||||
}
|
||||
|
||||
/// Represents an expression with a left and a right side.
|
||||
@ -759,7 +744,6 @@ pub enum Expression {
|
||||
|
||||
// Binary expressions
|
||||
Binary(BinaryOpDef),
|
||||
Compare(ComparisonDef),
|
||||
|
||||
// Complex Expressions
|
||||
Copy(CopyDef),
|
||||
@ -779,7 +763,6 @@ impl Expression {
|
||||
match self {
|
||||
&Expression::Simple(ref v) => v.pos(),
|
||||
&Expression::Binary(ref def) => &def.pos,
|
||||
&Expression::Compare(ref def) => &def.pos,
|
||||
&Expression::Copy(ref def) => &def.pos,
|
||||
&Expression::Grouped(ref expr) => expr.pos(),
|
||||
&Expression::Format(ref def) => &def.pos,
|
||||
@ -801,9 +784,6 @@ impl fmt::Display for Expression {
|
||||
&Expression::Binary(_) => {
|
||||
write!(w, "<Expr>")?;
|
||||
}
|
||||
&Expression::Compare(_) => {
|
||||
write!(w, "<Expr>")?;
|
||||
}
|
||||
&Expression::ListOp(_) => {
|
||||
write!(w, "<Expr>")?;
|
||||
}
|
||||
|
@ -866,20 +866,12 @@ impl<'a> FileBuilder<'a> {
|
||||
&BinaryExprType::Sub => self.subtract_vals(&def.pos, left, right),
|
||||
&BinaryExprType::Mul => self.multiply_vals(&def.pos, left, right),
|
||||
&BinaryExprType::Div => self.divide_vals(&def.pos, left, right),
|
||||
}
|
||||
}
|
||||
|
||||
fn eval_compare(&mut self, def: &ComparisonDef, scope: &Scope) -> Result<Rc<Val>, Box<Error>> {
|
||||
let kind = &def.kind;
|
||||
let left = self.eval_expr(&def.left, scope)?;
|
||||
let right = self.eval_expr(&def.right, scope)?;
|
||||
match kind {
|
||||
&CompareType::Equal => self.do_deep_equal(&def.pos, left, right),
|
||||
&CompareType::GT => self.do_gt(&def.pos, left, right),
|
||||
&CompareType::LT => self.do_lt(&def.pos, left, right),
|
||||
&CompareType::GTEqual => self.do_gtequal(&def.pos, left, right),
|
||||
&CompareType::LTEqual => self.do_ltequal(&def.pos, left, right),
|
||||
&CompareType::NotEqual => self.do_not_deep_equal(&def.pos, left, right),
|
||||
&BinaryExprType::Equal => self.do_deep_equal(&def.pos, left, right),
|
||||
&BinaryExprType::GT => self.do_gt(&def.pos, left, right),
|
||||
&BinaryExprType::LT => self.do_lt(&def.pos, left, right),
|
||||
&BinaryExprType::GTEqual => self.do_gtequal(&def.pos, left, right),
|
||||
&BinaryExprType::LTEqual => self.do_ltequal(&def.pos, left, right),
|
||||
&BinaryExprType::NotEqual => self.do_not_deep_equal(&def.pos, left, right),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1247,7 +1239,6 @@ impl<'a> FileBuilder<'a> {
|
||||
match expr {
|
||||
&Expression::Simple(ref val) => self.eval_value(val, scope),
|
||||
&Expression::Binary(ref def) => self.eval_binary(def, scope),
|
||||
&Expression::Compare(ref def) => self.eval_compare(def, scope),
|
||||
&Expression::Copy(ref def) => self.eval_copy(def, scope),
|
||||
&Expression::Grouped(ref expr) => self.eval_expr(expr, scope),
|
||||
&Expression::Format(ref def) => self.eval_format(def, scope),
|
||||
|
@ -277,6 +277,8 @@ make_fn!(
|
||||
make_fn!(
|
||||
value<SliceIter<Token>, Value>,
|
||||
either!(
|
||||
// TODO This should move to op_expression instead of a value now.
|
||||
// We probably still need a bareword parser though?
|
||||
trace_parse!(selector_value),
|
||||
trace_parse!(compound_value),
|
||||
trace_parse!(boolean_value),
|
||||
@ -426,6 +428,7 @@ make_fn!(
|
||||
copy_expression<SliceIter<Token>, Expression>,
|
||||
do_each!(
|
||||
pos => pos,
|
||||
// TODO This should become just a bareword symbol now
|
||||
selector => trace_parse!(selector_list),
|
||||
_ => punct!("{"),
|
||||
fields => optional!(trace_parse!(field_list)),
|
||||
@ -635,6 +638,7 @@ make_fn!(
|
||||
|
||||
fn call_expression(input: SliceIter<Token>) -> Result<SliceIter<Token>, Expression> {
|
||||
let parsed = do_each!(input.clone(),
|
||||
// TODO This should become just a bareword symbol now
|
||||
callee_name => trace_parse!(selector_value),
|
||||
_ => punct!("("),
|
||||
args => optional!(separated!(punct!(","), trace_parse!(expression))),
|
||||
@ -723,6 +727,7 @@ make_fn!(
|
||||
do_each!(_ => word!("map"), (ListOpType::Map)),
|
||||
do_each!(_ => word!("filter"), (ListOpType::Filter))
|
||||
),
|
||||
// TODO This should become just a bareword symbol now
|
||||
macroname => trace_parse!(selector_value),
|
||||
list => trace_parse!(non_op_expression),
|
||||
(tuple_to_list_op(&input, optype, macroname, list).unwrap())
|
||||
|
@ -24,8 +24,7 @@ use crate::ast::*;
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum Element {
|
||||
Expr(Expression),
|
||||
MathOp(BinaryExprType),
|
||||
CompareOp(CompareType),
|
||||
Op(BinaryExprType),
|
||||
}
|
||||
|
||||
make_fn!(
|
||||
@ -33,16 +32,16 @@ make_fn!(
|
||||
either!(
|
||||
do_each!(
|
||||
_ => punct!("+"),
|
||||
(Element::MathOp(BinaryExprType::Add))),
|
||||
(Element::Op(BinaryExprType::Add))),
|
||||
do_each!(
|
||||
_ => punct!("-"),
|
||||
(Element::MathOp(BinaryExprType::Sub))),
|
||||
(Element::Op(BinaryExprType::Sub))),
|
||||
do_each!(
|
||||
_ => punct!("*"),
|
||||
(Element::MathOp(BinaryExprType::Mul))),
|
||||
(Element::Op(BinaryExprType::Mul))),
|
||||
do_each!(
|
||||
_ => punct!("/"),
|
||||
(Element::MathOp(BinaryExprType::Div)))
|
||||
(Element::Op(BinaryExprType::Div)))
|
||||
)
|
||||
);
|
||||
|
||||
@ -76,7 +75,7 @@ fn parse_sum_operator(i: SliceIter<Element>) -> Result<SliceIter<Element>, Binar
|
||||
));
|
||||
}
|
||||
let el = i_.next();
|
||||
if let Some(&Element::MathOp(ref op)) = el {
|
||||
if let Some(&Element::Op(ref op)) = el {
|
||||
match op {
|
||||
&BinaryExprType::Add => {
|
||||
return Result::Complete(i_.clone(), op.clone());
|
||||
@ -121,7 +120,7 @@ fn parse_product_operator(i: SliceIter<Element>) -> Result<SliceIter<Element>, B
|
||||
));
|
||||
}
|
||||
let el = i_.next();
|
||||
if let Some(&Element::MathOp(ref op)) = el {
|
||||
if let Some(&Element::Op(ref op)) = el {
|
||||
match op {
|
||||
&BinaryExprType::Mul => {
|
||||
return Result::Complete(i_.clone(), op.clone());
|
||||
@ -201,34 +200,19 @@ make_fn!(
|
||||
)
|
||||
);
|
||||
|
||||
// TODO(jwall): Change comparison operators to use the do_binary_expr! with precedence?
|
||||
fn tuple_to_compare_expression(
|
||||
kind: CompareType,
|
||||
left: Expression,
|
||||
right: Expression,
|
||||
) -> Expression {
|
||||
let pos = left.pos().clone();
|
||||
Expression::Compare(ComparisonDef {
|
||||
kind: kind,
|
||||
left: Box::new(left),
|
||||
right: Box::new(right),
|
||||
pos: pos,
|
||||
})
|
||||
}
|
||||
|
||||
make_fn!(
|
||||
compare_op_type<SliceIter<Token>, Element>,
|
||||
either!(
|
||||
do_each!(_ => punct!("=="), (Element::CompareOp(CompareType::Equal))),
|
||||
do_each!(_ => punct!("!="), (Element::CompareOp(CompareType::NotEqual))),
|
||||
do_each!(_ => punct!("<="), (Element::CompareOp(CompareType::LTEqual))),
|
||||
do_each!(_ => punct!(">="), (Element::CompareOp(CompareType::GTEqual))),
|
||||
do_each!(_ => punct!("<"), (Element::CompareOp(CompareType::LT))),
|
||||
do_each!(_ => punct!(">"), (Element::CompareOp(CompareType::GT)))
|
||||
do_each!(_ => punct!("=="), (Element::Op(BinaryExprType::Equal))),
|
||||
do_each!(_ => punct!("!="), (Element::Op(BinaryExprType::NotEqual))),
|
||||
do_each!(_ => punct!("<="), (Element::Op(BinaryExprType::LTEqual))),
|
||||
do_each!(_ => punct!(">="), (Element::Op(BinaryExprType::GTEqual))),
|
||||
do_each!(_ => punct!("<"), (Element::Op(BinaryExprType::LT))),
|
||||
do_each!(_ => punct!(">"), (Element::Op(BinaryExprType::GT)))
|
||||
)
|
||||
);
|
||||
|
||||
fn parse_compare_operator(i: SliceIter<Element>) -> Result<SliceIter<Element>, CompareType> {
|
||||
fn parse_compare_operator(i: SliceIter<Element>) -> Result<SliceIter<Element>, BinaryExprType> {
|
||||
let mut i_ = i.clone();
|
||||
if eoi(i_.clone()).is_complete() {
|
||||
return Result::Fail(Error::new(
|
||||
@ -237,9 +221,21 @@ fn parse_compare_operator(i: SliceIter<Element>) -> Result<SliceIter<Element>, C
|
||||
));
|
||||
}
|
||||
let el = i_.next();
|
||||
if let Some(&Element::CompareOp(ref op)) = el {
|
||||
if let Some(&Element::Op(ref op)) = el {
|
||||
match op {
|
||||
&BinaryExprType::GT
|
||||
| &BinaryExprType::GTEqual
|
||||
| &BinaryExprType::LT
|
||||
| &BinaryExprType::LTEqual
|
||||
| &BinaryExprType::NotEqual
|
||||
| &BinaryExprType::Equal => {
|
||||
return Result::Complete(i_.clone(), op.clone());
|
||||
}
|
||||
_other => {
|
||||
// noop
|
||||
}
|
||||
};
|
||||
}
|
||||
return Result::Fail(Error::new(
|
||||
format!(
|
||||
"Error while parsing Binary Expression Unexpected Operator {:?}",
|
||||
@ -249,13 +245,19 @@ fn parse_compare_operator(i: SliceIter<Element>) -> Result<SliceIter<Element>, C
|
||||
));
|
||||
}
|
||||
|
||||
make_fn!(
|
||||
binary_expression<SliceIter<Element>, Expression>,
|
||||
either!(compare_expression, math_expression, parse_expression)
|
||||
);
|
||||
|
||||
make_fn!(
|
||||
compare_expression<SliceIter<Element>, Expression>,
|
||||
do_each!(
|
||||
left => either!(trace_parse!(math_expression), trace_parse!(parse_expression)),
|
||||
typ => parse_compare_operator,
|
||||
right => either!(trace_parse!(math_expression), trace_parse!(parse_expression)),
|
||||
(tuple_to_compare_expression(typ, left, right))
|
||||
do_binary_expr!(
|
||||
parse_compare_operator,
|
||||
either!(
|
||||
trace_parse!(math_expression),
|
||||
trace_parse!(parse_expression)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
@ -340,11 +342,7 @@ pub fn op_expression<'a>(i: SliceIter<'a, Token>) -> Result<SliceIter<Token>, Ex
|
||||
Result::Incomplete(i) => Result::Incomplete(i),
|
||||
Result::Complete(rest, oplist) => {
|
||||
let i_ = SliceIter::new(&oplist);
|
||||
let parse_result = either!(
|
||||
i_.clone(),
|
||||
trace_parse!(compare_expression),
|
||||
trace_parse!(math_expression)
|
||||
);
|
||||
let parse_result = binary_expression(i_);
|
||||
|
||||
match parse_result {
|
||||
Result::Fail(_e) => {
|
||||
|
@ -619,8 +619,8 @@ fn test_expression_parse() {
|
||||
);
|
||||
assert_parse!(
|
||||
expression("1 > 1"),
|
||||
Expression::Compare(ComparisonDef {
|
||||
kind: CompareType::GT,
|
||||
Expression::Binary(BinaryOpDef {
|
||||
kind: BinaryExprType::GT,
|
||||
left: Box::new(Expression::Simple(Value::Int(value_node!(
|
||||
1,
|
||||
Position::new(1, 1, 0)
|
||||
@ -634,8 +634,8 @@ fn test_expression_parse() {
|
||||
);
|
||||
assert_parse!(
|
||||
expression("1 < 1"),
|
||||
Expression::Compare(ComparisonDef {
|
||||
kind: CompareType::LT,
|
||||
Expression::Binary(BinaryOpDef {
|
||||
kind: BinaryExprType::LT,
|
||||
left: Box::new(Expression::Simple(Value::Int(value_node!(
|
||||
1,
|
||||
Position::new(1, 1, 0)
|
||||
@ -649,8 +649,8 @@ fn test_expression_parse() {
|
||||
);
|
||||
assert_parse!(
|
||||
expression("1 <= 1"),
|
||||
Expression::Compare(ComparisonDef {
|
||||
kind: CompareType::LTEqual,
|
||||
Expression::Binary(BinaryOpDef {
|
||||
kind: BinaryExprType::LTEqual,
|
||||
left: Box::new(Expression::Simple(Value::Int(value_node!(
|
||||
1,
|
||||
Position::new(1, 1, 0)
|
||||
@ -664,8 +664,8 @@ fn test_expression_parse() {
|
||||
);
|
||||
assert_parse!(
|
||||
expression("1 >= 1"),
|
||||
Expression::Compare(ComparisonDef {
|
||||
kind: CompareType::GTEqual,
|
||||
Expression::Binary(BinaryOpDef {
|
||||
kind: BinaryExprType::GTEqual,
|
||||
left: Box::new(Expression::Simple(Value::Int(value_node!(
|
||||
1,
|
||||
Position::new(1, 1, 0)
|
||||
|
Loading…
x
Reference in New Issue
Block a user