handle stab clauses without right-hand-sides
Currently a stab clause without a right-hand-side is parsed as an error: ```elixir Enum.map(xs, fn x -> end) ``` And the `end` token ends up not being highlighted as a keyword. The compiler gives a warning about this syntax but it comes up pretty often when editing (writing a `case` block for example). Implementation-wise, this might be a bug in tree-sitter? `prec.right` seems to fight with error recovery when the rightmost token(s) are `optional`. ```elixir fn -> end ``` gets parsed as ```scm (anonymous_function (stab_clause right: (body (identifier))) (MISSING "end")) ``` although the `optional` should allow this case. I've seen this in other grammars and it seems like the way around it is to replace the `prec.right` with a conflict.
This commit is contained in:
parent
c68c4ad72f
commit
662426cd85
31
grammar.js
31
grammar.js
@ -159,6 +159,16 @@ module.exports = grammar({
|
|||||||
// * stab arguments item in `arg1, left when right ->`
|
// * stab arguments item in `arg1, left when right ->`
|
||||||
[$.binary_operator, $._stab_clause_arguments_without_parentheses],
|
[$.binary_operator, $._stab_clause_arguments_without_parentheses],
|
||||||
|
|
||||||
|
// Given `( -> • \n`, the newline could be either:
|
||||||
|
// * stab clause without a body
|
||||||
|
// * stab clause with a body
|
||||||
|
[$._stab_clause_without_body, $._stab_clause_with_body],
|
||||||
|
|
||||||
|
// Given `( -> • /`, `/` token could be either:
|
||||||
|
// * stab clause with a body
|
||||||
|
// * -> as an operator followed by `/`
|
||||||
|
[$._stab_clause_with_body, $.operator_identifier],
|
||||||
|
|
||||||
// Given `((arg1, arg2 • ,`, `arg3` expression can be either:
|
// Given `((arg1, arg2 • ,`, `arg3` expression can be either:
|
||||||
// * stab parenthesised arguments item in `((arg1, arg2, arg3) ->)`
|
// * stab parenthesised arguments item in `((arg1, arg2, arg3) ->)`
|
||||||
// * stab non-parenthesised arguments item in `((arg1, arg2, arg3 ->))`
|
// * stab non-parenthesised arguments item in `((arg1, arg2, arg3 ->))`
|
||||||
@ -729,13 +739,20 @@ module.exports = grammar({
|
|||||||
),
|
),
|
||||||
|
|
||||||
stab_clause: ($) =>
|
stab_clause: ($) =>
|
||||||
// Right precedence, because we want to consume body if any
|
choice($._stab_clause_with_body, $._stab_clause_without_body),
|
||||||
prec.right(
|
|
||||||
seq(
|
_stab_clause_with_body: ($) =>
|
||||||
optional(field("left", $._stab_clause_left)),
|
seq(
|
||||||
field("operator", "->"),
|
optional(field("left", $._stab_clause_left)),
|
||||||
optional(field("right", $.body))
|
field("operator", "->"),
|
||||||
)
|
field("right", $.body)
|
||||||
|
),
|
||||||
|
|
||||||
|
_stab_clause_without_body: ($) =>
|
||||||
|
seq(
|
||||||
|
optional(field("left", $._stab_clause_left)),
|
||||||
|
field("operator", "->"),
|
||||||
|
optional($._terminator)
|
||||||
),
|
),
|
||||||
|
|
||||||
_stab_clause_left: ($) =>
|
_stab_clause_left: ($) =>
|
||||||
|
@ -683,6 +683,28 @@ end
|
|||||||
(body
|
(body
|
||||||
(integer))))))
|
(integer))))))
|
||||||
|
|
||||||
|
=====================================
|
||||||
|
stab clause / edge cases / empty right-hand-sides
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
fun do
|
||||||
|
x ->
|
||||||
|
y ->
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(source
|
||||||
|
(call
|
||||||
|
(identifier)
|
||||||
|
(do_block
|
||||||
|
(stab_clause
|
||||||
|
(arguments
|
||||||
|
(identifier)))
|
||||||
|
(stab_clause
|
||||||
|
(arguments
|
||||||
|
(identifier))))))
|
||||||
|
|
||||||
=====================================
|
=====================================
|
||||||
pattern matching
|
pattern matching
|
||||||
=====================================
|
=====================================
|
||||||
|
@ -41,6 +41,12 @@ fn x, y, z ->
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
fn ->
|
||||||
|
# <- keyword
|
||||||
|
# ^ operator
|
||||||
|
end
|
||||||
|
# <- keyword
|
||||||
|
|
||||||
&Set.put(&1, &2)
|
&Set.put(&1, &2)
|
||||||
# <- operator
|
# <- operator
|
||||||
# ^ module
|
# ^ module
|
||||||
|
Loading…
x
Reference in New Issue
Block a user