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(field("parameters", $.function_parameters)),
optional(seq("->", field("return_type", $._type))), optional(seq("->", field("return_type", $._type))),
"{", "{",
alias($._expression_seq, $.function_body),
"}" "}"
), ),
function_parameters: ($) => function_parameters: ($) =>
@ -267,31 +268,90 @@ module.exports = grammar({
), ),
optional($._type_annotation) optional($._type_annotation)
), ),
_labelled_discard_param: ($) => _labelled_discard_param: ($) =>
seq(field("label", $.identifier), $._discard_name), seq(field("label", $.identifier), $._discard_name),
_discard_param: ($) => $._discard_name, _discard_param: ($) => $._discard_name,
_labelled_name_param: ($) => _labelled_name_param: ($) =>
seq(field("label", $.identifier), field("name", $.identifier)), seq(field("label", $.identifier), field("name", $.identifier)),
_name_param: ($) => field("name", $.identifier), _name_param: ($) => field("name", $.identifier),
// This method diverges from the parser's `parse_expression_seq` somewhat.
/* Literals */ // The parser considers all expressions after a `try` to be part of its AST
_literal: ($) => // 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( choice(
$.var,
$.discard_var,
$.remote_constructor_pattern,
$.constructor_pattern,
$.string, $.string,
$.float,
$.integer, $.integer,
$.tuple, $.float,
$.list $.constructor_tuple,
// $.bit_string, $.constructor_bitstring,
// $.record, $.constructor_list
// $.remote_record ),
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(
$.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\"\\]|[^\"])*\"/, string: ($) => /\"(?:\\[efnrt\"\\]|[^\"])*\"/,
float: ($) => /-?[0-9_]+\.[0-9_]+/, float: ($) => /-?[0-9_]+\.[0-9_]+/,
integer: ($) => /-?[0-9_]+/, integer: ($) => /-?[0-9_]+/,
tuple: ($) => seq("#", "(", optional(series_of($._literal, ",")), ")"),
list: ($) => seq("[", optional(series_of($._literal, ",")), "]"),
bit_string: ($) => bit_string: ($) =>
seq("<<", optional(series_of($.bit_string_segment, ",")), ">>"), seq("<<", optional(series_of($.bit_string_segment, ",")), ">>"),
bit_string_segment: ($) => bit_string_segment: ($) =>

@ -1484,6 +1484,15 @@
"type": "STRING", "type": "STRING",
"value": "{" "value": "{"
}, },
{
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "_expression_seq"
},
"named": true,
"value": "function_body"
},
{ {
"type": "STRING", "type": "STRING",
"value": "}" "value": "}"
@ -1624,6 +1633,63 @@
"name": "identifier" "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": { "_literal": {
"type": "CHOICE", "type": "CHOICE",
"members": [ "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", "type": "string",
"named": true "named": true
}, },
{
"type": "todo",
"named": false
},
{
"type": "try",
"named": false
},
{ {
"type": "type", "type": "type",
"named": false "named": false

File diff suppressed because it is too large Load Diff