REFACTOR: Unify the Binary Operator AST data structures.

This commit is contained in:
Jeremy Wall 2018-12-25 14:04:12 -06:00
parent 2b7c8e65f8
commit fb292b4684
5 changed files with 62 additions and 88 deletions

View File

@ -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>")?;
}

View File

@ -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),

View File

@ -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())

View File

@ -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) => {

View File

@ -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)