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)]
|
#[derive(PartialEq, Clone)]
|
||||||
pub struct SelectorList {
|
pub struct SelectorList {
|
||||||
pub head: Box<Expression>,
|
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>>,
|
pub tail: Option<Vec<Token>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -579,10 +580,6 @@ impl MacroDef {
|
|||||||
stack.push(&bexpr.left);
|
stack.push(&bexpr.left);
|
||||||
stack.push(&bexpr.right);
|
stack.push(&bexpr.right);
|
||||||
}
|
}
|
||||||
&Expression::Compare(ref cexpr) => {
|
|
||||||
stack.push(&cexpr.left);
|
|
||||||
stack.push(&cexpr.right);
|
|
||||||
}
|
|
||||||
&Expression::Grouped(ref expr) => {
|
&Expression::Grouped(ref expr) => {
|
||||||
stack.push(expr);
|
stack.push(expr);
|
||||||
}
|
}
|
||||||
@ -644,26 +641,14 @@ pub enum BinaryExprType {
|
|||||||
Sub,
|
Sub,
|
||||||
Mul,
|
Mul,
|
||||||
Div,
|
Div,
|
||||||
}
|
// Comparison
|
||||||
|
|
||||||
/// CompareType signals the type of a comparison for a binary expression.
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
|
||||||
pub enum CompareType {
|
|
||||||
Equal,
|
Equal,
|
||||||
GT,
|
GT,
|
||||||
LT,
|
LT,
|
||||||
NotEqual,
|
NotEqual,
|
||||||
GTEqual,
|
GTEqual,
|
||||||
LTEqual,
|
LTEqual,
|
||||||
}
|
// TODO DOT Selector operator
|
||||||
|
|
||||||
/// 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,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents an expression with a left and a right side.
|
/// Represents an expression with a left and a right side.
|
||||||
@ -759,7 +744,6 @@ pub enum Expression {
|
|||||||
|
|
||||||
// Binary expressions
|
// Binary expressions
|
||||||
Binary(BinaryOpDef),
|
Binary(BinaryOpDef),
|
||||||
Compare(ComparisonDef),
|
|
||||||
|
|
||||||
// Complex Expressions
|
// Complex Expressions
|
||||||
Copy(CopyDef),
|
Copy(CopyDef),
|
||||||
@ -779,7 +763,6 @@ impl Expression {
|
|||||||
match self {
|
match self {
|
||||||
&Expression::Simple(ref v) => v.pos(),
|
&Expression::Simple(ref v) => v.pos(),
|
||||||
&Expression::Binary(ref def) => &def.pos,
|
&Expression::Binary(ref def) => &def.pos,
|
||||||
&Expression::Compare(ref def) => &def.pos,
|
|
||||||
&Expression::Copy(ref def) => &def.pos,
|
&Expression::Copy(ref def) => &def.pos,
|
||||||
&Expression::Grouped(ref expr) => expr.pos(),
|
&Expression::Grouped(ref expr) => expr.pos(),
|
||||||
&Expression::Format(ref def) => &def.pos,
|
&Expression::Format(ref def) => &def.pos,
|
||||||
@ -801,9 +784,6 @@ impl fmt::Display for Expression {
|
|||||||
&Expression::Binary(_) => {
|
&Expression::Binary(_) => {
|
||||||
write!(w, "<Expr>")?;
|
write!(w, "<Expr>")?;
|
||||||
}
|
}
|
||||||
&Expression::Compare(_) => {
|
|
||||||
write!(w, "<Expr>")?;
|
|
||||||
}
|
|
||||||
&Expression::ListOp(_) => {
|
&Expression::ListOp(_) => {
|
||||||
write!(w, "<Expr>")?;
|
write!(w, "<Expr>")?;
|
||||||
}
|
}
|
||||||
|
@ -866,20 +866,12 @@ impl<'a> FileBuilder<'a> {
|
|||||||
&BinaryExprType::Sub => self.subtract_vals(&def.pos, left, right),
|
&BinaryExprType::Sub => self.subtract_vals(&def.pos, left, right),
|
||||||
&BinaryExprType::Mul => self.multiply_vals(&def.pos, left, right),
|
&BinaryExprType::Mul => self.multiply_vals(&def.pos, left, right),
|
||||||
&BinaryExprType::Div => self.divide_vals(&def.pos, left, right),
|
&BinaryExprType::Div => self.divide_vals(&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),
|
||||||
fn eval_compare(&mut self, def: &ComparisonDef, scope: &Scope) -> Result<Rc<Val>, Box<Error>> {
|
&BinaryExprType::GTEqual => self.do_gtequal(&def.pos, left, right),
|
||||||
let kind = &def.kind;
|
&BinaryExprType::LTEqual => self.do_ltequal(&def.pos, left, right),
|
||||||
let left = self.eval_expr(&def.left, scope)?;
|
&BinaryExprType::NotEqual => self.do_not_deep_equal(&def.pos, left, right),
|
||||||
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),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1247,7 +1239,6 @@ impl<'a> FileBuilder<'a> {
|
|||||||
match expr {
|
match expr {
|
||||||
&Expression::Simple(ref val) => self.eval_value(val, scope),
|
&Expression::Simple(ref val) => self.eval_value(val, scope),
|
||||||
&Expression::Binary(ref def) => self.eval_binary(def, 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::Copy(ref def) => self.eval_copy(def, scope),
|
||||||
&Expression::Grouped(ref expr) => self.eval_expr(expr, scope),
|
&Expression::Grouped(ref expr) => self.eval_expr(expr, scope),
|
||||||
&Expression::Format(ref def) => self.eval_format(def, scope),
|
&Expression::Format(ref def) => self.eval_format(def, scope),
|
||||||
|
@ -277,6 +277,8 @@ make_fn!(
|
|||||||
make_fn!(
|
make_fn!(
|
||||||
value<SliceIter<Token>, Value>,
|
value<SliceIter<Token>, Value>,
|
||||||
either!(
|
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!(selector_value),
|
||||||
trace_parse!(compound_value),
|
trace_parse!(compound_value),
|
||||||
trace_parse!(boolean_value),
|
trace_parse!(boolean_value),
|
||||||
@ -426,6 +428,7 @@ make_fn!(
|
|||||||
copy_expression<SliceIter<Token>, Expression>,
|
copy_expression<SliceIter<Token>, Expression>,
|
||||||
do_each!(
|
do_each!(
|
||||||
pos => pos,
|
pos => pos,
|
||||||
|
// TODO This should become just a bareword symbol now
|
||||||
selector => trace_parse!(selector_list),
|
selector => trace_parse!(selector_list),
|
||||||
_ => punct!("{"),
|
_ => punct!("{"),
|
||||||
fields => optional!(trace_parse!(field_list)),
|
fields => optional!(trace_parse!(field_list)),
|
||||||
@ -635,6 +638,7 @@ make_fn!(
|
|||||||
|
|
||||||
fn call_expression(input: SliceIter<Token>) -> Result<SliceIter<Token>, Expression> {
|
fn call_expression(input: SliceIter<Token>) -> Result<SliceIter<Token>, Expression> {
|
||||||
let parsed = do_each!(input.clone(),
|
let parsed = do_each!(input.clone(),
|
||||||
|
// TODO This should become just a bareword symbol now
|
||||||
callee_name => trace_parse!(selector_value),
|
callee_name => trace_parse!(selector_value),
|
||||||
_ => punct!("("),
|
_ => punct!("("),
|
||||||
args => optional!(separated!(punct!(","), trace_parse!(expression))),
|
args => optional!(separated!(punct!(","), trace_parse!(expression))),
|
||||||
@ -723,6 +727,7 @@ make_fn!(
|
|||||||
do_each!(_ => word!("map"), (ListOpType::Map)),
|
do_each!(_ => word!("map"), (ListOpType::Map)),
|
||||||
do_each!(_ => word!("filter"), (ListOpType::Filter))
|
do_each!(_ => word!("filter"), (ListOpType::Filter))
|
||||||
),
|
),
|
||||||
|
// TODO This should become just a bareword symbol now
|
||||||
macroname => trace_parse!(selector_value),
|
macroname => trace_parse!(selector_value),
|
||||||
list => trace_parse!(non_op_expression),
|
list => trace_parse!(non_op_expression),
|
||||||
(tuple_to_list_op(&input, optype, macroname, list).unwrap())
|
(tuple_to_list_op(&input, optype, macroname, list).unwrap())
|
||||||
|
@ -24,8 +24,7 @@ use crate::ast::*;
|
|||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum Element {
|
pub enum Element {
|
||||||
Expr(Expression),
|
Expr(Expression),
|
||||||
MathOp(BinaryExprType),
|
Op(BinaryExprType),
|
||||||
CompareOp(CompareType),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
make_fn!(
|
make_fn!(
|
||||||
@ -33,16 +32,16 @@ make_fn!(
|
|||||||
either!(
|
either!(
|
||||||
do_each!(
|
do_each!(
|
||||||
_ => punct!("+"),
|
_ => punct!("+"),
|
||||||
(Element::MathOp(BinaryExprType::Add))),
|
(Element::Op(BinaryExprType::Add))),
|
||||||
do_each!(
|
do_each!(
|
||||||
_ => punct!("-"),
|
_ => punct!("-"),
|
||||||
(Element::MathOp(BinaryExprType::Sub))),
|
(Element::Op(BinaryExprType::Sub))),
|
||||||
do_each!(
|
do_each!(
|
||||||
_ => punct!("*"),
|
_ => punct!("*"),
|
||||||
(Element::MathOp(BinaryExprType::Mul))),
|
(Element::Op(BinaryExprType::Mul))),
|
||||||
do_each!(
|
do_each!(
|
||||||
_ => punct!("/"),
|
_ => 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();
|
let el = i_.next();
|
||||||
if let Some(&Element::MathOp(ref op)) = el {
|
if let Some(&Element::Op(ref op)) = el {
|
||||||
match op {
|
match op {
|
||||||
&BinaryExprType::Add => {
|
&BinaryExprType::Add => {
|
||||||
return Result::Complete(i_.clone(), op.clone());
|
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();
|
let el = i_.next();
|
||||||
if let Some(&Element::MathOp(ref op)) = el {
|
if let Some(&Element::Op(ref op)) = el {
|
||||||
match op {
|
match op {
|
||||||
&BinaryExprType::Mul => {
|
&BinaryExprType::Mul => {
|
||||||
return Result::Complete(i_.clone(), op.clone());
|
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!(
|
make_fn!(
|
||||||
compare_op_type<SliceIter<Token>, Element>,
|
compare_op_type<SliceIter<Token>, Element>,
|
||||||
either!(
|
either!(
|
||||||
do_each!(_ => punct!("=="), (Element::CompareOp(CompareType::Equal))),
|
do_each!(_ => punct!("=="), (Element::Op(BinaryExprType::Equal))),
|
||||||
do_each!(_ => punct!("!="), (Element::CompareOp(CompareType::NotEqual))),
|
do_each!(_ => punct!("!="), (Element::Op(BinaryExprType::NotEqual))),
|
||||||
do_each!(_ => punct!("<="), (Element::CompareOp(CompareType::LTEqual))),
|
do_each!(_ => punct!("<="), (Element::Op(BinaryExprType::LTEqual))),
|
||||||
do_each!(_ => punct!(">="), (Element::CompareOp(CompareType::GTEqual))),
|
do_each!(_ => punct!(">="), (Element::Op(BinaryExprType::GTEqual))),
|
||||||
do_each!(_ => punct!("<"), (Element::CompareOp(CompareType::LT))),
|
do_each!(_ => punct!("<"), (Element::Op(BinaryExprType::LT))),
|
||||||
do_each!(_ => punct!(">"), (Element::CompareOp(CompareType::GT)))
|
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();
|
let mut i_ = i.clone();
|
||||||
if eoi(i_.clone()).is_complete() {
|
if eoi(i_.clone()).is_complete() {
|
||||||
return Result::Fail(Error::new(
|
return Result::Fail(Error::new(
|
||||||
@ -237,8 +221,20 @@ fn parse_compare_operator(i: SliceIter<Element>) -> Result<SliceIter<Element>, C
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
let el = i_.next();
|
let el = i_.next();
|
||||||
if let Some(&Element::CompareOp(ref op)) = el {
|
if let Some(&Element::Op(ref op)) = el {
|
||||||
return Result::Complete(i_.clone(), op.clone());
|
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(
|
return Result::Fail(Error::new(
|
||||||
format!(
|
format!(
|
||||||
@ -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!(
|
make_fn!(
|
||||||
compare_expression<SliceIter<Element>, Expression>,
|
compare_expression<SliceIter<Element>, Expression>,
|
||||||
do_each!(
|
do_binary_expr!(
|
||||||
left => either!(trace_parse!(math_expression), trace_parse!(parse_expression)),
|
parse_compare_operator,
|
||||||
typ => parse_compare_operator,
|
either!(
|
||||||
right => either!(trace_parse!(math_expression), trace_parse!(parse_expression)),
|
trace_parse!(math_expression),
|
||||||
(tuple_to_compare_expression(typ, left, right))
|
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::Incomplete(i) => Result::Incomplete(i),
|
||||||
Result::Complete(rest, oplist) => {
|
Result::Complete(rest, oplist) => {
|
||||||
let i_ = SliceIter::new(&oplist);
|
let i_ = SliceIter::new(&oplist);
|
||||||
let parse_result = either!(
|
let parse_result = binary_expression(i_);
|
||||||
i_.clone(),
|
|
||||||
trace_parse!(compare_expression),
|
|
||||||
trace_parse!(math_expression)
|
|
||||||
);
|
|
||||||
|
|
||||||
match parse_result {
|
match parse_result {
|
||||||
Result::Fail(_e) => {
|
Result::Fail(_e) => {
|
||||||
|
@ -619,8 +619,8 @@ fn test_expression_parse() {
|
|||||||
);
|
);
|
||||||
assert_parse!(
|
assert_parse!(
|
||||||
expression("1 > 1"),
|
expression("1 > 1"),
|
||||||
Expression::Compare(ComparisonDef {
|
Expression::Binary(BinaryOpDef {
|
||||||
kind: CompareType::GT,
|
kind: BinaryExprType::GT,
|
||||||
left: Box::new(Expression::Simple(Value::Int(value_node!(
|
left: Box::new(Expression::Simple(Value::Int(value_node!(
|
||||||
1,
|
1,
|
||||||
Position::new(1, 1, 0)
|
Position::new(1, 1, 0)
|
||||||
@ -634,8 +634,8 @@ fn test_expression_parse() {
|
|||||||
);
|
);
|
||||||
assert_parse!(
|
assert_parse!(
|
||||||
expression("1 < 1"),
|
expression("1 < 1"),
|
||||||
Expression::Compare(ComparisonDef {
|
Expression::Binary(BinaryOpDef {
|
||||||
kind: CompareType::LT,
|
kind: BinaryExprType::LT,
|
||||||
left: Box::new(Expression::Simple(Value::Int(value_node!(
|
left: Box::new(Expression::Simple(Value::Int(value_node!(
|
||||||
1,
|
1,
|
||||||
Position::new(1, 1, 0)
|
Position::new(1, 1, 0)
|
||||||
@ -649,8 +649,8 @@ fn test_expression_parse() {
|
|||||||
);
|
);
|
||||||
assert_parse!(
|
assert_parse!(
|
||||||
expression("1 <= 1"),
|
expression("1 <= 1"),
|
||||||
Expression::Compare(ComparisonDef {
|
Expression::Binary(BinaryOpDef {
|
||||||
kind: CompareType::LTEqual,
|
kind: BinaryExprType::LTEqual,
|
||||||
left: Box::new(Expression::Simple(Value::Int(value_node!(
|
left: Box::new(Expression::Simple(Value::Int(value_node!(
|
||||||
1,
|
1,
|
||||||
Position::new(1, 1, 0)
|
Position::new(1, 1, 0)
|
||||||
@ -664,8 +664,8 @@ fn test_expression_parse() {
|
|||||||
);
|
);
|
||||||
assert_parse!(
|
assert_parse!(
|
||||||
expression("1 >= 1"),
|
expression("1 >= 1"),
|
||||||
Expression::Compare(ComparisonDef {
|
Expression::Binary(BinaryOpDef {
|
||||||
kind: CompareType::GTEqual,
|
kind: BinaryExprType::GTEqual,
|
||||||
left: Box::new(Expression::Simple(Value::Int(value_node!(
|
left: Box::new(Expression::Simple(Value::Int(value_node!(
|
||||||
1,
|
1,
|
||||||
Position::new(1, 1, 0)
|
Position::new(1, 1, 0)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user