Repository: prql/prql
Pull request #465 (2022-05-08 02:33:52)

Implement sort syntax of `+`/`-`
It looks like a lot of lines changed, but actually that's mostly from making a pest rule non-silent, which adds another layer to parse trees, which indents a lot of snapshots.

I'm actually not sure whether we need all those `expr` items to be non-silent. But not worth spending time on at this stage.

max-sixty: Docs view: 
<img width="780" alt="image" src="https://user-images.githubusercontent.com/5635139/167280135-f6603849-6f72-4604-a3b9-2373a01d699e.png">

max-sixty: I'll merge but feel free to comment and I'll follow up

Patch:
diff --git a/prql-compiler/src/parser.rs b/prql-compiler/src/parser.rs
index 7ec40d85..d5be0f12 100644
--- a/prql-compiler/src/parser.rs
+++ b/prql-compiler/src/parser.rs
@@ -496,6 +496,22 @@ Canada
           - Ident: b
         "###);
         assert_ne!(ab, a_comma_b);
+
+        assert_debug_snapshot!(
+            parse_tree_of_str(r#"[amount, +amount, -amount]"#, Rule::list).unwrap()
+        );
+        // Operators in list items
+        assert_yaml_snapshot!(ast_of_string(r#"[amount, +amount, -amount]"#, Rule::list).unwrap(), @r###"
+        ---
+        List:
+          - Ident: amount
+          - Expr:
+              - Operator: +
+              - Ident: amount
+          - Expr:
+              - Operator: "-"
+              - Ident: amount
+        "###);
     }
 
     #[test]
@@ -1318,18 +1334,21 @@ select [
                     name: sort
                     args:
                       - List:
-                          - Operator: "-"
-                          - Ident: issued_at
+                          - Expr:
+                              - Operator: "-"
+                              - Ident: issued_at
                     named_args: {}
                 - FuncCall:
                     name: sort
                     args:
                       - List:
                           - Ident: issued_at
-                          - Operator: "-"
-                          - Ident: amount
-                          - Operator: +
-                          - Ident: num_of_articles
+                          - Expr:
+                              - Operator: "-"
+                              - Ident: amount
+                          - Expr:
+                              - Operator: +
+                              - Ident: num_of_articles
                     named_args: {}
         "###);
 
diff --git a/prql-compiler/src/prql.pest b/prql-compiler/src/prql.pest
index c5e9e9bc..421447bb 100644
--- a/prql-compiler/src/prql.pest
+++ b/prql-compiler/src/prql.pest
@@ -64,9 +64,8 @@ assign      = { ident ~ "=" ~ !"=" ~ expr }
 assign_call = { ident ~ "=" ~ !"=" ~ expr_call }
 
 // Expression that can contain a function call and a leading `+` or `-`
-expr_call = _{ operator_add? ~ (func_call | expr) }
+expr_call = { operator_add? ~ (func_call | expr) }
 
-// We add an `operator_add?` to the `expr` rule to allow for a leading `+` or `-`.
 expr = !{ expr_compare ~ (operator_logical ~ expr_compare)* }
 expr_compare = _{ expr_add ~ (operator_compare ~ expr_add)? }
 expr_add = _{ expr_mul ~ (operator_add ~ expr_mul)* }
diff --git a/prql-compiler/src/semantic/transforms.rs b/prql-compiler/src/semantic/transforms.rs
index 550e5ebd..9f6bb0fd 100644
--- a/prql-compiler/src/semantic/transforms.rs
+++ b/prql-compiler/src/semantic/transforms.rs
@@ -51,23 +51,52 @@ pub fn cast_transform(func_call: FuncCall, span: Option<Span>) -> Result<Transfo
                 .coerce_to_vec()
                 .into_iter()
                 .map(|node| {
-                    let (column, direction) = match node.item {
-                        Item::Assign(named_expr) => {
-                            let direction = match named_expr.name.as_str() {
-                                "asc" => SortDirection::Asc,
-                                "desc" => SortDirection::Desc,
-                                _ => {
-                                    return Err(Error::new(Reason::Expected {
-                                        who: Some("sort".to_string()),
-                                        expected: "asc or desc".to_string(),
-                                        found: named_expr.name,
-                                    })
-                                    .with_span(node.span))
-                                }
-                            };
-                            (*named_expr.expr, direction)
+                    let (column, direction) = match &node.item {
+                        // If it's `+foo`, then it's two items; if `foo` then one.
+                        Item::Ident(_) => (node, SortDirection::default()),
+                        Item::Expr(nodes) => match &nodes[..] {
+                            [Node {
+                                item: Item::Operator(op),
+                                ..
+                            }, column]
+                            // We could use a guard, but we instead fall through
+                            // for a better error message.
+                            // if op == "+" || op == "-" =>
+                            => {
+                                let direction = match op.as_str() {
+                                    "+" => SortDirection::Asc,
+                                    "-" => SortDirection::Desc,
+                                    _ => {
+                                        return Err(Error::new(Reason::Expected {
+                                            who: Some("sort".to_string()),
+                                            expected: "+ or -".to_string(),
+                                            found: op.to_string(),
+                                        })
+                                        .with_span(node.span))
+                                    }
+                                };
+                                (column.clone(), direction)
+                            }
+                            _ => {
+                                return Err(Error::new(Reason::Expected {
+                                    who: Some("sort".to_string()),
+                                    expected: "column name, optionally prefixed with + or -"
+                                        .to_string(),
+                                    found: node.item.to_string(),
+                                })
+                                .with_span(node.span))
+                            }
+                        },
+                        _ => {
+                            // Copy-pasted from above; can we consolidate?
+                            return Err(Error::new(Reason::Expected {
+                                who: Some("sort".to_string()),
+                                expected: "column name, optionally prefixed with + or -"
+                                    .to_string(),
+                                found: node.item.to_string(),
+                            })
+                            .with_span(node.span));
                         }
-                        _ => (node, SortDirection::default()),
                     };
 
                     if matches!(column.item, Item::Ident(_)) {
@@ -314,14 +343,15 @@ mod tests {
         let query = parse(
             "
         from invoices
-        sort [amount]
-        # sort [-issued_at, desc=amount, num_of_articles]
-        # sort [-amount]
+        sort [issued_at, -amount, +num_of_articles]
+        sort issued_at
+        sort (-issued_at)
+        sort [issued_at]
+        sort [-issued_at]
         ",
         )
         .unwrap();
 
-        dbg!(&query);
         let (result, _) = resolve(query.nodes, context).unwrap();
         assert_yaml_snapshot!(result, @r###"
         ---
@@ -336,8 +366,34 @@ mod tests {
               - Transform:
                   Sort:
                     - direction: Asc
+                      column:
+                        Ident: issued_at
+                    - direction: Desc
                       column:
                         Ident: amount
+                    - direction: Asc
+                      column:
+                        Ident: num_of_articles
+              - Transform:
+                  Sort:
+                    - direction: Asc
+                      column:
+                        Ident: issued_at
+              - Transform:
+                  Sort:
+                    - direction: Desc
+                      column:
+                        Ident: issued_at
+              - Transform:
+                  Sort:
+                    - direction: Asc
+                      column:
+                        Ident: issued_at
+              - Transform:
+                  Sort:
+                    - direction: Desc
+                      column:
+                        Ident: issued_at
         "###);
     }
 }
diff --git a/prql-compiler/src/sql/translator.rs b/prql-compiler/src/sql/translator.rs
index 061d0d8c..0faa6ff7 100644
--- a/prql-compiler/src/sql/translator.rs
+++ b/prql-compiler/src/sql/translator.rs
@@ -1190,21 +1190,20 @@ take 20
     fn test_sorts() -> Result<()> {
         let query: Query = parse(
             r###"
-        from Employees
-        sort [id]
-        sort [age, desc=last_name, asc=first_name]
+        from invoices
+        sort [issued_at, -amount, +num_of_articles]
         "###,
         )?;
 
         assert_display_snapshot!((resolve_and_translate(query)?), @r###"
         SELECT
-          Employees.*
+          invoices.*
         FROM
-          Employees
+          invoices
         ORDER BY
-          age,
-          last_name DESC,
-          first_name
+          issued_at,
+          amount DESC,
+          num_of_articles
         "###);
 
         Ok(())
diff --git a/reference/src/transforms.md b/reference/src/transforms.md
index 7ce9c907..3bddcf7c 100644
--- a/reference/src/transforms.md
+++ b/reference/src/transforms.md
@@ -10,7 +10,7 @@ Core principle of the language is a pipeline, which is a series of sequential tr
 from {table reference}
 ```
 
-*Example:*
+#### Examples
 
 ```prql
 from employees
@@ -24,7 +24,7 @@ from employees
 select [{expression}]
 ```
 
-*Example:*
+#### Examples
 
 ```prql
 from employees
@@ -39,7 +39,7 @@ select [first_name, last_name]
 derive [{new_name} = {expression}]
 ```
 
-*Example:*
+#### Examples
 
 ```prql
 from employees
@@ -62,45 +62,60 @@ derive [
 filter {boolean expression}
 ```
 
-*Example:*
+#### Examples
 
 ```prql_no_test
 from employees
 filter (length last_name < 3)
 ```
 
-## Take
+## Sort
 
-> picks first n rows
+`sort` orders rows based on the values of one or more columns.
 
 ```prql_no_test
-take {n}
+sort [{direction}{column}]
 ```
 
-*Example:*
+#### Arguments
+
+- One or multiple columns
+- Each column can be prefixed with:
+  - `+`, for ascending order, the default
+  - `-`, for descending order
+
+#### Examples
 
 ```prql
 from employees
-take 10
+sort age
 ```
 
-## Sort
+```prql
+from employees
+sort (-age)
+```
 
-> orders the rows by the values of selected columns
+> Note that `sort -age` is not valid; `-age` needs to be surrounded by parentheses.
 
-```prql_no_test
-sort {column}
+```prql
+from employees
+sort [age, -tenure, +salary]
 ```
 
-*Arguments:*
+## Take
 
-- a column identifier of the key to sort by
+> picks first n rows
 
-*Example:*
+```prql_no_test
+take {n}
+```
+
+#### Examples
 
 ```prql
 from employees
-sort age
+take 10
 ```
 
 ## Join
@@ -111,21 +126,21 @@ sort age
 join side:{inner|left|right|full} {table} {[conditions]}
 ```
 
-*Arguments:*
+#### Arguments
 
 - `side` decides which rows to include. Defaults to `inner`
 - table reference
 - list of conditions
   - If all terms are column identifiers, this will compile to `USING(...)`. In this case, both of the tables must have specified column. The result will only contain one column instead one for each table.
 
-*Example:*
+#### Examples
 
 ```prql
 from employees
 join side:left positions [id==employee_id]
 ```
 
-*Example:*
+#### Examples
 
 ```prql
 from employees
@@ -179,7 +194,7 @@ group role (
 aggregate [{expression or assign operations}]
 ```
 
-*Example:*
+#### Examples
 
 ```prql
 from employees


Test patch:
diff --git a/prql-compiler/src/snapshots/prql_compiler__parser__test__inline_pipeline.snap b/prql-compiler/src/snapshots/prql_compiler__parser__test__inline_pipeline.snap
index 32aa98a7..a0bd1ae8 100644
--- a/prql-compiler/src/snapshots/prql_compiler__parser__test__inline_pipeline.snap
+++ b/prql-compiler/src/snapshots/prql_compiler__parser__test__inline_pipeline.snap
@@ -12,7 +12,7 @@ expression: "parse_tree_of_str(\"(salary | percentile 50)\", Rule::nested_pipeli
         },
         inner: [
             Pair {
-                rule: expr,
+                rule: expr_call,
                 span: Span {
                     str: "salary ",
                     start: 1,
@@ -20,13 +20,23 @@ expression: "parse_tree_of_str(\"(salary | percentile 50)\", Rule::nested_pipeli
                 },
                 inner: [
                     Pair {
-                        rule: ident,
+                        rule: expr,
                         span: Span {
-                            str: "salary",
+                            str: "salary ",
                             start: 1,
-                            end: 7,
+                            end: 8,
                         },
-                        inner: [],
+                        inner: [
+                            Pair {
+                                rule: ident,
+                                span: Span {
+                                    str: "salary",
+                                    start: 1,
+                                    end: 7,
+                                },
+                                inner: [],
+                            },
+                        ],
                     },
                 ],
             },
diff --git a/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_into_parse_tree-2.snap b/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_into_parse_tree-2.snap
index a9237ddf..b85926ff 100644
--- a/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_into_parse_tree-2.snap
+++ b/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_into_parse_tree-2.snap
@@ -37,7 +37,7 @@ expression: "parse_tree_of_str(\"select [a, b, c]\", Rule::func_curry)?"
                         },
                         inner: [
                             Pair {
-                                rule: expr,
+                                rule: expr_call,
                                 span: Span {
                                     str: "a",
                                     start: 8,
@@ -45,18 +45,28 @@ expression: "parse_tree_of_str(\"select [a, b, c]\", Rule::func_curry)?"
                                 },
                                 inner: [
                                     Pair {
-                                        rule: ident,
+                                        rule: expr,
                                         span: Span {
                                             str: "a",
                                             start: 8,
                                             end: 9,
                                         },
-                                        inner: [],
+                                        inner: [
+                                            Pair {
+                                                rule: ident,
+                                                span: Span {
+                                                    str: "a",
+                                                    start: 8,
+                                                    end: 9,
+                                                },
+                                                inner: [],
+                                            },
+                                        ],
                                     },
                                 ],
                             },
                             Pair {
-                                rule: expr,
+                                rule: expr_call,
                                 span: Span {
                                     str: "b",
                                     start: 11,
@@ -64,18 +74,28 @@ expression: "parse_tree_of_str(\"select [a, b, c]\", Rule::func_curry)?"
                                 },
                                 inner: [
                                     Pair {
-                                        rule: ident,
+                                        rule: expr,
                                         span: Span {
                                             str: "b",
                                             start: 11,
                                             end: 12,
                                         },
-                                        inner: [],
+                                        inner: [
+                                            Pair {
+                                                rule: ident,
+                                                span: Span {
+                                                    str: "b",
+                                                    start: 11,
+                                                    end: 12,
+                                                },
+                                                inner: [],
+                                            },
+                                        ],
                                     },
                                 ],
                             },
                             Pair {
-                                rule: expr,
+                                rule: expr_call,
                                 span: Span {
                                     str: "c",
                                     start: 14,
@@ -83,13 +103,23 @@ expression: "parse_tree_of_str(\"select [a, b, c]\", Rule::func_curry)?"
                                 },
                                 inner: [
                                     Pair {
-                                        rule: ident,
+                                        rule: expr,
                                         span: Span {
                                             str: "c",
                                             start: 14,
                                             end: 15,
                                         },
-                                        inner: [],
+                                        inner: [
+                                            Pair {
+                                                rule: ident,
+                                                span: Span {
+                                                    str: "c",
+                                                    start: 14,
+                                                    end: 15,
+                                                },
+                                                inner: [],
+                                            },
+                                        ],
                                     },
                                 ],
                             },
diff --git a/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_into_parse_tree-3.snap b/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_into_parse_tree-3.snap
index fa2ae807..1fa7c891 100644
--- a/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_into_parse_tree-3.snap
+++ b/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_into_parse_tree-3.snap
@@ -45,7 +45,7 @@ expression: "parse_tree_of_str(\"group [title, country] (\n                aggre
                                 },
                                 inner: [
                                     Pair {
-                                        rule: expr,
+                                        rule: expr_call,
                                         span: Span {
                                             str: "title",
                                             start: 7,
@@ -53,18 +53,28 @@ expression: "parse_tree_of_str(\"group [title, country] (\n                aggre
                                         },
                                         inner: [
                                             Pair {
-                                                rule: ident,
+                                                rule: expr,
                                                 span: Span {
                                                     str: "title",
                                                     start: 7,
                                                     end: 12,
                                                 },
-                                                inner: [],
+                                                inner: [
+                                                    Pair {
+                                                        rule: ident,
+                                                        span: Span {
+                                                            str: "title",
+                                                            start: 7,
+                                                            end: 12,
+                                                        },
+                                                        inner: [],
+                                                    },
+                                                ],
                                             },
                                         ],
                                     },
                                     Pair {
-                                        rule: expr,
+                                        rule: expr_call,
                                         span: Span {
                                             str: "country",
                                             start: 14,
@@ -72,13 +82,23 @@ expression: "parse_tree_of_str(\"group [title, country] (\n                aggre
                                         },
                                         inner: [
                                             Pair {
-                                                rule: ident,
+                                                rule: expr,
                                                 span: Span {
                                                     str: "country",
                                                     start: 14,
                                                     end: 21,
                                                 },
-                                                inner: [],
+                                                inner: [
+                                                    Pair {
+                                                        rule: ident,
+                                                        span: Span {
+                                                            str: "country",
+                                                            start: 14,
+                                                            end: 21,
+                                                        },
+                                                        inner: [],
+                                                    },
+                                                ],
                                             },
                                         ],
                                     },
@@ -144,7 +164,7 @@ expression: "parse_tree_of_str(\"group [title, country] (\n                aggre
                                                                 },
                                                                 inner: [
                                                                     Pair {
-                                                                        rule: func_call,
+                                                                        rule: expr_call,
                                                                         span: Span {
                                                                             str: "sum salary",
                                                                             start: 52,
@@ -152,30 +172,40 @@ expression: "parse_tree_of_str(\"group [title, country] (\n                aggre
                                                                         },
                                                                         inner: [
                                                                             Pair {
-                                                                                rule: ident,
+                                                                                rule: func_call,
                                                                                 span: Span {
-                                                                                    str: "sum",
+                                                                                    str: "sum salary",
                                                                                     start: 52,
-                                                                                    end: 55,
-                                                                                },
-                                                                                inner: [],
-                                                                            },
-                                                                            Pair {
-                                                                                rule: expr,
-                                                                                span: Span {
-                                                                                    str: "salary",
-                                                                                    start: 56,
                                                                                     end: 62,
                                                                                 },
                                                                                 inner: [
                                                                                     Pair {
                                                                                         rule: ident,
+                                                                                        span: Span {
+                                                                                            str: "sum",
+                                                                                            start: 52,
+                                                                                            end: 55,
+                                                                                        },
+                                                                                        inner: [],
+                                                                                    },
+                                                                                    Pair {
+                                                                                        rule: expr,
                                                                                         span: Span {
                                                                                             str: "salary",
                                                                                             start: 56,
                                                                                             end: 62,
                                                                                         },
-                                                                                        inner: [],
+                                                                                        inner: [
+                                                                                            Pair {
+                                                                                                rule: ident,
+                                                                                                span: Span {
+                                                                                                    str: "salary",
+                                                                                                    start: 56,
+                                                                                                    end: 62,
+                                                                                                },
+                                                                                                inner: [],
+                                                                                            },
+                                                                                        ],
                                                                                     },
                                                                                 ],
                                                                             },
diff --git a/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_into_parse_tree-5.snap b/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_into_parse_tree-5.snap
index 327657b7..96c27179 100644
--- a/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_into_parse_tree-5.snap
+++ b/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_into_parse_tree-5.snap
@@ -12,7 +12,7 @@ expression: "parse_tree_of_str(\"[a, b, c,]\", Rule::list)?"
         },
         inner: [
             Pair {
-                rule: expr,
+                rule: expr_call,
                 span: Span {
                     str: "a",
                     start: 1,
@@ -20,18 +20,28 @@ expression: "parse_tree_of_str(\"[a, b, c,]\", Rule::list)?"
                 },
                 inner: [
                     Pair {
-                        rule: ident,
+                        rule: expr,
                         span: Span {
                             str: "a",
                             start: 1,
                             end: 2,
                         },
-                        inner: [],
+                        inner: [
+                            Pair {
+                                rule: ident,
+                                span: Span {
+                                    str: "a",
+                                    start: 1,
+                                    end: 2,
+                                },
+                                inner: [],
+                            },
+                        ],
                     },
                 ],
             },
             Pair {
-                rule: expr,
+                rule: expr_call,
                 span: Span {
                     str: "b",
                     start: 4,
@@ -39,18 +49,28 @@ expression: "parse_tree_of_str(\"[a, b, c,]\", Rule::list)?"
                 },
                 inner: [
                     Pair {
-                        rule: ident,
+                        rule: expr,
                         span: Span {
                             str: "b",
                             start: 4,
                             end: 5,
                         },
-                        inner: [],
+                        inner: [
+                            Pair {
+                                rule: ident,
+                                span: Span {
+                                    str: "b",
+                                    start: 4,
+                                    end: 5,
+                                },
+                                inner: [],
+                            },
+                        ],
                     },
                 ],
             },
             Pair {
-                rule: expr,
+                rule: expr_call,
                 span: Span {
                     str: "c",
                     start: 7,
@@ -58,13 +78,23 @@ expression: "parse_tree_of_str(\"[a, b, c,]\", Rule::list)?"
                 },
                 inner: [
                     Pair {
-                        rule: ident,
+                        rule: expr,
                         span: Span {
                             str: "c",
                             start: 7,
                             end: 8,
                         },
-                        inner: [],
+                        inner: [
+                            Pair {
+                                rule: ident,
+                                span: Span {
+                                    str: "c",
+                                    start: 7,
+                                    end: 8,
+                                },
+                                inner: [],
+                            },
+                        ],
                     },
                 ],
             },
diff --git a/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_into_parse_tree-6.snap b/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_into_parse_tree-6.snap
index ec007f60..99b3eb56 100644
--- a/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_into_parse_tree-6.snap
+++ b/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_into_parse_tree-6.snap
@@ -29,7 +29,7 @@ expression: "parse_tree_of_str(r#\"[\n  gross_salary = salary + payroll_tax,\n
                         inner: [],
                     },
                     Pair {
-                        rule: expr,
+                        rule: expr_call,
                         span: Span {
                             str: "salary + payroll_tax",
                             start: 19,
@@ -37,31 +37,41 @@ expression: "parse_tree_of_str(r#\"[\n  gross_salary = salary + payroll_tax,\n
                         },
                         inner: [
                             Pair {
-                                rule: ident,
+                                rule: expr,
                                 span: Span {
-                                    str: "salary",
+                                    str: "salary + payroll_tax",
                                     start: 19,
-                                    end: 25,
-                                },
-                                inner: [],
-                            },
-                            Pair {
-                                rule: operator_add,
-                                span: Span {
-                                    str: "+",
-                                    start: 26,
-                                    end: 27,
-                                },
-                                inner: [],
-                            },
-                            Pair {
-                                rule: ident,
-                                span: Span {
-                                    str: "payroll_tax",
-                                    start: 28,
                                     end: 39,
                                 },
-                                inner: [],
+                                inner: [
+                                    Pair {
+                                        rule: ident,
+                                        span: Span {
+                                            str: "salary",
+                                            start: 19,
+                                            end: 25,
+                                        },
+                                        inner: [],
+                                    },
+                                    Pair {
+                                        rule: operator_add,
+                                        span: Span {
+                                            str: "+",
+                                            start: 26,
+                                            end: 27,
+                                        },
+                                        inner: [],
+                                    },
+                                    Pair {
+                                        rule: ident,
+                                        span: Span {
+                                            str: "payroll_tax",
+                                            start: 28,
+                                            end: 39,
+                                        },
+                                        inner: [],
+                                    },
+                                ],
                             },
                         ],
                     },
@@ -85,7 +95,7 @@ expression: "parse_tree_of_str(r#\"[\n  gross_salary = salary + payroll_tax,\n
                         inner: [],
                     },
                     Pair {
-                        rule: expr,
+                        rule: expr_call,
                         span: Span {
                             str: "gross_salary + benefits_cost",
                             start: 58,
@@ -93,31 +103,41 @@ expression: "parse_tree_of_str(r#\"[\n  gross_salary = salary + payroll_tax,\n
                         },
                         inner: [
                             Pair {
-                                rule: ident,
+                                rule: expr,
                                 span: Span {
-                                    str: "gross_salary",
+                                    str: "gross_salary + benefits_cost",
                                     start: 58,
-                                    end: 70,
-                                },
-                                inner: [],
-                            },
-                            Pair {
-                                rule: operator_add,
-                                span: Span {
-                                    str: "+",
-                                    start: 71,
-                                    end: 72,
-                                },
-                                inner: [],
-                            },
-                            Pair {
-                                rule: ident,
-                                span: Span {
-                                    str: "benefits_cost",
-                                    start: 73,
                                     end: 86,
                                 },
-                                inner: [],
+                                inner: [
+                                    Pair {
+                                        rule: ident,
+                                        span: Span {
+                                            str: "gross_salary",
+                                            start: 58,
+                                            end: 70,
+                                        },
+                                        inner: [],
+                                    },
+                                    Pair {
+                                        rule: operator_add,
+                                        span: Span {
+                                            str: "+",
+                                            start: 71,
+                                            end: 72,
+                                        },
+                                        inner: [],
+                                    },
+                                    Pair {
+                                        rule: ident,
+                                        span: Span {
+                                            str: "benefits_cost",
+                                            start: 73,
+                                            end: 86,
+                                        },
+                                        inner: [],
+                                    },
+                                ],
                             },
                         ],
                     },
diff --git a/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_into_parse_tree-8.snap b/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_into_parse_tree-8.snap
index 4ebe6bf1..11a4c9ab 100644
--- a/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_into_parse_tree-8.snap
+++ b/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_into_parse_tree-8.snap
@@ -56,7 +56,7 @@ expression: "parse_tree_of_str(\"join country [id==employee_id]\", Rule::func_cu
                         },
                         inner: [
                             Pair {
-                                rule: expr,
+                                rule: expr_call,
                                 span: Span {
                                     str: "id==employee_id",
                                     start: 14,
@@ -64,31 +64,41 @@ expression: "parse_tree_of_str(\"join country [id==employee_id]\", Rule::func_cu
                                 },
                                 inner: [
                                     Pair {
-                                        rule: ident,
+                                        rule: expr,
                                         span: Span {
-                                            str: "id",
+                                            str: "id==employee_id",
                                             start: 14,
-                                            end: 16,
-                                        },
-                                        inner: [],
-                                    },
-                                    Pair {
-                                        rule: operator_compare,
-                                        span: Span {
-                                            str: "==",
-                                            start: 16,
-                                            end: 18,
-                                        },
-                                        inner: [],
-                                    },
-                                    Pair {
-                                        rule: ident,
-                                        span: Span {
-                                            str: "employee_id",
-                                            start: 18,
                                             end: 29,
                                         },
-                                        inner: [],
+                                        inner: [
+                                            Pair {
+                                                rule: ident,
+                                                span: Span {
+                                                    str: "id",
+                                                    start: 14,
+                                                    end: 16,
+                                                },
+                                                inner: [],
+                                            },
+                                            Pair {
+                                                rule: operator_compare,
+                                                span: Span {
+                                                    str: "==",
+                                                    start: 16,
+                                                    end: 18,
+                                                },
+                                                inner: [],
+                                            },
+                                            Pair {
+                                                rule: ident,
+                                                span: Span {
+                                                    str: "employee_id",
+                                                    start: 18,
+                                                    end: 29,
+                                                },
+                                                inner: [],
+                                            },
+                                        ],
                                     },
                                 ],
                             },
diff --git a/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_into_parse_tree-9.snap b/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_into_parse_tree-9.snap
index 14343147..d21be23a 100644
--- a/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_into_parse_tree-9.snap
+++ b/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_into_parse_tree-9.snap
@@ -94,7 +94,7 @@ expression: "parse_tree_of_str(\"join side:left country [id==employee_id]\",\n
                         },
                         inner: [
                             Pair {
-                                rule: expr,
+                                rule: expr_call,
                                 span: Span {
                                     str: "id==employee_id",
                                     start: 24,
@@ -102,31 +102,41 @@ expression: "parse_tree_of_str(\"join side:left country [id==employee_id]\",\n
                                 },
                                 inner: [
                                     Pair {
-                                        rule: ident,
+                                        rule: expr,
                                         span: Span {
-                                            str: "id",
+                                            str: "id==employee_id",
                                             start: 24,
-                                            end: 26,
-                                        },
-                                        inner: [],
-                                    },
-                                    Pair {
-                                        rule: operator_compare,
-                                        span: Span {
-                                            str: "==",
-                                            start: 26,
-                                            end: 28,
-                                        },
-                                        inner: [],
-                                    },
-                                    Pair {
-                                        rule: ident,
-                                        span: Span {
-                                            str: "employee_id",
-                                            start: 28,
                                             end: 39,
                                         },
-                                        inner: [],
+                                        inner: [
+                                            Pair {
+                                                rule: ident,
+                                                span: Span {
+                                                    str: "id",
+                                                    start: 24,
+                                                    end: 26,
+                                                },
+                                                inner: [],
+                                            },
+                                            Pair {
+                                                rule: operator_compare,
+                                                span: Span {
+                                                    str: "==",
+                                                    start: 26,
+                                                    end: 28,
+                                                },
+                                                inner: [],
+                                            },
+                                            Pair {
+                                                rule: ident,
+                                                span: Span {
+                                                    str: "employee_id",
+                                                    start: 28,
+                                                    end: 39,
+                                                },
+                                                inner: [],
+                                            },
+                                        ],
                                     },
                                 ],
                             },
diff --git a/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_list-7.snap b/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_list-7.snap
new file mode 100644
index 00000000..aa4ed41c
--- /dev/null
+++ b/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_list-7.snap
@@ -0,0 +1,121 @@
+---
+source: prql-compiler/src/parser.rs
+expression: "parse_tree_of_str(r#\"[amount, +amount, -amount]\"#, Rule::list).unwrap()"
+---
+[
+    Pair {
+        rule: list,
+        span: Span {
+            str: "[amount, +amount, -amount]",
+            start: 0,
+            end: 26,
+        },
+        inner: [
+            Pair {
+                rule: expr_call,
+                span: Span {
+                    str: "amount",
+                    start: 1,
+                    end: 7,
+                },
+                inner: [
+                    Pair {
+                        rule: expr,
+                        span: Span {
+                            str: "amount",
+                            start: 1,
+                            end: 7,
+                        },
+                        inner: [
+                            Pair {
+                                rule: ident,
+                                span: Span {
+                                    str: "amount",
+                                    start: 1,
+                                    end: 7,
+                                },
+                                inner: [],
+                            },
+                        ],
+                    },
+                ],
+            },
+            Pair {
+                rule: expr_call,
+                span: Span {
+                    str: "+amount",
+                    start: 9,
+                    end: 16,
+                },
+                inner: [
+                    Pair {
+                        rule: operator_add,
+                        span: Span {
+                            str: "+",
+                            start: 9,
+                            end: 10,
+                        },
+                        inner: [],
+                    },
+                    Pair {
+                        rule: expr,
+                        span: Span {
+                            str: "amount",
+                            start: 10,
+                            end: 16,
+                        },
+                        inner: [
+                            Pair {
+                                rule: ident,
+                                span: Span {
+                                    str: "amount",
+                                    start: 10,
+                                    end: 16,
+                                },
+                                inner: [],
+                            },
+                        ],
+                    },
+                ],
+            },
+            Pair {
+                rule: expr_call,
+                span: Span {
+                    str: "-amount",
+                    start: 18,
+                    end: 25,
+                },
+                inner: [
+                    Pair {
+                        rule: operator_add,
+                        span: Span {
+                            str: "-",
+                            start: 18,
+                            end: 19,
+                        },
+                        inner: [],
+                    },
+                    Pair {
+                        rule: expr,
+                        span: Span {
+                            str: "amount",
+                            start: 19,
+                            end: 25,
+                        },
+                        inner: [
+                            Pair {
+                                rule: ident,
+                                span: Span {
+                                    str: "amount",
+                                    start: 19,
+                                    end: 25,
+                                },
+                                inner: [],
+                            },
+                        ],
+                    },
+                ],
+            },
+        ],
+    },
+]
diff --git a/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_list.snap b/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_list.snap
index cd467dc1..8b42c19e 100644
--- a/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_list.snap
+++ b/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_list.snap
@@ -12,7 +12,7 @@ expression: "parse_tree_of_str(r#\"[1 + 1, 2]\"#, Rule::list).unwrap()"
         },
         inner: [
             Pair {
-                rule: expr,
+                rule: expr_call,
                 span: Span {
                     str: "1 + 1",
                     start: 1,
@@ -20,36 +20,46 @@ expression: "parse_tree_of_str(r#\"[1 + 1, 2]\"#, Rule::list).unwrap()"
                 },
                 inner: [
                     Pair {
-                        rule: number,
+                        rule: expr,
                         span: Span {
-                            str: "1",
+                            str: "1 + 1",
                             start: 1,
-                            end: 2,
-                        },
-                        inner: [],
-                    },
-                    Pair {
-                        rule: operator_add,
-                        span: Span {
-                            str: "+",
-                            start: 3,
-                            end: 4,
-                        },
-                        inner: [],
-                    },
-                    Pair {
-                        rule: number,
-                        span: Span {
-                            str: "1",
-                            start: 5,
                             end: 6,
                         },
-                        inner: [],
+                        inner: [
+                            Pair {
+                                rule: number,
+                                span: Span {
+                                    str: "1",
+                                    start: 1,
+                                    end: 2,
+                                },
+                                inner: [],
+                            },
+                            Pair {
+                                rule: operator_add,
+                                span: Span {
+                                    str: "+",
+                                    start: 3,
+                                    end: 4,
+                                },
+                                inner: [],
+                            },
+                            Pair {
+                                rule: number,
+                                span: Span {
+                                    str: "1",
+                                    start: 5,
+                                    end: 6,
+                                },
+                                inner: [],
+                            },
+                        ],
                     },
                 ],
             },
             Pair {
-                rule: expr,
+                rule: expr_call,
                 span: Span {
                     str: "2",
                     start: 8,
@@ -57,13 +67,23 @@ expression: "parse_tree_of_str(r#\"[1 + 1, 2]\"#, Rule::list).unwrap()"
                 },
                 inner: [
                     Pair {
-                        rule: number,
+                        rule: expr,
                         span: Span {
                             str: "2",
                             start: 8,
                             end: 9,
                         },
-                        inner: [],
+                        inner: [
+                            Pair {
+                                rule: number,
+                                span: Span {
+                                    str: "2",
+                                    start: 8,
+                                    end: 9,
+                                },
+                                inner: [],
+                            },
+                        ],
                     },
                 ],
             },
diff --git a/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_pipeline_parse_tree-3.snap b/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_pipeline_parse_tree-3.snap
index 0b49889f..269b111d 100644
--- a/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_pipeline_parse_tree-3.snap
+++ b/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_pipeline_parse_tree-3.snap
@@ -166,7 +166,7 @@ expression: "parse_tree_of_str(r#\"\nfrom employees\nfilter country == \"USA\"
                                                 inner: [],
                                             },
                                             Pair {
-                                                rule: expr,
+                                                rule: expr_call,
                                                 span: Span {
                                                     str: "salary + payroll_tax",
                                                     start: 208,
@@ -174,31 +174,41 @@ expression: "parse_tree_of_str(r#\"\nfrom employees\nfilter country == \"USA\"
                                                 },
                                                 inner: [
                                                     Pair {
-                                                        rule: ident,
+                                                        rule: expr,
                                                         span: Span {
-                                                            str: "salary",
+                                                            str: "salary + payroll_tax",
                                                             start: 208,
-                                                            end: 214,
-                                                        },
-                                                        inner: [],
-                                                    },
-                                                    Pair {
-                                                        rule: operator_add,
-                                                        span: Span {
-                                                            str: "+",
-                                                            start: 215,
-                                                            end: 216,
-                                                        },
-                                                        inner: [],
-                                                    },
-                                                    Pair {
-                                                        rule: ident,
-                                                        span: Span {
-                                                            str: "payroll_tax",
-                                                            start: 217,
                                                             end: 228,
                                                         },
-                                                        inner: [],
+                                                        inner: [
+                                                            Pair {
+                                                                rule: ident,
+                                                                span: Span {
+                                                                    str: "salary",
+                                                                    start: 208,
+                                                                    end: 214,
+                                                                },
+                                                                inner: [],
+                                                            },
+                                                            Pair {
+                                                                rule: operator_add,
+                                                                span: Span {
+                                                                    str: "+",
+                                                                    start: 215,
+                                                                    end: 216,
+                                                                },
+                                                                inner: [],
+                                                            },
+                                                            Pair {
+                                                                rule: ident,
+                                                                span: Span {
+                                                                    str: "payroll_tax",
+                                                                    start: 217,
+                                                                    end: 228,
+                                                                },
+                                                                inner: [],
+                                                            },
+                                                        ],
                                                     },
                                                 ],
                                             },
@@ -222,7 +232,7 @@ expression: "parse_tree_of_str(r#\"\nfrom employees\nfilter country == \"USA\"
                                                 inner: [],
                                             },
                                             Pair {
-                                                rule: expr,
+                                                rule: expr_call,
                                                 span: Span {
                                                     str: "gross_salary + benefits_cost    # Variables can use other variables.",
                                                     start: 247,
@@ -230,31 +240,41 @@ expression: "parse_tree_of_str(r#\"\nfrom employees\nfilter country == \"USA\"
                                                 },
                                                 inner: [
                                                     Pair {
-                                                        rule: ident,
+                                                        rule: expr,
                                                         span: Span {
-                                                            str: "gross_salary",
+                                                            str: "gross_salary + benefits_cost    # Variables can use other variables.",
                                                             start: 247,
-                                                            end: 259,
-                                                        },
-                                                        inner: [],
-                                                    },
-                                                    Pair {
-                                                        rule: operator_add,
-                                                        span: Span {
-                                                            str: "+",
-                                                            start: 260,
-                                                            end: 261,
+                                                            end: 315,
                                                         },
-                                                        inner: [],
-                                                    },
-                                                    Pair {
-                                                        rule: ident,
-                                                        span: Span {
-                                                            str: "benefits_cost",
-                                                            start: 262,
-                                                            end: 275,
-                                                        },
-                                                        inner: [],
+                                                        inner: [
+                                                            Pair {
+                                                                rule: ident,
+                                                                span: Span {
+                                                                    str: "gross_salary",
+                                                                    start: 247,
+                                                                    end: 259,
+                                                                },
+                                                                inner: [],
+                                                            },
+                                                            Pair {
+                                                                rule: operator_add,
+                                                                span: Span {
+                                                                    str: "+",
+                                                                    start: 260,
+                                                                    end: 261,
+                                                                },
+                                                                inner: [],
+                                                            },
+                                                            Pair {
+                                                                rule: ident,
+                                                                span: Span {
+                                                                    str: "benefits_cost",
+                                                                    start: 262,
+                                                                    end: 275,
+                                                                },
+                                                                inner: [],
+                                                            },
+                                                        ],
                                                     },
                                                 ],
                                             },
@@ -356,7 +376,7 @@ expression: "parse_tree_of_str(r#\"\nfrom employees\nfilter country == \"USA\"
                                 },
                                 inner: [
                                     Pair {
-                                        rule: expr,
+                                        rule: expr_call,
                                         span: Span {
                                             str: "title",
                                             start: 347,
@@ -364,18 +384,28 @@ expression: "parse_tree_of_str(r#\"\nfrom employees\nfilter country == \"USA\"
                                         },
                                         inner: [
                                             Pair {
-                                                rule: ident,
+                                                rule: expr,
                                                 span: Span {
                                                     str: "title",
                                                     start: 347,
                                                     end: 352,
                                                 },
-                                                inner: [],
+                                                inner: [
+                                                    Pair {
+                                                        rule: ident,
+                                                        span: Span {
+                                                            str: "title",
+                                                            start: 347,
+                                                            end: 352,
+                                                        },
+                                                        inner: [],
+                                                    },
+                                                ],
                                             },
                                         ],
                                     },
                                     Pair {
-                                        rule: expr,
+                                        rule: expr_call,
                                         span: Span {
                                             str: "country",
                                             start: 354,
@@ -383,13 +413,23 @@ expression: "parse_tree_of_str(r#\"\nfrom employees\nfilter country == \"USA\"
                                         },
                                         inner: [
                                             Pair {
-                                                rule: ident,
+                                                rule: expr,
                                                 span: Span {
                                                     str: "country",
                                                     start: 354,
                                                     end: 361,
                                                 },
-                                                inner: [],
+                                                inner: [
+                                                    Pair {
+                                                        rule: ident,
+                                                        span: Span {
+                                                            str: "country",
+                                                            start: 354,
+                                                            end: 361,
+                                                        },
+                                                        inner: [],
+                                                    },
+                                                ],
                                             },
                                         ],
                                     },
@@ -455,7 +495,7 @@ expression: "parse_tree_of_str(r#\"\nfrom employees\nfilter country == \"USA\"
                                                                 },
                                                                 inner: [
                                                                     Pair {
-                                                                        rule: func_call,
+                                                                        rule: expr_call,
                                                                         span: Span {
                                                                             str: "average salary",
                                                                             start: 458,
@@ -463,37 +503,47 @@ expression: "parse_tree_of_str(r#\"\nfrom employees\nfilter country == \"USA\"
                                                                         },
                                                                         inner: [
                                                                             Pair {
-                                                                                rule: ident,
+                                                                                rule: func_call,
                                                                                 span: Span {
-                                                                                    str: "average",
+                                                                                    str: "average salary",
                                                                                     start: 458,
-                                                                                    end: 465,
-                                                                                },
-                                                                                inner: [],
-                                                                            },
-                                                                            Pair {
-                                                                                rule: expr,
-                                                                                span: Span {
-                                                                                    str: "salary",
-                                                                                    start: 466,
                                                                                     end: 472,
                                                                                 },
                                                                                 inner: [
                                                                                     Pair {
                                                                                         rule: ident,
+                                                                                        span: Span {
+                                                                                            str: "average",
+                                                                                            start: 458,
+                                                                                            end: 465,
+                                                                                        },
+                                                                                        inner: [],
+                                                                                    },
+                                                                                    Pair {
+                                                                                        rule: expr,
                                                                                         span: Span {
                                                                                             str: "salary",
                                                                                             start: 466,
                                                                                             end: 472,
                                                                                         },
-                                                                                        inner: [],
+                                                                                        inner: [
+                                                                                            Pair {
+                                                                                                rule: ident,
+                                                                                                span: Span {
+                                                                                                    str: "salary",
+                                                                                                    start: 466,
+                                                                                                    end: 472,
+                                                                                                },
+                                                                                                inner: [],
+                                                                                            },
+                                                                                        ],
                                                                                     },
                                                                                 ],
                                                                             },
                                                                         ],
                                                                     },
                                                                     Pair {
-                                                                        rule: func_call,
+                                                                        rule: expr_call,
                                                                         span: Span {
                                                                             str: "sum     salary",
                                                                             start: 556,
@@ -501,37 +551,47 @@ expression: "parse_tree_of_str(r#\"\nfrom employees\nfilter country == \"USA\"
                                                                         },
                                                                         inner: [
                                                                             Pair {
-                                                                                rule: ident,
+                                                                                rule: func_call,
                                                                                 span: Span {
-                                                                                    str: "sum",
+                                                                                    str: "sum     salary",
                                                                                     start: 556,
-                                                                                    end: 559,
-                                                                                },
-                                                                                inner: [],
-                                                                            },
-                                                                            Pair {
-                                                                                rule: expr,
-                                                                                span: Span {
-                                                                                    str: "salary",
-                                                                                    start: 564,
                                                                                     end: 570,
                                                                                 },
                                                                                 inner: [
                                                                                     Pair {
                                                                                         rule: ident,
+                                                                                        span: Span {
+                                                                                            str: "sum",
+                                                                                            start: 556,
+                                                                                            end: 559,
+                                                                                        },
+                                                                                        inner: [],
+                                                                                    },
+                                                                                    Pair {
+                                                                                        rule: expr,
                                                                                         span: Span {
                                                                                             str: "salary",
                                                                                             start: 564,
                                                                                             end: 570,
                                                                                         },
-                                                                                        inner: [],
+                                                                                        inner: [
+                                                                                            Pair {
+                                                                                                rule: ident,
+                                                                                                span: Span {
+                                                                                                    str: "salary",
+                                                                                                    start: 564,
+                                                                                                    end: 570,
+                                                                                                },
+                                                                                                inner: [],
+                                                                                            },
+                                                                                        ],
                                                                                     },
                                                                                 ],
                                                                             },
                                                                         ],
                                                                     },
                                                                     Pair {
-                                                                        rule: func_call,
+                                                                        rule: expr_call,
                                                                         span: Span {
                                                                             str: "average gross_salary",
                                                                             start: 580,
@@ -539,37 +599,47 @@ expression: "parse_tree_of_str(r#\"\nfrom employees\nfilter country == \"USA\"
                                                                         },
                                                                         inner: [
                                                                             Pair {
-                                                                                rule: ident,
+                                                                                rule: func_call,
                                                                                 span: Span {
-                                                                                    str: "average",
+                                                                                    str: "average gross_salary",
                                                                                     start: 580,
-                                                                                    end: 587,
-                                                                                },
-                                                                                inner: [],
-                                                                            },
-                                                                            Pair {
-                                                                                rule: expr,
-                                                                                span: Span {
-                                                                                    str: "gross_salary",
-                                                                                    start: 588,
                                                                                     end: 600,
                                                                                 },
                                                                                 inner: [
                                                                                     Pair {
                                                                                         rule: ident,
+                                                                                        span: Span {
+                                                                                            str: "average",
+                                                                                            start: 580,
+                                                                                            end: 587,
+                                                                                        },
+                                                                                        inner: [],
+                                                                                    },
+                                                                                    Pair {
+                                                                                        rule: expr,
                                                                                         span: Span {
                                                                                             str: "gross_salary",
                                                                                             start: 588,
                                                                                             end: 600,
                                                                                         },
-                                                                                        inner: [],
+                                                                                        inner: [
+                                                                                            Pair {
+                                                                                                rule: ident,
+                                                                                                span: Span {
+                                                                                                    str: "gross_salary",
+                                                                                                    start: 588,
+                                                                                                    end: 600,
+                                                                                                },
+                                                                                                inner: [],
+                                                                                            },
+                                                                                        ],
                                                                                     },
                                                                                 ],
                                                                             },
                                                                         ],
                                                                     },
                                                                     Pair {
-                                                                        rule: func_call,
+                                                                        rule: expr_call,
                                                                         span: Span {
                                                                             str: "sum     gross_salary",
                                                                             start: 610,
@@ -577,37 +647,47 @@ expression: "parse_tree_of_str(r#\"\nfrom employees\nfilter country == \"USA\"
                                                                         },
                                                                         inner: [
                                                                             Pair {
-                                                                                rule: ident,
+                                                                                rule: func_call,
                                                                                 span: Span {
-                                                                                    str: "sum",
+                                                                                    str: "sum     gross_salary",
                                                                                     start: 610,
-                                                                                    end: 613,
-                                                                                },
-                                                                                inner: [],
-                                                                            },
-                                                                            Pair {
-                                                                                rule: expr,
-                                                                                span: Span {
-                                                                                    str: "gross_salary",
-                                                                                    start: 618,
                                                                                     end: 630,
                                                                                 },
                                                                                 inner: [
                                                                                     Pair {
                                                                                         rule: ident,
+                                                                                        span: Span {
+                                                                                            str: "sum",
+                                                                                            start: 610,
+                                                                                            end: 613,
+                                                                                        },
+                                                                                        inner: [],
+                                                                                    },
+                                                                                    Pair {
+                                                                                        rule: expr,
                                                                                         span: Span {
                                                                                             str: "gross_salary",
                                                                                             start: 618,
                                                                                             end: 630,
                                                                                         },
-                                                                                        inner: [],
+                                                                                        inner: [
+                                                                                            Pair {
+                                                                                                rule: ident,
+                                                                                                span: Span {
+                                                                                                    str: "gross_salary",
+                                                                                                    start: 618,
+                                                                                                    end: 630,
+                                                                                                },
+                                                                                                inner: [],
+                                                                                            },
+                                                                                        ],
                                                                                     },
                                                                                 ],
                                                                             },
                                                                         ],
                                                                     },
                                                                     Pair {
-                                                                        rule: func_call,
+                                                                        rule: expr_call,
                                                                         span: Span {
                                                                             str: "average gross_cost",
                                                                             start: 640,
@@ -615,30 +695,40 @@ expression: "parse_tree_of_str(r#\"\nfrom employees\nfilter country == \"USA\"
                                                                         },
                                                                         inner: [
                                                                             Pair {
-                                                                                rule: ident,
+                                                                                rule: func_call,
                                                                                 span: Span {
-                                                                                    str: "average",
+                                                                                    str: "average gross_cost",
                                                                                     start: 640,
-                                                                                    end: 647,
-                                                                                },
-                                                                                inner: [],
-                                                                            },
-                                                                            Pair {
-                                                                                rule: expr,
-                                                                                span: Span {
-                                                                                    str: "gross_cost",
-                                                                                    start: 648,
                                                                                     end: 658,
                                                                                 },
                                                                                 inner: [
                                                                                     Pair {
                                                                                         rule: ident,
+                                                                                        span: Span {
+                                                                                            str: "average",
+                                                                                            start: 640,
+                                                                                            end: 647,
+                                                                                        },
+                                                                                        inner: [],
+                                                                                    },
+                                                                                    Pair {
+                                                                                        rule: expr,
                                                                                         span: Span {
                                                                                             str: "gross_cost",
                                                                                             start: 648,
                                                                                             end: 658,
                                                                                         },
-                                                                                        inner: [],
+                                                                                        inner: [
+                                                                                            Pair {
+                                                                                                rule: ident,
+                                                                                                span: Span {
+                                                                                                    str: "gross_cost",
+                                                                                                    start: 648,
+                                                                                                    end: 658,
+                                                                                                },
+                                                                                                inner: [],
+                                                                                            },
+                                                                                        ],
                                                                                     },
                                                                                 ],
                                                                             },
@@ -662,7 +752,7 @@ expression: "parse_tree_of_str(r#\"\nfrom employees\nfilter country == \"USA\"
                                                                                 inner: [],
                                                                             },
                                                                             Pair {
-                                                                                rule: func_call,
+                                                                                rule: expr_call,
                                                                                 span: Span {
                                                                                     str: "sum gross_cost",
                                                                                     start: 685,
@@ -670,30 +760,40 @@ expression: "parse_tree_of_str(r#\"\nfrom employees\nfilter country == \"USA\"
                                                                                 },
                                                                                 inner: [
                                                                                     Pair {
-                                                                                        rule: ident,
+                                                                                        rule: func_call,
                                                                                         span: Span {
-                                                                                            str: "sum",
+                                                                                            str: "sum gross_cost",
                                                                                             start: 685,
-                                                                                            end: 688,
-                                                                                        },
-                                                                                        inner: [],
-                                                                                    },
-                                                                                    Pair {
-                                                                                        rule: expr,
-                                                                                        span: Span {
-                                                                                            str: "gross_cost",
-                                                                                            start: 689,
                                                                                             end: 699,
                                                                                         },
                                                                                         inner: [
                                                                                             Pair {
                                                                                                 rule: ident,
+                                                                                                span: Span {
+                                                                                                    str: "sum",
+                                                                                                    start: 685,
+                                                                                                    end: 688,
+                                                                                                },
+                                                                                                inner: [],
+                                                                                            },
+                                                                                            Pair {
+                                                                                                rule: expr,
                                                                                                 span: Span {
                                                                                                     str: "gross_cost",
                                                                                                     start: 689,
                                                                                                     end: 699,
                                                                                                 },
-                                                                                                inner: [],
+                                                                                                inner: [
+                                                                                                    Pair {
+                                                                                                        rule: ident,
+                                                                                                        span: Span {
+                                                                                                            str: "gross_cost",
+                                                                                                            start: 689,
+                                                                                                            end: 699,
+                                                                                                        },
+                                                                                                        inner: [],
+                                                                                                    },
+                                                                                                ],
                                                                                             },
                                                                                         ],
                                                                                     },
@@ -719,7 +819,7 @@ expression: "parse_tree_of_str(r#\"\nfrom employees\nfilter country == \"USA\"
                                                                                 inner: [],
                                                                             },
                                                                             Pair {
-                                                                                rule: expr,
+                                                                                rule: expr_call,
                                                                                 span: Span {
                                                                                     str: "count",
                                                                                     start: 717,
@@ -727,13 +827,23 @@ expression: "parse_tree_of_str(r#\"\nfrom employees\nfilter country == \"USA\"
                                                                                 },
                                                                                 inner: [
                                                                                     Pair {
-                                                                                        rule: ident,
+                                                                                        rule: expr,
                                                                                         span: Span {
                                                                                             str: "count",
                                                                                             start: 717,
                                                                                             end: 722,
                                                                                         },
-                                                                                        inner: [],
+                                                                                        inner: [
+                                                                                            Pair {
+                                                                                                rule: ident,
+                                                                                                span: Span {
+                                                                                                    str: "count",
+                                                                                                    start: 717,
+                                                                                                    end: 722,
+                                                                                                },
+                                                                                                inner: [],
+                                                                                            },
+                                                                                        ],
                                                                                     },
                                                                                 ],
                                                                             },
diff --git a/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_pipeline_parse_tree.snap b/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_pipeline_parse_tree.snap
index 2c582938..876a1a50 100644
--- a/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_pipeline_parse_tree.snap
+++ b/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_pipeline_parse_tree.snap
@@ -83,7 +83,7 @@ expression: "parse_tree_of_str(r#\"\n            from employees\n            sel
                                 },
                                 inner: [
                                     Pair {
-                                        rule: expr,
+                                        rule: expr_call,
                                         span: Span {
                                             str: "a",
                                             start: 35,
@@ -91,18 +91,28 @@ expression: "parse_tree_of_str(r#\"\n            from employees\n            sel
                                         },
                                         inner: [
                                             Pair {
-                                                rule: ident,
+                                                rule: expr,
                                                 span: Span {
                                                     str: "a",
                                                     start: 35,
                                                     end: 36,
                                                 },
-                                                inner: [],
+                                                inner: [
+                                                    Pair {
+                                                        rule: ident,
+                                                        span: Span {
+                                                            str: "a",
+                                                            start: 35,
+                                                            end: 36,
+                                                        },
+                                                        inner: [],
+                                                    },
+                                                ],
                                             },
                                         ],
                                     },
                                     Pair {
-                                        rule: expr,
+                                        rule: expr_call,
                                         span: Span {
                                             str: "b",
                                             start: 38,
@@ -110,13 +120,23 @@ expression: "parse_tree_of_str(r#\"\n            from employees\n            sel
                                         },
                                         inner: [
                                             Pair {
-                                                rule: ident,
+                                                rule: expr,
                                                 span: Span {
                                                     str: "b",
                                                     start: 38,
                                                     end: 39,
                                                 },
-                                                inner: [],
+                                                inner: [
+                                                    Pair {
+                                                        rule: ident,
+                                                        span: Span {
+                                                            str: "b",
+                                                            start: 38,
+                                                            end: 39,
+                                                        },
+                                                        inner: [],
+                                                    },
+                                                ],
                                             },
                                         ],
                                     },
diff --git a/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_s_string.snap b/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_s_string.snap
index db16faf6..d2a8c773 100644
--- a/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_s_string.snap
+++ b/prql-compiler/src/snapshots/prql_compiler__parser__test__parse_s_string.snap
@@ -4,7 +4,7 @@ expression: "parse_tree_of_str(r#\"s\"SUM({col})\"\"#, Rule::expr_call)?"
 ---
 [
     Pair {
-        rule: expr,
+        rule: expr_call,
         span: Span {
             str: "s\"SUM({col})\"",
             start: 0,
@@ -12,7 +12,7 @@ expression: "parse_tree_of_str(r#\"s\"SUM({col})\"\"#, Rule::expr_call)?"
         },
         inner: [
             Pair {
-                rule: s_string,
+                rule: expr,
                 span: Span {
                     str: "s\"SUM({col})\"",
                     start: 0,
@@ -20,42 +20,62 @@ expression: "parse_tree_of_str(r#\"s\"SUM({col})\"\"#, Rule::expr_call)?"
                 },
                 inner: [
                     Pair {
-                        rule: interpolate_string_inner,
+                        rule: s_string,
                         span: Span {
-                            str: "SUM(",
-                            start: 2,
-                            end: 6,
-                        },
-                        inner: [],
-                    },
-                    Pair {
-                        rule: expr,
-                        span: Span {
-                            str: "col",
-                            start: 7,
-                            end: 10,
+                            str: "s\"SUM({col})\"",
+                            start: 0,
+                            end: 13,
                         },
                         inner: [
                             Pair {
-                                rule: ident,
+                                rule: interpolate_string_inner,
+                                span: Span {
+                                    str: "SUM(",
+                                    start: 2,
+                                    end: 6,
+                                },
+                                inner: [],
+                            },
+                            Pair {
+                                rule: expr_call,
                                 span: Span {
                                     str: "col",
                                     start: 7,
                                     end: 10,
                                 },
+                                inner: [
+                                    Pair {
+                                        rule: expr,
+                                        span: Span {
+                                            str: "col",
+                                            start: 7,
+                                            end: 10,
+                                        },
+                                        inner: [
+                                            Pair {
+                                                rule: ident,
+                                                span: Span {
+                                                    str: "col",
+                                                    start: 7,
+                                                    end: 10,
+                                                },
+                                                inner: [],
+                                            },
+                                        ],
+                                    },
+                                ],
+                            },
+                            Pair {
+                                rule: interpolate_string_inner,
+                                span: Span {
+                                    str: ")",
+                                    start: 11,
+                                    end: 12,
+                                },
                                 inner: [],
                             },
                         ],
                     },
-                    Pair {
-                        rule: interpolate_string_inner,
-                        span: Span {
-                            str: ")",
-                            start: 11,
-                            end: 12,
-                        },
-                        inner: [],
-                    },
                 ],
             },
         ],
diff --git a/reference/tests/examples/transforms-10.prql b/reference/tests/examples/transforms-10.prql
index 12e9ff29..f655f463 100644
--- a/reference/tests/examples/transforms-10.prql
+++ b/reference/tests/examples/transforms-10.prql
@@ -1,5 +1,7 @@
 from employees
-aggregate [
-  average salary,
-  ct = count
-]
+group [title, country] (
+  aggregate [
+    average salary,
+    ct = count
+  ]
+)
diff --git a/reference/tests/examples/transforms-11.prql b/reference/tests/examples/transforms-11.prql
new file mode 100644
index 00000000..1d1d99b0
--- /dev/null
+++ b/reference/tests/examples/transforms-11.prql
@@ -0,0 +1,3 @@
+from employees
+sort join_date
+take 1
diff --git a/reference/tests/examples/transforms-12.prql b/reference/tests/examples/transforms-12.prql
new file mode 100644
index 00000000..12e9ff29
--- /dev/null
+++ b/reference/tests/examples/transforms-12.prql
@@ -0,0 +1,5 @@
+from employees
+aggregate [
+  average salary,
+  ct = count
+]
diff --git a/reference/tests/examples/transforms-4.prql b/reference/tests/examples/transforms-4.prql
index 63d11c6b..e019af01 100644
--- a/reference/tests/examples/transforms-4.prql
+++ b/reference/tests/examples/transforms-4.prql
@@ -1,2 +1,2 @@
 from employees
-take 10
+sort age
diff --git a/reference/tests/examples/transforms-5.prql b/reference/tests/examples/transforms-5.prql
index e019af01..9bf01131 100644
--- a/reference/tests/examples/transforms-5.prql
+++ b/reference/tests/examples/transforms-5.prql
@@ -1,2 +1,2 @@
 from employees
-sort age
+sort (-age)
diff --git a/reference/tests/examples/transforms-6.prql b/reference/tests/examples/transforms-6.prql
index 11706e8b..7809593b 100644
--- a/reference/tests/examples/transforms-6.prql
+++ b/reference/tests/examples/transforms-6.prql
@@ -1,2 +1,2 @@
 from employees
-join side:left positions [id==employee_id]
+sort [age, -tenure, +salary]
diff --git a/reference/tests/examples/transforms-7.prql b/reference/tests/examples/transforms-7.prql
index 3d9afde8..63d11c6b 100644
--- a/reference/tests/examples/transforms-7.prql
+++ b/reference/tests/examples/transforms-7.prql
@@ -1,2 +1,2 @@
 from employees
-join side:full positions [emp_no]
+take 10
diff --git a/reference/tests/examples/transforms-8.prql b/reference/tests/examples/transforms-8.prql
index f655f463..11706e8b 100644
--- a/reference/tests/examples/transforms-8.prql
+++ b/reference/tests/examples/transforms-8.prql
@@ -1,7 +1,2 @@
 from employees
-group [title, country] (
-  aggregate [
-    average salary,
-    ct = count
-  ]
-)
+join side:left positions [id==employee_id]
diff --git a/reference/tests/examples/transforms-9.prql b/reference/tests/examples/transforms-9.prql
index 1d1d99b0..3d9afde8 100644
--- a/reference/tests/examples/transforms-9.prql
+++ b/reference/tests/examples/transforms-9.prql
@@ -1,3 +1,2 @@
 from employees
-sort join_date
-take 1
+join side:full positions [emp_no]
diff --git a/reference/tests/snapshots/snapshot__run_reference_examples@transforms-10.prql.snap b/reference/tests/snapshots/snapshot__run_reference_examples@transforms-10.prql.snap
index 1faa0407..0f64eb4e 100644
--- a/reference/tests/snapshots/snapshot__run_reference_examples@transforms-10.prql.snap
+++ b/reference/tests/snapshots/snapshot__run_reference_examples@transforms-10.prql.snap
@@ -4,7 +4,12 @@ expression: sql
 input_file: reference/tests/examples/transforms-10.prql
 ---
 SELECT
+  title,
+  country,
   AVG(salary),
   COUNT(*) AS ct
 FROM
   employees
+GROUP BY
+  title,
+  country
diff --git a/reference/tests/snapshots/snapshot__run_reference_examples@transforms-11.prql.snap b/reference/tests/snapshots/snapshot__run_reference_examples@transforms-11.prql.snap
new file mode 100644
index 00000000..4c402627
--- /dev/null
+++ b/reference/tests/snapshots/snapshot__run_reference_examples@transforms-11.prql.snap
@@ -0,0 +1,13 @@
+---
+source: reference/tests/snapshot.rs
+expression: sql
+input_file: reference/tests/examples/transforms-11.prql
+---
+SELECT
+  employees.*
+FROM
+  employees
+ORDER BY
+  join_date
+LIMIT
+  1
diff --git a/reference/tests/snapshots/snapshot__run_reference_examples@transforms-12.prql.snap b/reference/tests/snapshots/snapshot__run_reference_examples@transforms-12.prql.snap
new file mode 100644
index 00000000..b20d3b8a
--- /dev/null
+++ b/reference/tests/snapshots/snapshot__run_reference_examples@transforms-12.prql.snap
@@ -0,0 +1,10 @@
+---
+source: reference/tests/snapshot.rs
+expression: sql
+input_file: reference/tests/examples/transforms-12.prql
+---
+SELECT
+  AVG(salary),
+  COUNT(*) AS ct
+FROM
+  employees
diff --git a/reference/tests/snapshots/snapshot__run_reference_examples@transforms-4.prql.snap b/reference/tests/snapshots/snapshot__run_reference_examples@transforms-4.prql.snap
index 32c11e33..7690de5a 100644
--- a/reference/tests/snapshots/snapshot__run_reference_examples@transforms-4.prql.snap
+++ b/reference/tests/snapshots/snapshot__run_reference_examples@transforms-4.prql.snap
@@ -7,5 +7,5 @@ SELECT
   employees.*
 FROM
   employees
-LIMIT
-  10
+ORDER BY
+  age
diff --git a/reference/tests/snapshots/snapshot__run_reference_examples@transforms-5.prql.snap b/reference/tests/snapshots/snapshot__run_reference_examples@transforms-5.prql.snap
index 42a11776..65ee96ad 100644
--- a/reference/tests/snapshots/snapshot__run_reference_examples@transforms-5.prql.snap
+++ b/reference/tests/snapshots/snapshot__run_reference_examples@transforms-5.prql.snap
@@ -8,4 +8,4 @@ SELECT
 FROM
   employees
 ORDER BY
-  age
+  age DESC
diff --git a/reference/tests/snapshots/snapshot__run_reference_examples@transforms-6.prql.snap b/reference/tests/snapshots/snapshot__run_reference_examples@transforms-6.prql.snap
index c4ae7533..018de05f 100644
--- a/reference/tests/snapshots/snapshot__run_reference_examples@transforms-6.prql.snap
+++ b/reference/tests/snapshots/snapshot__run_reference_examples@transforms-6.prql.snap
@@ -4,8 +4,10 @@ expression: sql
 input_file: reference/tests/examples/transforms-6.prql
 ---
 SELECT
-  employees.*,
-  positions.*
+  employees.*
 FROM
   employees
-  LEFT JOIN positions ON id = employee_id
+ORDER BY
+  age,
+  tenure DESC,
+  salary
diff --git a/reference/tests/snapshots/snapshot__run_reference_examples@transforms-7.prql.snap b/reference/tests/snapshots/snapshot__run_reference_examples@transforms-7.prql.snap
index a5a5483b..e6d499e5 100644
--- a/reference/tests/snapshots/snapshot__run_reference_examples@transforms-7.prql.snap
+++ b/reference/tests/snapshots/snapshot__run_reference_examples@transforms-7.prql.snap
@@ -4,9 +4,8 @@ expression: sql
 input_file: reference/tests/examples/transforms-7.prql
 ---
 SELECT
-  employees.*,
-  positions.*,
-  emp_no
+  employees.*
 FROM
-  employees FULL
-  JOIN positions USING(emp_no)
+  employees
+LIMIT
+  10
diff --git a/reference/tests/snapshots/snapshot__run_reference_examples@transforms-8.prql.snap b/reference/tests/snapshots/snapshot__run_reference_examples@transforms-8.prql.snap
index 2428c0f2..d954b346 100644
--- a/reference/tests/snapshots/snapshot__run_reference_examples@transforms-8.prql.snap
+++ b/reference/tests/snapshots/snapshot__run_reference_examples@transforms-8.prql.snap
@@ -4,12 +4,8 @@ expression: sql
 input_file: reference/tests/examples/transforms-8.prql
 ---
 SELECT
-  title,
-  country,
-  AVG(salary),
-  COUNT(*) AS ct
+  employees.*,
+  positions.*
 FROM
   employees
-GROUP BY
-  title,
-  country
+  LEFT JOIN positions ON id = employee_id
diff --git a/reference/tests/snapshots/snapshot__run_reference_examples@transforms-9.prql.snap b/reference/tests/snapshots/snapshot__run_reference_examples@transforms-9.prql.snap
index 5028495c..255ff6f0 100644
--- a/reference/tests/snapshots/snapshot__run_reference_examples@transforms-9.prql.snap
+++ b/reference/tests/snapshots/snapshot__run_reference_examples@transforms-9.prql.snap
@@ -4,10 +4,9 @@ expression: sql
 input_file: reference/tests/examples/transforms-9.prql
 ---
 SELECT
-  employees.*
+  employees.*,
+  positions.*,
+  emp_no
 FROM
-  employees
-ORDER BY
-  join_date
-LIMIT
-  1
+  employees FULL
+  JOIN positions USING(emp_no)