Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for pattern matching #140

Merged
merged 2 commits into from
Jan 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 38 additions & 12 deletions grammar.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ module.exports = grammar({
[$.tuple, $.tuple_pattern],
[$.list, $.list_pattern],
[$.with_item, $._collection_elements],
[$.named_expression, $.as_pattern],
[$.match_statement, $.primary_expression],
],

supertypes: $ => [
Expand Down Expand Up @@ -228,7 +230,8 @@ module.exports = grammar({
$.with_statement,
$.function_definition,
$.class_definition,
$.decorated_definition
$.decorated_definition,
$.match_statement,
),

if_statement: $ => seq(
Expand All @@ -253,6 +256,22 @@ module.exports = grammar({
field('body', $._suite)
),

match_statement: $ => seq(
'match',
commaSep1(field('subject', $.expression)),
optional(','),
':',
repeat(field('alternative', $.case_clause))),

case_clause: $ => seq(
'case',
commaSep1(field('pattern', choice($.expression, $.list_splat_pattern))),
optional(','),
optional(field('guard', $.if_clause)),
':',
field('consequence', $._suite)
),

for_statement: $ => seq(
optional('async'),
'for',
Expand Down Expand Up @@ -320,10 +339,6 @@ module.exports = grammar({

with_item: $ => prec.dynamic(-1, seq(
field('value', $.expression),
optional(seq(
'as',
field('alias', $.pattern)
))
)),

function_definition: $ => seq(
Expand Down Expand Up @@ -479,6 +494,7 @@ module.exports = grammar({

pattern: $ => choice(
$.identifier,
alias("match", $.identifier), // ambiguity with match statement: only ":" at end of line decides if "match" keyword
$.keyword_identifier,
$.subscript,
$.attribute,
Expand Down Expand Up @@ -523,6 +539,14 @@ module.exports = grammar({
choice($.identifier, $.keyword_identifier, $.subscript, $.attribute)
),

// Extended patterns (patterns allowed in match statement are far more flexible than simple patterns though still a subset of "expression")

as_pattern: $ => prec.left(seq(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or call this alias_expression?

Copy link
Contributor Author

@theHamsta theHamsta Dec 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The patterns in a match case are a subset of expressions. I simplified using expression here since I didn't want to replicated all the new patterns that basically follow the same rules as expressions.

$.expression,
'as',
field('alias', $.expression)
)),

// Expressions

_expression_within_for_in_clause: $ => choice(
Expand All @@ -538,12 +562,14 @@ module.exports = grammar({
$.lambda,
$.primary_expression,
$.conditional_expression,
$.named_expression
$.named_expression,
$.as_pattern
),

primary_expression: $ => choice(
$.binary_operator,
$.identifier,
alias("match", $.identifier),
theHamsta marked this conversation as resolved.
Show resolved Hide resolved
$.keyword_identifier,
$.string,
$.concatenated_string,
Expand Down Expand Up @@ -632,8 +658,8 @@ module.exports = grammar({
'is',
seq('is', 'not')
)),
$.primary_expression
))
$.primary_expression
))
)),

lambda: $ => prec(PREC.lambda, seq(
Expand Down Expand Up @@ -670,7 +696,7 @@ module.exports = grammar({

_left_hand_side: $ => choice(
$.pattern,
$.pattern_list
$.pattern_list,
),

pattern_list: $ => seq(
Expand Down Expand Up @@ -750,7 +776,7 @@ module.exports = grammar({
type: $ => $.expression,

keyword_argument: $ => seq(
field('name', choice($.identifier, $.keyword_identifier)),
field('name', choice($.identifier, $.keyword_identifier, alias("match", $.identifier))),
'=',
field('value', $.expression)
),
Expand Down Expand Up @@ -974,10 +1000,10 @@ module.exports = grammar({
}
})

function commaSep1 (rule) {
function commaSep1(rule) {
return sep1(rule, ',')
}

function sep1 (rule, separator) {
function sep1(rule, separator) {
return seq(rule, repeat(seq(separator, rule)))
}
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
"author": "Max Brunsfeld",
"license": "MIT",
"dependencies": {
"nan": "^2.14.0"
"nan": "^2.15.0"
},
"devDependencies": {
"tree-sitter-cli": "^0.19.3"
"tree-sitter-cli": "^0.20.1"
},
"scripts": {
"build": "tree-sitter generate && node-gyp build",
Expand Down
2 changes: 2 additions & 0 deletions queries/highlights.scm
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,6 @@
"while"
"with"
"yield"
"match"
"case"
] @keyword
Loading