diff --git a/src/parser/expr.rs b/src/parser/expr.rs index 058cfb4..0d4830a 100644 --- a/src/parser/expr.rs +++ b/src/parser/expr.rs @@ -182,28 +182,24 @@ pub fn quantifier_expr( /// /// # Grammar /// -/// `RANGE_EXPR := NUM_LIT_EXPR .. NUM_LIT_EXPR` +/// `RANGE_EXPR := EXPR .. EXPR` /// /// # Examples /// /// `0..10` corresponds to the mathematical interval `[0, 10)` /// -/// an arithmetic expression evalutes to a number a | b +/// an arithmetic expression evaluates to a number a | b pub fn range_expr( input: VelosiTokenStream, ) -> IResult { let mut loc = input.clone(); - let (i, (s, _, e)) = tuple((num_lit_expr, dotdot, num_lit_expr))(input)?; + + let (i, (s, _, e)) = tuple((expr, dotdot, expr))(input)?; + loc.span_until_start(&i); - match (s, e) { - (VelosiParseTreeExpr::NumLiteral(s), VelosiParseTreeExpr::NumLiteral(e)) => { - let range = VelosiParseTreeRangeExpr::with_loc(s.value, e.value, loc); - Ok((i, range)) - //Ok((i, VelosiParseTreeExpr::Range(range))) - } - _ => unreachable!(), - } + let range = VelosiParseTreeRangeExpr::with_loc(s, e, loc); + Ok((i, range)) } /// pares a function call expression @@ -826,10 +822,10 @@ fn test_slice() { test_parse_and_compare_ok!("foo[3..4]", expr); test_parse_and_compare_ok!("foo.bar[0..3]", expr); test_parse_and_compare_ok!("foo[1..2]", slice_expr); + test_parse_and_compare_ok!("foo[1 + 2..1 + 2]", slice_expr); + test_parse_and_compare_ok!("foo[a..b]", slice_expr); - // currently we don't support this - test_parse_and_check_fail!("foo[1+2..1+2]", slice_expr); - test_parse_and_check_fail!("foo[a..b]", slice_expr); + test_parse_and_check_fail!("foo.bar[a..(b..c)]", slice_expr); } #[test] @@ -865,12 +861,17 @@ fn test_ifelse_fail() { #[test] fn test_range() { - // parse_equal!(range_expr, "a..b", "a..b"); test_parse_and_compare_ok!("1..2", range_expr); - - // currently we don't support this - test_parse_and_check_fail!("a..b", range_expr); - test_parse_and_check_fail!("1+2..a+2", range_expr); + test_parse_and_compare_ok!("a..b", range_expr); + test_parse_and_compare_ok!("a..b", range_expr); + test_parse_and_compare_ok!("1 + 2..a + 2", range_expr); + test_parse_and_compare_ok!( + "1 + 2 + 3 .. a + 4 * 3", + range_expr, + "(1 + 2) + 3..a + (4 * 3)" + ); + test_parse_and_compare_ok!("(1 + 2)..(a + 2)", range_expr, "1 + 2..a + 2"); + test_parse_and_check_fail!("1 + 2 + 3 .. ( 1 .. 4)", range_expr); } #[test] diff --git a/src/parser/map.rs b/src/parser/map.rs index a6ef736..696a2fb 100644 --- a/src/parser/map.rs +++ b/src/parser/map.rs @@ -320,8 +320,7 @@ fn test_map_dest_fail() { #[test] fn test_map_src_ok() { test_parse_and_check_ok!("0..0x1000 =>", map_src); - // TODO: should have support for this... - test_parse_and_check_fail!("i * 0x1000..(i+1) * 0x1000 =>", map_src); + test_parse_and_check_ok!("i * 0x1000..(i + 1) * 0x1000 =>", map_src); } #[test] @@ -343,8 +342,7 @@ fn test_map_element_ok() { test_parse_and_compare_ok!("0..4096 => UnitA() @ 4096", map_element); test_parse_and_compare_ok!("0..4096 => UnitA() @ 4096 + (i * 4096)", map_element); - // TODO: should have support for this... - test_parse_and_check_fail!("i * 4096..(i+1) * 4096 => UnitA()", map_element); + test_parse_and_compare_ok!("i * 4096..(i + 1) * 4096 => UnitA()", map_element); } #[test] diff --git a/src/parsetree/expr.rs b/src/parsetree/expr.rs index aeb2af4..a0939fb 100644 --- a/src/parsetree/expr.rs +++ b/src/parsetree/expr.rs @@ -543,23 +543,39 @@ impl Debug for VelosiParseTreeIfElseExpr { #[derive(PartialEq, Eq, Clone)] pub struct VelosiParseTreeRangeExpr { /// start of the range (including) - pub start: u64, + pub start: Box, /// end value of the range (not including) - pub end: u64, + pub end: Box, /// location of the range expression in the source tree pub loc: VelosiTokenStream, } impl VelosiParseTreeRangeExpr { /// constructs a new range expression with default location - pub fn with_loc(start: u64, end: u64, loc: VelosiTokenStream) -> Self { - Self { start, end, loc } + pub fn with_loc( + start: VelosiParseTreeExpr, + end: VelosiParseTreeExpr, + loc: VelosiTokenStream, + ) -> Self { + Self { + start: Box::new(start), + end: Box::new(end), + loc, + } } /// constructs a new range expression with default location - pub fn new(start: u64, end: u64) -> Self { + pub fn new(start: VelosiParseTreeExpr, end: VelosiParseTreeExpr) -> Self { Self::with_loc(start, end, VelosiTokenStream::default()) } + + pub fn new_fixed(start: u64, end: u64) -> Self { + Self::with_loc( + VelosiParseTreeExpr::NumLiteral(VelosiParseTreeNumLiteral::new(start)), + VelosiParseTreeExpr::NumLiteral(VelosiParseTreeNumLiteral::new(end)), + VelosiTokenStream::default(), + ) + } } /// Implementation of [Display] for [VelosiParseTreeRangeExpr]