WIP: Most of "patterns"

pull/204/head
Jonathan Arnett 2021-12-19 22:14:44 +07:00
parent fd348b11c3
commit 4f1cee304c
4 changed files with 3530 additions and 3007 deletions

@ -253,6 +253,7 @@ module.exports = grammar({
optional(field("parameters", $.function_parameters)),
optional(seq("->", field("return_type", $._type))),
"{",
alias($._expression_seq, $.function_body),
"}"
),
function_parameters: ($) =>
@ -267,31 +268,90 @@ module.exports = grammar({
),
optional($._type_annotation)
),
_labelled_discard_param: ($) =>
seq(field("label", $.identifier), $._discard_name),
_discard_param: ($) => $._discard_name,
_labelled_name_param: ($) =>
seq(field("label", $.identifier), field("name", $.identifier)),
_name_param: ($) => field("name", $.identifier),
/* Literals */
_literal: ($) =>
// This method diverges from the parser's `parse_expression_seq` somewhat.
// The parser considers all expressions after a `try` to be part of its AST
// node, namely the "then" section. Gleam code like this:
//
// try int_a = parse(a)
// try int_b = parse(b)
// Ok(int_a + int_b)
//
// is parsed as:
//
// (try
// pattern: (pattern)
// value: (call (identifier))
// then: (try
// pattern: (pattern)
// value: (call (identifier))
// then: (type_constructor (...))))
//
// This makes sense for the parser, but (IMO) would be more confusing for
// users and tooling which don't think about `try`s as having a "then". Thus,
// `try`s are essentially treated the same as any other expression.
_expression_seq: ($) =>
repeat1(
choice(
seq(
"try",
$._pattern,
optional($._type_annotation),
"=",
$._expression
),
$._expression
)
),
_pattern: ($) =>
seq(
choice(
$.var,
$.discard_var,
$.remote_constructor_pattern,
$.constructor_pattern,
$.string,
$.integer,
$.float,
$.constructor_tuple,
$.constructor_bitstring,
$.constructor_list
),
optional(seq("as", alias($._name, $.pattern_assign)))
),
_expression: ($) => "todo",
var: ($) => $._name,
discard_var: ($) => $._discard_name,
remote_constructor_pattern: ($) => seq($._name, $._constructor_pattern),
constructor_pattern: ($) => $._constructor_pattern,
_constructor_pattern: ($) =>
seq($._upname, optional($.pattern_constructor_args)),
pattern_constructor_args: ($) =>
seq(
"(",
optional(series_of($._pattern_constructor_arg, ",")),
optional($.pattern_spread),
")"
),
_pattern_constructor_arg: ($) =>
choice(
$.string,
$.float,
$.integer,
$.tuple,
$.list
// $.bit_string,
// $.record,
// $.remote_record
$.pattern_constructor_named_arg,
alias($.constructor_pattern, $.pattern_constructor_unnamed_arg)
),
pattern_constructor_named_arg: ($) =>
seq($._name, ":", $.constructor_pattern),
pattern_spread: ($) => seq("..", optional(",")),
/* Literals */
string: ($) => /\"(?:\\[efnrt\"\\]|[^\"])*\"/,
float: ($) => /-?[0-9_]+\.[0-9_]+/,
integer: ($) => /-?[0-9_]+/,
tuple: ($) => seq("#", "(", optional(series_of($._literal, ",")), ")"),
list: ($) => seq("[", optional(series_of($._literal, ",")), "]"),
bit_string: ($) =>
seq("<<", optional(series_of($.bit_string_segment, ",")), ">>"),
bit_string_segment: ($) =>

@ -1484,6 +1484,15 @@
"type": "STRING",
"value": "{"
},
{
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "_expression_seq"
},
"named": true,
"value": "function_body"
},
{
"type": "STRING",
"value": "}"
@ -1624,6 +1633,63 @@
"name": "identifier"
}
},
"_expression_seq": {
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "try"
},
{
"type": "SYMBOL",
"name": "_pattern"
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "_type_annotation"
},
{
"type": "BLANK"
}
]
},
{
"type": "STRING",
"value": "="
},
{
"type": "SYMBOL",
"name": "_expression"
},
{
"type": "SYMBOL",
"name": "_expression_seq"
}
]
},
{
"type": "REPEAT1",
"content": {
"type": "SYMBOL",
"name": "_expression"
}
}
]
},
"_pattern": {
"type": "STRING",
"value": "todo"
},
"_expression": {
"type": "STRING",
"value": "todo"
},
"_literal": {
"type": "CHOICE",
"members": [

@ -539,6 +539,64 @@
}
]
}
},
"children": {
"multiple": false,
"required": true,
"types": [
{
"type": "function_body",
"named": true
}
]
}
},
{
"type": "function_body",
"named": true,
"fields": {
"type": {
"multiple": true,
"required": false,
"types": [
{
"type": ".",
"named": false
},
{
"type": "function_type",
"named": true
},
{
"type": "remote_type",
"named": true
},
{
"type": "remote_type_constructor",
"named": true
},
{
"type": "tuple_type",
"named": true
},
{
"type": "type",
"named": true
},
{
"type": "type_constructor",
"named": true
},
{
"type": "type_hole",
"named": true
},
{
"type": "type_var",
"named": true
}
]
}
}
},
{
@ -1583,6 +1641,14 @@
"type": "string",
"named": true
},
{
"type": "todo",
"named": false
},
{
"type": "try",
"named": false
},
{
"type": "type",
"named": false

File diff suppressed because it is too large Load Diff