KCL: End-exclusive ranges like [0..<10] (#7179)
Closes https://github.com/KittyCAD/modeling-app/issues/6843 To clarify: `[1..10]` is 1, 2, ..., 8, 9, 10 `[1..<10]` is 1, 2, ... 8, 9
This commit is contained in:
@ -1189,6 +1189,7 @@ impl LanguageServer for Backend {
|
||||
}
|
||||
|
||||
async fn completion(&self, params: CompletionParams) -> RpcResult<Option<CompletionResponse>> {
|
||||
// ADAM: This is the entrypoint.
|
||||
let mut completions = vec![CompletionItem {
|
||||
label: PIPE_OPERATOR.to_string(),
|
||||
label_details: None,
|
||||
|
@ -886,7 +886,7 @@ fn array_end_start(i: &mut TokenSlice) -> PResult<Node<ArrayRangeExpression>> {
|
||||
ignore_whitespace(i);
|
||||
let start_element = expression.parse_next(i)?;
|
||||
ignore_whitespace(i);
|
||||
double_period.parse_next(i)?;
|
||||
let end_inclusive = alt((end_inclusive_range.map(|_| true), end_exclusive_range.map(|_| false))).parse_next(i)?;
|
||||
ignore_whitespace(i);
|
||||
let end_element = expression.parse_next(i)?;
|
||||
ignore_whitespace(i);
|
||||
@ -895,7 +895,7 @@ fn array_end_start(i: &mut TokenSlice) -> PResult<Node<ArrayRangeExpression>> {
|
||||
ArrayRangeExpression {
|
||||
start_element,
|
||||
end_element,
|
||||
end_inclusive: true,
|
||||
end_inclusive,
|
||||
digest: None,
|
||||
},
|
||||
start,
|
||||
@ -2705,7 +2705,7 @@ fn period(i: &mut TokenSlice) -> PResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn double_period(i: &mut TokenSlice) -> PResult<Token> {
|
||||
fn end_inclusive_range(i: &mut TokenSlice) -> PResult<Token> {
|
||||
any.try_map(|token: Token| {
|
||||
if matches!(token.token_type, TokenType::DoublePeriod) {
|
||||
Ok(token)
|
||||
@ -2724,6 +2724,21 @@ fn double_period(i: &mut TokenSlice) -> PResult<Token> {
|
||||
.parse_next(i)
|
||||
}
|
||||
|
||||
fn end_exclusive_range(i: &mut TokenSlice) -> PResult<Token> {
|
||||
any.try_map(|token: Token| {
|
||||
if matches!(token.token_type, TokenType::DoublePeriodLessThan) {
|
||||
Ok(token)
|
||||
} else {
|
||||
Err(CompilationError::fatal(
|
||||
token.as_source_range(),
|
||||
format!("expected a '..<' but found {}", token.value.as_str()),
|
||||
))
|
||||
}
|
||||
})
|
||||
.context(expected("the ..< operator, used for array ranges like [0..<10]"))
|
||||
.parse_next(i)
|
||||
}
|
||||
|
||||
fn colon(i: &mut TokenSlice) -> PResult<Token> {
|
||||
TokenType::Colon.parse_from(i)
|
||||
}
|
||||
@ -5344,7 +5359,6 @@ mod snapshot_tests {
|
||||
);
|
||||
snapshot_test!(aa, r#"sg = -scale"#);
|
||||
snapshot_test!(ab, "line(endAbsolute = [0, -1])");
|
||||
snapshot_test!(ac, "myArray = [0..10]");
|
||||
snapshot_test!(
|
||||
ad,
|
||||
r#"
|
||||
@ -5485,6 +5499,11 @@ my14 = 4 ^ 2 - 3 ^ 2 * 2
|
||||
)"#
|
||||
);
|
||||
snapshot_test!(kw_function_in_binary_op, r#"val = f(x = 1) + 1"#);
|
||||
snapshot_test!(
|
||||
array_ranges,
|
||||
r#"incl = [1..10]
|
||||
excl = [0..<10]"#
|
||||
);
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
|
@ -0,0 +1,117 @@
|
||||
---
|
||||
source: kcl-lib/src/parsing/parser.rs
|
||||
expression: actual
|
||||
---
|
||||
{
|
||||
"body": [
|
||||
{
|
||||
"commentStart": 0,
|
||||
"declaration": {
|
||||
"commentStart": 0,
|
||||
"end": 14,
|
||||
"id": {
|
||||
"commentStart": 0,
|
||||
"end": 4,
|
||||
"name": "incl",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"init": {
|
||||
"commentStart": 7,
|
||||
"end": 14,
|
||||
"endElement": {
|
||||
"commentStart": 11,
|
||||
"end": 13,
|
||||
"raw": "10",
|
||||
"start": 11,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 10.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"endInclusive": true,
|
||||
"start": 7,
|
||||
"startElement": {
|
||||
"commentStart": 8,
|
||||
"end": 9,
|
||||
"raw": "1",
|
||||
"start": 8,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"type": "ArrayRangeExpression",
|
||||
"type": "ArrayRangeExpression"
|
||||
},
|
||||
"start": 0,
|
||||
"type": "VariableDeclarator"
|
||||
},
|
||||
"end": 14,
|
||||
"kind": "const",
|
||||
"start": 0,
|
||||
"type": "VariableDeclaration",
|
||||
"type": "VariableDeclaration"
|
||||
},
|
||||
{
|
||||
"commentStart": 23,
|
||||
"declaration": {
|
||||
"commentStart": 23,
|
||||
"end": 38,
|
||||
"id": {
|
||||
"commentStart": 23,
|
||||
"end": 27,
|
||||
"name": "excl",
|
||||
"start": 23,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"init": {
|
||||
"commentStart": 30,
|
||||
"end": 38,
|
||||
"endElement": {
|
||||
"commentStart": 35,
|
||||
"end": 37,
|
||||
"raw": "10",
|
||||
"start": 35,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 10.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"endInclusive": false,
|
||||
"start": 30,
|
||||
"startElement": {
|
||||
"commentStart": 31,
|
||||
"end": 32,
|
||||
"raw": "0",
|
||||
"start": 31,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 0.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"type": "ArrayRangeExpression",
|
||||
"type": "ArrayRangeExpression"
|
||||
},
|
||||
"start": 23,
|
||||
"type": "VariableDeclarator"
|
||||
},
|
||||
"end": 38,
|
||||
"kind": "const",
|
||||
"start": 23,
|
||||
"type": "VariableDeclaration",
|
||||
"type": "VariableDeclaration"
|
||||
}
|
||||
],
|
||||
"commentStart": 0,
|
||||
"end": 38,
|
||||
"start": 0
|
||||
}
|
@ -369,6 +369,8 @@ pub enum TokenType {
|
||||
Period,
|
||||
/// A double period: `..`.
|
||||
DoublePeriod,
|
||||
/// A double period and a less than: `..<`.
|
||||
DoublePeriodLessThan,
|
||||
/// A line comment.
|
||||
LineComment,
|
||||
/// A block comment.
|
||||
@ -410,6 +412,7 @@ impl TryFrom<TokenType> for SemanticTokenType {
|
||||
| TokenType::DoubleColon
|
||||
| TokenType::Period
|
||||
| TokenType::DoublePeriod
|
||||
| TokenType::DoublePeriodLessThan
|
||||
| TokenType::Hash
|
||||
| TokenType::Dollar
|
||||
| TokenType::At
|
||||
|
@ -87,7 +87,7 @@ pub(super) fn token(i: &mut Input<'_>) -> PResult<Token> {
|
||||
'0'..='9' => number,
|
||||
';' => semi_colon,
|
||||
':' => alt((double_colon, colon)),
|
||||
'.' => alt((number, double_period, period)),
|
||||
'.' => alt((number, double_period_less_than, double_period, period)),
|
||||
'#' => hash,
|
||||
'$' => dollar,
|
||||
'!' => alt((operator, bang)),
|
||||
@ -320,6 +320,16 @@ fn double_period(i: &mut Input<'_>) -> PResult<Token> {
|
||||
))
|
||||
}
|
||||
|
||||
fn double_period_less_than(i: &mut Input<'_>) -> PResult<Token> {
|
||||
let (value, range) = "..<".with_span().parse_next(i)?;
|
||||
Ok(Token::from_range(
|
||||
range,
|
||||
i.state.module_id,
|
||||
TokenType::DoublePeriodLessThan,
|
||||
value.to_string(),
|
||||
))
|
||||
}
|
||||
|
||||
/// Zero or more of either:
|
||||
/// 1. Any character except " or \
|
||||
/// 2. Any character preceded by \
|
||||
|
Reference in New Issue
Block a user