Fix multiline stab clause with trailing identifier (#20)

This commit is contained in:
Jonatan Kłosko 2021-12-27 22:56:00 +01:00 committed by GitHub
parent 1b3ecf7765
commit 94d6471cc8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 185 additions and 62 deletions

View File

@ -672,11 +672,22 @@ module.exports = grammar({
), ),
_call_arguments_without_parentheses: ($) => _call_arguments_without_parentheses: ($) =>
// Right precedence, because `fun1 fun2 x, y` is `fun1(fun2(x, y))` // In stab clauses a newline can either separate multiple body expressions
prec.right( // or multiple stab clauses, this falls under the $.body conflict. Given a
choice( // multiline stab clause with trailing identifier like `1 -> 1 \n x \n 2 -> x`,
seq(sep1($._expression, ","), optional(seq(",", $.keywords))), // there are two matching interpretations:
$.keywords // * `x` as identifier and `2` as stab argument
// * `x 2` call as stab argument
// Similarly for `Mod.fun` or `mod.fun` the newline should terminate the call.
// Consequently, we reject the second interpretation using dynamic precedence
prec.dynamic(
-1,
// Right precedence, because `fun1 fun2 x, y` is `fun1(fun2(x, y))`
prec.right(
choice(
seq(sep1($._expression, ","), optional(seq(",", $.keywords))),
$.keywords
)
) )
), ),

102
src/grammar.json generated
View File

@ -4791,24 +4791,46 @@
] ]
}, },
"_call_arguments_without_parentheses": { "_call_arguments_without_parentheses": {
"type": "PREC_RIGHT", "type": "PREC_DYNAMIC",
"value": 0, "value": -1,
"content": { "content": {
"type": "CHOICE", "type": "PREC_RIGHT",
"members": [ "value": 0,
{ "content": {
"type": "SEQ", "type": "CHOICE",
"members": [ "members": [
{ {
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {
"type": "SYMBOL", "type": "SEQ",
"name": "_expression" "members": [
}, {
{ "type": "SYMBOL",
"type": "REPEAT", "name": "_expression"
"content": { },
{
"type": "REPEAT",
"content": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": ","
},
{
"type": "SYMBOL",
"name": "_expression"
}
]
}
}
]
},
{
"type": "CHOICE",
"members": [
{
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {
@ -4817,41 +4839,23 @@
}, },
{ {
"type": "SYMBOL", "type": "SYMBOL",
"name": "_expression" "name": "keywords"
} }
] ]
},
{
"type": "BLANK"
} }
} ]
] }
}, ]
{ },
"type": "CHOICE", {
"members": [ "type": "SYMBOL",
{ "name": "keywords"
"type": "SEQ", }
"members": [ ]
{ }
"type": "STRING",
"value": ","
},
{
"type": "SYMBOL",
"name": "keywords"
}
]
},
{
"type": "BLANK"
}
]
}
]
},
{
"type": "SYMBOL",
"name": "keywords"
}
]
} }
}, },
"do_block": { "do_block": {

16
src/parser.c generated
View File

@ -380813,8 +380813,8 @@ static const TSParseActionEntry ts_parse_actions[] = {
[3028] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym__items_with_trailing_separator_repeat1, 2), [3028] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym__items_with_trailing_separator_repeat1, 2),
[3030] = {.entry = {.count = 1, .reusable = false}}, REDUCE(aux_sym__items_with_trailing_separator_repeat1, 2), [3030] = {.entry = {.count = 1, .reusable = false}}, REDUCE(aux_sym__items_with_trailing_separator_repeat1, 2),
[3032] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym__items_with_trailing_separator_repeat1, 2), SHIFT_REPEAT(741), [3032] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym__items_with_trailing_separator_repeat1, 2), SHIFT_REPEAT(741),
[3035] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__call_arguments_without_parentheses, 2), [3035] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__call_arguments_without_parentheses, 2, .dynamic_precedence = -1),
[3037] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym__call_arguments_without_parentheses, 2), [3037] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym__call_arguments_without_parentheses, 2, .dynamic_precedence = -1),
[3039] = {.entry = {.count = 1, .reusable = false}}, SHIFT(315), [3039] = {.entry = {.count = 1, .reusable = false}}, SHIFT(315),
[3041] = {.entry = {.count = 1, .reusable = true}}, SHIFT(5471), [3041] = {.entry = {.count = 1, .reusable = true}}, SHIFT(5471),
[3043] = {.entry = {.count = 1, .reusable = true}}, SHIFT(5469), [3043] = {.entry = {.count = 1, .reusable = true}}, SHIFT(5469),
@ -380961,8 +380961,8 @@ static const TSParseActionEntry ts_parse_actions[] = {
[3325] = {.entry = {.count = 1, .reusable = false}}, SHIFT(1257), [3325] = {.entry = {.count = 1, .reusable = false}}, SHIFT(1257),
[3327] = {.entry = {.count = 1, .reusable = false}}, SHIFT(1256), [3327] = {.entry = {.count = 1, .reusable = false}}, SHIFT(1256),
[3329] = {.entry = {.count = 1, .reusable = false}}, SHIFT(1253), [3329] = {.entry = {.count = 1, .reusable = false}}, SHIFT(1253),
[3331] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__call_arguments_without_parentheses, 1), [3331] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__call_arguments_without_parentheses, 1, .dynamic_precedence = -1),
[3333] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym__call_arguments_without_parentheses, 1), [3333] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym__call_arguments_without_parentheses, 1, .dynamic_precedence = -1),
[3335] = {.entry = {.count = 1, .reusable = false}}, SHIFT(443), [3335] = {.entry = {.count = 1, .reusable = false}}, SHIFT(443),
[3337] = {.entry = {.count = 1, .reusable = false}}, SHIFT(337), [3337] = {.entry = {.count = 1, .reusable = false}}, SHIFT(337),
[3339] = {.entry = {.count = 1, .reusable = false}}, SHIFT(630), [3339] = {.entry = {.count = 1, .reusable = false}}, SHIFT(630),
@ -381019,10 +381019,10 @@ static const TSParseActionEntry ts_parse_actions[] = {
[3442] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_block, 6), [3442] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_block, 6),
[3444] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_block, 6), [3444] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_block, 6),
[3446] = {.entry = {.count = 1, .reusable = false}}, SHIFT(1245), [3446] = {.entry = {.count = 1, .reusable = false}}, SHIFT(1245),
[3448] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__call_arguments_without_parentheses, 4), [3448] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__call_arguments_without_parentheses, 4, .dynamic_precedence = -1),
[3450] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym__call_arguments_without_parentheses, 4), [3450] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym__call_arguments_without_parentheses, 4, .dynamic_precedence = -1),
[3452] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__call_arguments_without_parentheses, 3), [3452] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__call_arguments_without_parentheses, 3, .dynamic_precedence = -1),
[3454] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym__call_arguments_without_parentheses, 3), [3454] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym__call_arguments_without_parentheses, 3, .dynamic_precedence = -1),
[3456] = {.entry = {.count = 1, .reusable = false}}, SHIFT(1497), [3456] = {.entry = {.count = 1, .reusable = false}}, SHIFT(1497),
[3458] = {.entry = {.count = 1, .reusable = false}}, SHIFT(309), [3458] = {.entry = {.count = 1, .reusable = false}}, SHIFT(309),
[3460] = {.entry = {.count = 1, .reusable = false}}, SHIFT(1500), [3460] = {.entry = {.count = 1, .reusable = false}}, SHIFT(1500),

View File

@ -575,6 +575,114 @@ fun do->end
(do_block (do_block
(stab_clause)))) (stab_clause))))
=====================================
stab clause / edge cases / trailing call in multiline clause
=====================================
fun do
1 ->
1
x
1 ->
1
end
fun do
1 ->
1
Mod.fun
1 ->
1
end
fun do
1 ->
1
mod.fun
1 ->
1
end
fun do
1 ->
1
x 1 ->
1
end
---
(source
(call
(identifier)
(do_block
(stab_clause
(arguments
(integer))
(body
(integer)
(identifier)))
(stab_clause
(arguments
(integer))
(body
(integer)))))
(call
(identifier)
(do_block
(stab_clause
(arguments
(integer))
(body
(integer)
(call
(dot
(alias)
(identifier)))))
(stab_clause
(arguments
(integer))
(body
(integer)))))
(call
(identifier)
(do_block
(stab_clause
(arguments
(integer))
(body
(integer)
(call
(dot
(identifier)
(identifier)))))
(stab_clause
(arguments
(integer))
(body
(integer)))))
(call
(identifier)
(do_block
(stab_clause
(arguments
(integer))
(body
(integer)))
(stab_clause
(arguments
(call
(identifier)
(arguments
(integer))))
(body
(integer))))))
===================================== =====================================
pattern matching pattern matching
===================================== =====================================