diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index 5636934648..8c0da62201 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -629,6 +629,14 @@ pub fn parse_call( err, ) } else { + // We might be parsing left-unbounded range ("..10") + let bytes = working_set.get_span_contents(spans[0]); + if let (Some(b'.'), Some(b'.')) = (bytes.get(0), bytes.get(1)) { + let (range_expr, range_err) = parse_range(working_set, spans[0]); + if range_err.is_none() { + return (range_expr, range_err); + } + } parse_external_call(working_set, spans) } } diff --git a/crates/nu-parser/tests/test_parser.rs b/crates/nu-parser/tests/test_parser.rs index e0359378c2..cdc6f5a8de 100644 --- a/crates/nu-parser/tests/test_parser.rs +++ b/crates/nu-parser/tests/test_parser.rs @@ -371,6 +371,38 @@ mod range { } } + #[test] + fn parse_left_unbounded_range() { + let engine_state = EngineState::new(); + let mut working_set = StateWorkingSet::new(&engine_state); + + let (block, err) = parse(&mut working_set, None, b"..10", true); + + assert!(err.is_none()); + assert!(block.len() == 1); + match &block[0] { + Statement::Pipeline(Pipeline { expressions }) => { + assert!(expressions.len() == 1); + assert!(matches!( + expressions[0], + Expression { + expr: Expr::Range( + None, + None, + Some(_), + RangeOperator { + inclusion: RangeInclusion::Inclusive, + .. + } + ), + .. + } + )) + } + _ => panic!("No match"), + } + } + #[test] fn parse_negative_range() { let engine_state = EngineState::new();