|
@@ -10,8 +10,9 @@ const LF = /[\n]+/
|
|
|
const Text = /'[^']*'|"[^"]*"/
|
|
|
const Int = /\-?0[xX][0-9A-Fa-f]+|\-?0[oO][0-7]+|\-?0[bB][01]+|\-?\d+/
|
|
|
const Float = /\-?\d+(\.\d+)?[Ee][\+\-]?\d+|\-?\d+\.\d+/
|
|
|
+const Byte = /\\x[0-9A-Fa-f][0-9A-Fa-f]/
|
|
|
const Char = /`.`|\\u[0-9A-Fa-f]+|\\[a-z]/
|
|
|
-const Name = /[^0-9\{\}\[\]\(\)\.,:;\&\|\\'"` \t\r \n][^\{\}\[\]\(\)\.,:;\&\|\\'"` \t\r \n]*/
|
|
|
+const Name = /[^0-9\{\}\[\]\(\)\.,:;@\&\|\\'"` \t\r \n][^\{\}\[\]\(\)\.,:;@\&\|\\'"` \t\r \n]*/
|
|
|
|
|
|
const IgnoreRule = $ => Comment
|
|
|
const IgnoreTokens = [Blank, LF]
|
|
@@ -40,93 +41,86 @@ module.exports = grammar({
|
|
|
return rules
|
|
|
})({
|
|
|
// RULES
|
|
|
- source_file: $ => repeat($.stmt),
|
|
|
- stmt: $ => choice($.decl_entry, $.decl_type, $.decl_op, $.decl_method, $.decl_const, $.decl_msg),
|
|
|
+ source_file: $ => seq($.ns, repeat($.stmt)),
|
|
|
+ ns: $ => seq('namespace', optional($.name), '::'),
|
|
|
+ name: $ => Name,
|
|
|
+ stmt: $ => choice($.decl_entry, $.decl_type, $.decl_func, $.decl_const, $.decl_method),
|
|
|
decl_entry: $ => seq('entry', $.block),
|
|
|
decl_type: $ => seq(optional($.docs), 'type', $.name, optional($.type_params), optional($.impl), $.type_def),
|
|
|
type_params: $ => seq('[', optional(seq($.name, repeat(seq(',', $.name)))), ']'),
|
|
|
- name: $ => Name,
|
|
|
docs: $ => repeat1($.doc),
|
|
|
doc: $ => Doc,
|
|
|
impl: $ => seq('(', optional(seq($.ref_base, repeat(seq(',', $.ref_base)))), ')'),
|
|
|
- ref_base: $ => seq(optional($.module_prefix), $.name),
|
|
|
- module_prefix: $ => seq($.name, '::'),
|
|
|
- type_def: $ => choice('native', $.interface, $.record, $.union),
|
|
|
- interface: $ => seq(optional('service'), 'interface', '{', optional(seq($.method, repeat(seq(',', $.method)))), '}'),
|
|
|
- method: $ => seq(optional($.docs), $.name, $.type),
|
|
|
- record: $ => seq(optional('open'), optional('data'), 'record', $.record_def),
|
|
|
+ ref_base: $ => seq(optional($.ns_prefix), $.name),
|
|
|
+ ns_prefix: $ => seq($.name, '::'),
|
|
|
+ type_def: $ => choice('native', $.record, $.interface, $.union, $.enum),
|
|
|
+ record: $ => seq('record', $.record_def),
|
|
|
record_def: $ => seq('{', optional(seq($.field, repeat(seq(',', $.field)))), '}'),
|
|
|
field: $ => seq(optional($.docs), $.name, $.type, optional($.field_default)),
|
|
|
field_default: $ => seq('default', '(', $.expr, ')'),
|
|
|
- union: $ => seq(optional('data'), 'union', '{', optional(seq($.union_item, repeat(seq('|', $.union_item)))), '}'),
|
|
|
- union_item: $ => choice($.union_item_def_const, $.union_item_use_type),
|
|
|
- union_item_def_const: $ => seq('const', seq($.union_const_def, repeat(seq(',', $.union_const_def)))),
|
|
|
- union_const_def: $ => seq(optional($.docs), $.name),
|
|
|
- union_item_use_type: $ => $.type,
|
|
|
- decl_op: $ => seq(optional($.docs), optional('public'), 'operator', optional(choice('infix', 'variadic')), $.name, $.sig, $.body),
|
|
|
+ interface: $ => seq('interface', '{', optional(seq($.method, repeat(seq(',', $.method)))), '}'),
|
|
|
+ method: $ => seq(optional($.docs), $.name, $.type),
|
|
|
+ union: $ => seq('union', '{', seq($.type, repeat(seq(',', $.type))), '}'),
|
|
|
+ enum: $ => seq('enum', '{', seq($.enum_item, repeat(seq(',', $.enum_item))), '}'),
|
|
|
+ enum_item: $ => seq(optional($.docs), $.name),
|
|
|
+ decl_func: $ => seq(optional($.docs), choice('function', 'operator'), optional('variadic'), $.name, $.sig, $.body),
|
|
|
sig: $ => seq(optional($.type_params), $.inputs, optional($.implicit), $.output),
|
|
|
inputs: $ => $.record_def,
|
|
|
implicit: $ => $.inputs,
|
|
|
output: $ => $.type,
|
|
|
body: $ => choice($.native_body, $.block),
|
|
|
native_body: $ => seq('native', '(', $.text, ')'),
|
|
|
- decl_method: $ => seq(optional($.docs), optional('public'), 'method', $.receiver, '.', $.name, $.type, $.body),
|
|
|
+ decl_const: $ => seq(optional($.docs), 'const', $.name, $.type, $.body),
|
|
|
+ decl_method: $ => seq(optional($.docs), 'method', $.receiver, '.', $.name, $.type, $.body),
|
|
|
receiver: $ => $.name,
|
|
|
- decl_const: $ => seq(optional($.docs), optional('public'), 'const', $.name, $.type, $.body),
|
|
|
- decl_msg: $ => seq(optional($.docs), optional('public'), 'message', $.msg_lang, $.name, $.inputs, $.msg_expr),
|
|
|
- msg_lang: $ => $.name,
|
|
|
- msg_expr: $ => choice($.msg_expr_sp, $.msg_expr_plain),
|
|
|
- msg_expr_sp: $ => seq($.msg_singular, $.msg_plural),
|
|
|
- msg_singular: $ => seq('singular', '(', $.string, ')'),
|
|
|
- msg_plural: $ => seq('plural', '(', $.string, ')'),
|
|
|
- msg_expr_plain: $ => $.string,
|
|
|
type: $ => $.ref,
|
|
|
ref: $ => seq($.ref_base, optional($.type_args)),
|
|
|
type_args: $ => seq('[', optional(seq($.type, repeat(seq(',', $.type)))), ']'),
|
|
|
expr: $ => seq(repeat($.cast), $.term, repeat($.pipe)),
|
|
|
cast: $ => seq('(', '[', $.type, ']', ')'),
|
|
|
- pipe: $ => choice($.pipe_call, $.pipe_ufcs, $.pipe_cast, $.pipe_get, $.pipe_interior),
|
|
|
+ pipe: $ => choice($.pipe_call, $.pipe_infix, $.pipe_cast, $.pipe_get, $.pipe_interior),
|
|
|
pipe_call: $ => choice($.call_ordered, $.call_unordered),
|
|
|
call_ordered: $ => seq('(', optional(seq($.expr, repeat(seq(',', $.expr)))), ')'),
|
|
|
call_unordered: $ => seq('{', optional(seq($.arg_mapping, repeat(seq(',', $.arg_mapping)))), '}'),
|
|
|
arg_mapping: $ => seq($.name, optional($.arg_mapping_to)),
|
|
|
arg_mapping_to: $ => seq(':', $.expr),
|
|
|
- pipe_ufcs: $ => seq('|', $.ref, $.pipe_call),
|
|
|
+ pipe_infix: $ => seq('|', $.ref, $.pipe_call),
|
|
|
pipe_cast: $ => seq('.', $.cast),
|
|
|
pipe_get: $ => seq('.', $.name),
|
|
|
pipe_interior: $ => seq('.', '(', $.ref_base, ')'),
|
|
|
- term: $ => choice($.infix, $.lambda, $.if, $.when, $.block, $.ref_term, $.char, $.int, $.float, $.string),
|
|
|
- infix: $ => seq('(', $.infix_left, $.operator, $.infix_right, ')'),
|
|
|
+ term: $ => choice($.infix_term, $.lambda, $.if, $.when, $.block, $.ref_term, $.int, $.float, $.char, $.bytes, $.string),
|
|
|
+ infix_term: $ => seq('(', $.infix_left, $.operator, $.infix_right, ')'),
|
|
|
infix_left: $ => $.expr,
|
|
|
operator: $ => $.ref,
|
|
|
infix_right: $ => $.expr,
|
|
|
- lambda: $ => seq('{', '&', optional($.input_names), optional($.rec), '=>', $.expr, '}'),
|
|
|
- input_names: $ => seq('(', seq($.name, repeat(seq(',', $.name))), ')'),
|
|
|
- rec: $ => seq('rec', '(', $.name, ')'),
|
|
|
- if: $ => seq('if', '(', $.cond, ')', $.if_yes, repeat($.elif), 'else', $.if_no),
|
|
|
- cond: $ => $.expr,
|
|
|
- if_yes: $ => $.block,
|
|
|
- if_no: $ => $.block,
|
|
|
- elif: $ => seq('else', 'if', '(', $.cond, ')', $.block),
|
|
|
- when: $ => seq('when', '(', seq($.expr, repeat(seq(',', $.expr))), ')', '{', seq($.branch, repeat(seq(',', $.branch))), '}'),
|
|
|
- branch: $ => seq(seq($.branch_pattern, repeat(seq('|', $.branch_pattern))), optional($.input_names), '=>', $.expr),
|
|
|
- branch_pattern: $ => choice('else', $.pattern),
|
|
|
+ lambda: $ => seq('{', optional($.pattern), optional($.lambda_self), '=>', $.expr, '}'),
|
|
|
+ lambda_self: $ => seq('&', $.name),
|
|
|
pattern: $ => choice($.pattern_single, $.pattern_multiple),
|
|
|
pattern_single: $ => $.name,
|
|
|
pattern_multiple: $ => seq('(', seq($.name, repeat(seq(',', $.name))), ')'),
|
|
|
+ if: $ => seq('if', '(', seq($.cond, repeat(seq(',', $.cond))), ')', $.if_yes, repeat($.elif), 'else', $.if_no),
|
|
|
+ cond: $ => seq(optional($.cond_pattern), $.expr),
|
|
|
+ cond_pattern: $ => seq('let', $.pattern, '='),
|
|
|
+ if_yes: $ => $.block,
|
|
|
+ if_no: $ => $.block,
|
|
|
+ elif: $ => seq('if', '(', seq($.cond, repeat(seq(',', $.cond))), ')', $.block),
|
|
|
+ when: $ => seq('when', '(', $.expr, ')', '{', seq($.case, repeat(seq(',', $.case))), '}'),
|
|
|
+ case: $ => seq(seq($.name, repeat(seq('|', $.name))), optional($.pattern), '=>', $.expr),
|
|
|
block: $ => seq('{', repeat($.binding), $.expr, '}'),
|
|
|
binding: $ => choice($.binding_plain, $.binding_cps),
|
|
|
- binding_plain: $ => seq('let', $.pattern, ':=', $.expr, ','),
|
|
|
- binding_cps: $ => seq('\\', $.ref, optional($.cps_binding), $.expr, ','),
|
|
|
- cps_binding: $ => seq($.pattern, ':='),
|
|
|
+ binding_plain: $ => seq('let', $.pattern, '=', $.expr, ','),
|
|
|
+ binding_cps: $ => seq('@', $.ref, optional($.cps_pattern), $.expr, ','),
|
|
|
+ cps_pattern: $ => seq($.pattern, '='),
|
|
|
ref_term: $ => seq(optional('new'), $.ref),
|
|
|
- char: $ => Char,
|
|
|
int: $ => Int,
|
|
|
float: $ => Float,
|
|
|
+ char: $ => Char,
|
|
|
+ bytes: $ => repeat1($.byte),
|
|
|
+ byte: $ => Byte,
|
|
|
string: $ => seq($.text, repeat($.string_part)),
|
|
|
text: $ => Text,
|
|
|
string_part: $ => seq('..', $.string_part_content),
|
|
|
- string_part_content: $ => choice($.text, $.char, $.block),
|
|
|
+ string_part_content: $ => choice($.text, $.char),
|
|
|
})
|
|
|
});
|
|
|
|