Skip to content

Conversation

@doorgan
Copy link
Contributor

@doorgan doorgan commented Jan 31, 2026

In the elixir parser there is a rule that allows when to bind to a bracketless keyword list(no_parens_op_expr -> when_op_eol call_args_no_parens_kw).

Spitfire doesn't have that rule, so this code:

+with a <- b, do: c when a (from property tests)

parses incorrectly as:

{
  :+,
  [line: 1, column: 1],
  [
    {
      :with,
      [line: 1, column: 2],
      [
        {
          :<-,
          [line: 1, column: 9],
          [{:a, [line: 1, column: 7], nil}, {:b, [line: 1, column: 12], nil}]
        },
        {:when, [line: 1, column: 21], [[do: {:c, [line: 1, column: 19], nil}], {:a, [line: 1, column: 26], nil}]}
      ]
    }
  ]
}

when Elixir produces this:

{
  :+,
  [line: 1, column: 1],
  [
    {
      :with,
      [line: 1, column: 2],
      [
        {
          :<-,
          [line: 1, column: 9],
          [{:a, [line: 1, column: 7], nil}, {:b, [line: 1, column: 12], nil}]
        },
        [do: {:when, [line: 1, column: 21], [{:c, [line: 1, column: 19], nil}, {:a, [line: 1, column: 26], nil}]}]
      ]
    }
  ]
}

The fix here is the same as #85, we need to use @list_comma to ensure the correct associativity for them.

In the elixir parser there is a rule that allows `when` to bind to a
bracketless keyword list(`no_parens_op_expr` -> `when_op_eol
call_args_no_parens_kw`).

Spitfire doesn't have that rule, so this code:

`+with a <- b, do: c when a` (from property tests)

parses incorrectly as:

```elixir
{
  :+,
  [line: 1, column: 1],
  [
    {
      :with,
      [line: 1, column: 2],
      [
        {
          :<-,
          [line: 1, column: 9],
          [{:a, [line: 1, column: 7], nil}, {:b, [line: 1, column: 12], nil}]
        },
        {:when, [line: 1, column: 21], [[do: {:c, [line: 1, column: 19], nil}], {:a, [line: 1, column: 26], nil}]}
      ]
    }
  ]
}
```

when Elixir produces this:

```elixir
{
  :+,
  [line: 1, column: 1],
  [
    {
      :with,
      [line: 1, column: 2],
      [
        {
          :<-,
          [line: 1, column: 9],
          [{:a, [line: 1, column: 7], nil}, {:b, [line: 1, column: 12], nil}]
        },
        [do: {:when, [line: 1, column: 21], [{:c, [line: 1, column: 19], nil}, {:a, [line: 1, column: 26], nil}]}]
      ]
    }
  ]
}
```

The fix here is the same as elixir-tools#85, we need to use `@list_comma` to
ensure the correct associativity for them.
@mhanberg mhanberg merged commit 91b5d5b into elixir-tools:main Jan 31, 2026
37 checks passed
@doorgan doorgan deleted the doorgan/bracketless-kw-associativity branch February 1, 2026 04:39
mhanberg pushed a commit that referenced this pull request Feb 4, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.3.2](v0.3.1...v0.3.2)
(2026-02-01)


### Bug Fixes

* associativity in bracketless kw list
([#89](#89))
([91b5d5b](91b5d5b))
* extract newlines only from newline carrying tokens
([#86](#86))
([edba800](edba800))
* improve handling of matched/unmatched expressions
([#88](#88))
([dd45cb1](dd45cb1))
* keyword list associativity
([#85](#85))
([a7d2a54](a7d2a54))
* parse ellipsis_op as unary operator
([#83](#83))
([e86f1f4](e86f1f4))
* rearrange `!(left) in right`
([#91](#91))
([fae2579](fae2579))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants