[LIGO-25] Add grammar for ReasonLIGO and move it to squirrel
Problem: Before making parser for ReasonLIGO we need to construct its grammar so that we can collect *all* errors and simplify our further work with AST. Also since we use those grammars in squirrel it would be conscise to use them from the project directory directly. Solution: Add grammar for ReasonLIGO and move grammar to squirrel.
This commit is contained in:
parent
0fbfd134ec
commit
99321a59bb
@ -7,7 +7,7 @@ let sepBy1 = (sep, rule) =>
|
||||
|
||||
let sepBy = (sep, rule) => optional(sepBy1(sep, rule))
|
||||
|
||||
let par = x => seq('(', x, ')')
|
||||
let par = x => seq('(', x, ')')
|
||||
let brackets = x => seq('[', x, ']')
|
||||
|
||||
let ne_injection = (Kind, element) =>
|
||||
@ -40,7 +40,7 @@ let injection = (Kind, element) =>
|
||||
),
|
||||
)
|
||||
|
||||
let tuple = x => seq(x, ',', x, repeat(seq(',', x)))
|
||||
let tuple = x => seq(x, ',', x, repeat(seq(',', x)))
|
||||
let list__ = x => brackets(sepBy(';', x))
|
||||
|
||||
let nseq = x => seq(x, repeat(x))
|
||||
@ -57,7 +57,7 @@ let lop = (l, x, r) => op(l, x, r, l)
|
||||
module.exports = grammar({
|
||||
name: 'CAMLigo',
|
||||
|
||||
word: $ => $.Keyword,
|
||||
word: $ => $.Keyword,
|
||||
extras: $ => [$.ocaml_comment, $.comment, /\s/],
|
||||
|
||||
conflicts: $ => [[$.call, $.if_then_else]],
|
||||
@ -65,7 +65,8 @@ module.exports = grammar({
|
||||
rules: {
|
||||
// debug: $ => $.expr,
|
||||
|
||||
contract: $ => repeat($.declaration),
|
||||
// contract: $ => repeat($.declaration),
|
||||
contract: $ => $.expr,
|
||||
|
||||
expr: $ =>
|
||||
choice(
|
||||
@ -91,9 +92,9 @@ module.exports = grammar({
|
||||
disj: $ => prec.left(3, rop($.disj, $.or, $.conj)),
|
||||
conj: $ => prec.left(4, rop($.conj, $.and, $.comp)),
|
||||
comp: $ => prec.left(5, rop($.comp, $.compare, $.cat)),
|
||||
cat: $ => prec.left(6, lop($.cons, $.catenate, $.cat)),
|
||||
cat: $ => prec.left(6, lop($.cons, $.catenate, $.cat)),
|
||||
cons: $ => prec.right(7, lop($.add, $.consolidate, $.cons)),
|
||||
add: $ => prec.left(8, rop($.add, $.plus, $.mult)),
|
||||
add: $ => prec.left(8, rop($.add, $.plus, $.mult)),
|
||||
mult: $ => prec.left(9, rop($.mult, $.times, $.unary)),
|
||||
|
||||
unary: $ =>
|
||||
@ -341,9 +342,9 @@ module.exports = grammar({
|
||||
|
||||
field_decl: $ =>
|
||||
seq(
|
||||
$.field_name,
|
||||
':',
|
||||
$.type_expr,
|
||||
$.field_name,
|
||||
':',
|
||||
$.type_expr,
|
||||
),
|
||||
|
||||
let_declaration: $ =>
|
||||
@ -414,7 +415,7 @@ module.exports = grammar({
|
||||
$.pattern,
|
||||
),
|
||||
|
||||
pattern: $ => sepBy1('::', $.pattern_tuple),
|
||||
pattern: $ => sepBy1('::', $.pattern_tuple),
|
||||
pattern_tuple: $ => sepBy1(',', $.construct),
|
||||
|
||||
construct: $ =>
|
||||
@ -423,7 +424,7 @@ module.exports = grammar({
|
||||
$.pattern_term,
|
||||
),
|
||||
|
||||
///////////////////////////////////////////
|
||||
///////////////////////////////////////////
|
||||
|
||||
type_name: $ => $.ident,
|
||||
field_name: $ => $.ident,
|
||||
@ -448,23 +449,23 @@ module.exports = grammar({
|
||||
|
||||
include: $ => seq('#include', $.String),
|
||||
|
||||
String: $ => /\"(\\.|[^"])*\"/,
|
||||
Int: $ => /-?([1-9][0-9_]*|0)/,
|
||||
Nat: $ => /([1-9][0-9_]*|0)n/,
|
||||
Tez: $ => /([1-9][0-9_]*|0)(\.[0-9_]+)?(tz|tez|mutez)/,
|
||||
Bytes: $ => /0x[0-9a-fA-F]+/,
|
||||
Name: $ => /[a-z][a-zA-Z0-9_]*/,
|
||||
String: $ => /\"(\\.|[^"])*\"/,
|
||||
Int: $ => /-?([1-9][0-9_]*|0)/,
|
||||
Nat: $ => /([1-9][0-9_]*|0)n/,
|
||||
Tez: $ => /([1-9][0-9_]*|0)(\.[0-9_]+)?(tz|tez|mutez)/,
|
||||
Bytes: $ => /0x[0-9a-fA-F]+/,
|
||||
Name: $ => /[a-z][a-zA-Z0-9_]*/,
|
||||
Name_Capital: $ => /[A-Z][a-zA-Z0-9_]*/,
|
||||
Keyword: $ => /[A-Za-z][a-z]*/,
|
||||
Keyword: $ => /[A-Za-z][a-z]*/,
|
||||
|
||||
False: $ => 'False',
|
||||
True: $ => 'True',
|
||||
Unit: $ => 'Unit',
|
||||
None: $ => 'None',
|
||||
Some: $ => 'Some',
|
||||
skip: $ => 'skip',
|
||||
rec: $ => 'rec',
|
||||
False: $ => 'False',
|
||||
True: $ => 'True',
|
||||
Unit: $ => 'Unit',
|
||||
None: $ => 'None',
|
||||
Some: $ => 'Some',
|
||||
skip: $ => 'skip',
|
||||
rec: $ => 'rec',
|
||||
|
||||
attr: $ => seq('[@@', $.name, ']'),
|
||||
attr: $ => seq('[@@', $.name, ']'),
|
||||
}
|
||||
});
|
13
tools/lsp/squirrel/grammar/camligo/index.js
Normal file
13
tools/lsp/squirrel/grammar/camligo/index.js
Normal file
@ -0,0 +1,13 @@
|
||||
try {
|
||||
module.exports = require("./build/Release/tree_sitter_CAMLigo_binding");
|
||||
} catch (error) {
|
||||
try {
|
||||
module.exports = require("./build/Debug/tree_sitter_CAMLigo_binding");
|
||||
} catch (_) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
module.exports.nodeTypeInfo = require("./src/node-types.json");
|
||||
} catch (_) {}
|
@ -14,7 +14,7 @@ let op = (name, left, right, term) =>
|
||||
)
|
||||
|
||||
let right_op = (name, left, right) => op(name, left, right, right)
|
||||
let left_op = (name, left, right) => op(name, left, right, left)
|
||||
let left_op = (name, left, right) => op(name, left, right, left)
|
||||
|
||||
let par = x => seq('(', x, ')')
|
||||
let brackets = x => seq('[', x, ']')
|
||||
@ -52,7 +52,7 @@ let injection = (Kind, element) =>
|
||||
module.exports = grammar({
|
||||
name: 'PascaLigo',
|
||||
|
||||
word: $ => $.Keyword,
|
||||
word: $ => $.Keyword,
|
||||
extras: $ => [$.ocaml_comment, $.comment, /\s/],
|
||||
|
||||
rules: {
|
||||
@ -119,30 +119,30 @@ module.exports = grammar({
|
||||
|
||||
michelsonTypeOr: $ =>
|
||||
seq(
|
||||
"michelson_or",
|
||||
"(",
|
||||
field("left_type", $._type_expr),
|
||||
",",
|
||||
field("left_type_name", $.String),
|
||||
",",
|
||||
field("right_type", $._type_expr),
|
||||
",",
|
||||
field("right_type_name", $.String),
|
||||
")",
|
||||
"michelson_or",
|
||||
"(",
|
||||
field("left_type", $._type_expr),
|
||||
",",
|
||||
field("left_type_name", $.String),
|
||||
",",
|
||||
field("right_type", $._type_expr),
|
||||
",",
|
||||
field("right_type_name", $.String),
|
||||
")",
|
||||
),
|
||||
|
||||
michelsonTypeAnd: $ =>
|
||||
seq(
|
||||
"michelson_pair",
|
||||
"(",
|
||||
field("left_type", $._type_expr),
|
||||
",",
|
||||
field("left_type_name", $.String),
|
||||
",",
|
||||
field("right_type", $._type_expr),
|
||||
",",
|
||||
field("right_type_name", $.String),
|
||||
")",
|
||||
"michelson_pair",
|
||||
"(",
|
||||
field("left_type", $._type_expr),
|
||||
",",
|
||||
field("left_type_name", $.String),
|
||||
",",
|
||||
field("right_type", $._type_expr),
|
||||
",",
|
||||
field("right_type_name", $.String),
|
||||
")",
|
||||
),
|
||||
|
||||
invokeBinary: $ =>
|
||||
@ -157,10 +157,10 @@ module.exports = grammar({
|
||||
par(field("arguments", $._type_expr)),
|
||||
),
|
||||
|
||||
map: $ => 'map',
|
||||
map: $ => 'map',
|
||||
big_map: $ => 'big_map',
|
||||
list: $ => 'list',
|
||||
set: $ => 'set',
|
||||
list: $ => 'list',
|
||||
set: $ => 'set',
|
||||
|
||||
type_tuple: $ => par(sepBy1(',', field("element", $._type_expr))),
|
||||
|
||||
@ -184,7 +184,7 @@ module.exports = grammar({
|
||||
|
||||
record_type: $ =>
|
||||
choice(
|
||||
seq('record', sepBy(';', field("field", $.field_decl)), 'end'),
|
||||
seq('record', sepBy(';', field("field", $.field_decl)), 'end'),
|
||||
seq('record', '[', sepBy(';', field("field", $.field_decl)), ']'),
|
||||
),
|
||||
|
||||
@ -525,22 +525,22 @@ module.exports = grammar({
|
||||
|
||||
binop: $ =>
|
||||
choice(
|
||||
prec.left (0, seq(field("arg1", $._op_expr), field("op", 'or'), field("arg2", $._op_expr))),
|
||||
prec.left (1, seq(field("arg1", $._op_expr), field("op", 'and'), field("arg2", $._op_expr))),
|
||||
prec.right(2, seq(field("arg1", $._core_expr), field("op", 'contains'), field("arg2", $._op_expr))),
|
||||
prec.left (3, seq(field("arg1", $._op_expr), field("op", $.comparison), field("arg2", $._op_expr))),
|
||||
prec.right(4, seq(field("arg1", $._op_expr), field("op", '^'), field("arg2", $._op_expr))),
|
||||
prec.right(5, seq(field("arg1", $._op_expr), field("op", '#'), field("arg2", $._op_expr))),
|
||||
prec.left (6, seq(field("arg1", $._op_expr), field("op", $.adder), field("arg2", $._op_expr))),
|
||||
prec.left (7, seq(field("arg1", $._op_expr), field("op", $.multiplier), field("arg2", $._op_expr))),
|
||||
prec.left(0, seq(field("arg1", $._op_expr), field("op", 'or'), field("arg2", $._op_expr))),
|
||||
prec.left(1, seq(field("arg1", $._op_expr), field("op", 'and'), field("arg2", $._op_expr))),
|
||||
prec.right(2, seq(field("arg1", $._core_expr), field("op", 'contains'), field("arg2", $._op_expr))),
|
||||
prec.left(3, seq(field("arg1", $._op_expr), field("op", $.comparison), field("arg2", $._op_expr))),
|
||||
prec.right(4, seq(field("arg1", $._op_expr), field("op", '^'), field("arg2", $._op_expr))),
|
||||
prec.right(5, seq(field("arg1", $._op_expr), field("op", '#'), field("arg2", $._op_expr))),
|
||||
prec.left(6, seq(field("arg1", $._op_expr), field("op", $.adder), field("arg2", $._op_expr))),
|
||||
prec.left(7, seq(field("arg1", $._op_expr), field("op", $.multiplier), field("arg2", $._op_expr))),
|
||||
),
|
||||
|
||||
unop: $ => prec.right(8, seq(field("negate", $.negate), field("arg", $._core_expr))),
|
||||
|
||||
comparison: $ => choice('<', '<=', '>', '>=', '=', '=/='),
|
||||
adder: $ => choice('-', '+'),
|
||||
adder: $ => choice('-', '+'),
|
||||
multiplier: $ => choice('/', '*', 'mod'),
|
||||
negate: $ => choice('-', 'not'),
|
||||
negate: $ => choice('-', 'not'),
|
||||
|
||||
_core_expr: $ =>
|
||||
choice(
|
||||
@ -718,8 +718,8 @@ module.exports = grammar({
|
||||
field("arguments", $.arguments),
|
||||
),
|
||||
|
||||
tuple_expr: $ => par(sepBy1(',', field("element", $._expr))),
|
||||
arguments: $ => par(sepBy(',', field("argument", $._expr))),
|
||||
tuple_expr: $ => par(sepBy1(',', field("element", $._expr))),
|
||||
arguments: $ => par(sepBy(',', field("argument", $._expr))),
|
||||
|
||||
_list_expr: $ => choice($.list_injection, 'nil'),
|
||||
|
||||
@ -802,22 +802,22 @@ module.exports = grammar({
|
||||
|
||||
include: $ => seq('#include', field("filename", $.String)),
|
||||
|
||||
String: $ => choice(/\"(\\.|[^"])*\"/, /{\|(\\.|[^\|])*\|}/),
|
||||
Int: $ => /-?([1-9][0-9_]*|0)/,
|
||||
Nat: $ => /([1-9][0-9_]*|0)n/,
|
||||
Tez: $ => /([1-9][0-9_]*|0)(\.[0-9_]+)?(tz|tez|mutez)/,
|
||||
Bytes: $ => /0x[0-9a-fA-F]+/,
|
||||
FieldName: $ => /[a-z][a-zA-Z0-9_]*/,
|
||||
TypeName: $ => /[a-z][a-zA-Z0-9_]*/,
|
||||
Name: $ => /[a-z][a-zA-Z0-9_]*/,
|
||||
String: $ => choice(/\"(\\.|[^"])*\"/, /{\|(\\.|[^\|])*\|}/),
|
||||
Int: $ => /-?([1-9][0-9_]*|0)/,
|
||||
Nat: $ => /([1-9][0-9_]*|0)n/,
|
||||
Tez: $ => /([1-9][0-9_]*|0)(\.[0-9_]+)?(tz|tez|mutez)/,
|
||||
Bytes: $ => /0x[0-9a-fA-F]+/,
|
||||
FieldName: $ => /[a-z][a-zA-Z0-9_]*/,
|
||||
TypeName: $ => /[a-z][a-zA-Z0-9_]*/,
|
||||
Name: $ => /[a-z][a-zA-Z0-9_]*/,
|
||||
Name_Capital: $ => /[A-Z][a-zA-Z0-9_]*/,
|
||||
Keyword: $ => /[A-Za-z][a-z]*/,
|
||||
Keyword: $ => /[A-Za-z][a-z]*/,
|
||||
|
||||
False: $ => 'False',
|
||||
True: $ => 'True',
|
||||
Unit: $ => 'Unit',
|
||||
None: $ => 'None',
|
||||
skip: $ => 'skip',
|
||||
recursive: $ => 'recursive',
|
||||
False: $ => 'False',
|
||||
True: $ => 'True',
|
||||
Unit: $ => 'Unit',
|
||||
None: $ => 'None',
|
||||
skip: $ => 'skip',
|
||||
recursive: $ => 'recursive',
|
||||
}
|
||||
});
|
13
tools/lsp/squirrel/grammar/pascaligo/index.js
Normal file
13
tools/lsp/squirrel/grammar/pascaligo/index.js
Normal file
@ -0,0 +1,13 @@
|
||||
try {
|
||||
module.exports = require("./build/Release/tree_sitter_PascaLigo_binding");
|
||||
} catch (error) {
|
||||
try {
|
||||
module.exports = require("./build/Debug/tree_sitter_PascaLigo_binding");
|
||||
} catch (_) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
module.exports.nodeTypeInfo = require("./src/node-types.json");
|
||||
} catch (_) {}
|
682
tools/lsp/squirrel/grammar/reasonligo/grammar.js
Normal file
682
tools/lsp/squirrel/grammar/reasonligo/grammar.js
Normal file
@ -0,0 +1,682 @@
|
||||
const PREC = {
|
||||
|
||||
CALL: 300000000,
|
||||
OR: 0,
|
||||
AND: 1,
|
||||
COMPARE: 3,
|
||||
CONCAT: 5,
|
||||
PLUS: 6,
|
||||
MINUS: 6,
|
||||
MUL: 7,
|
||||
DIV: 7,
|
||||
|
||||
ATTR: 1,
|
||||
TYPE: 101,
|
||||
LET: 100,
|
||||
EXPR: 100000000,
|
||||
CONSTR: 100000,
|
||||
LAM: 1000,
|
||||
};
|
||||
|
||||
const OPS = [
|
||||
['+', PREC.PLUS],
|
||||
['-', PREC.MINUS],
|
||||
['mod', PREC.DIV],
|
||||
['/', PREC.DIV],
|
||||
['*', PREC.MUL],
|
||||
['++', PREC.CONCAT],
|
||||
['<', PREC.COMPARE],
|
||||
['>', PREC.COMPARE],
|
||||
['<=', PREC.COMPARE],
|
||||
['>=', PREC.COMPARE],
|
||||
['==', PREC.COMPARE],
|
||||
['!=', PREC.COMPARE],
|
||||
['&&', PREC.COMPARE],
|
||||
['||', PREC.OR],
|
||||
]
|
||||
|
||||
let sepBy1 = (sep, rule) =>
|
||||
seq(
|
||||
rule,
|
||||
repeat(seq(sep, rule)),
|
||||
optional(sep)
|
||||
)
|
||||
|
||||
let sepBy = (sep, rule) => optional(sepBy1(sep, rule))
|
||||
|
||||
let par = x => seq('(', x, ')')
|
||||
let opar = x => seq(optional('('), x, optional(')'))
|
||||
let brackets = x => seq('[', x, ']')
|
||||
let block = x => seq('{', x, '}')
|
||||
|
||||
let tuple = x => seq(x, ',', x, repeat(seq(',', x)))
|
||||
let list__ = x => brackets(sepBy(';', x))
|
||||
|
||||
let nseq = x => seq(x, repeat(x))
|
||||
|
||||
module.exports = grammar({
|
||||
name: 'ReasonLigo',
|
||||
|
||||
word: $ => $.Keyword,
|
||||
extras: $ => [$.oneline_comment, $.block_comment, /\s/],
|
||||
|
||||
conflicts: $ => [
|
||||
[$._fun_type, $.type_application],
|
||||
[$._pattern, $.tuple_pattern],
|
||||
[$._expr], // TODO: left-precendence is used for tuple_expr, right for nested `let`s
|
||||
[$._exprf],
|
||||
|
||||
[$.tuple_expr, $.parameters],
|
||||
[$.record_field, $._accessor], // TODO
|
||||
[$.variant], // TODO: some alien stuff
|
||||
[$.sum_type], // TODO: fix in `let_declaration`.
|
||||
[$.bracket_block], // TODO: same as $.lambda_body
|
||||
[$.type_decl],
|
||||
[$.lambda],
|
||||
[$._instruction, $._expr], // switch_instr
|
||||
[$._functional_block, $.bracket_block], // TODO: remove
|
||||
[$.list_access], // TODO: remove
|
||||
[$.list_access, $._ident], // TODO
|
||||
[$.record_field, $._ident], // TODO
|
||||
[$._core_pattern, $._expr], //TODO: remove as soon as possible
|
||||
[$.lambda_call], // TODO: remove
|
||||
[$.lambda_call, $.binary_call],
|
||||
[$._expr, $.bracket_block], // TODO
|
||||
[$.lambda_call, $.parameters], // TODO
|
||||
[$["-"], $.negate], // unary vs binary calls
|
||||
|
||||
[$.parameters, $.annot_expr], // TODO
|
||||
[$.type_tuple, $._core_type],
|
||||
|
||||
[$._pattern, $.annot_pattern], // TODO: constr (pat) case
|
||||
[$.annot_expr, $._type_annotation],
|
||||
[$.annot_expr, $.lambda_call],
|
||||
[$.annot_expr, $._functional_block],
|
||||
|
||||
// TODO: those are produced in conflicts of `fun_call` and `expr` in bracket blocks
|
||||
[$.annot_expr, $._exprf],
|
||||
[$.lambda_call, $._exprf],
|
||||
[$.bracket_block, $._exprf],
|
||||
[$._functional_block, $._exprf],
|
||||
[$.tuple_expr, $._exprf],
|
||||
[$._annot_fun_call, $._exprf],
|
||||
],
|
||||
|
||||
rules: {
|
||||
contract: $ => sepBy(optional(';'), field("declaration", $._declaration)),
|
||||
|
||||
_expr: $ =>
|
||||
prec(PREC.EXPR,
|
||||
seq(
|
||||
choice(
|
||||
$.lambda_call,
|
||||
$.tuple_expr,
|
||||
$._literal,
|
||||
// $.fun_call,
|
||||
$.constructor_call,
|
||||
$.unary_call,
|
||||
$.binary_call,
|
||||
$.annot_expr,
|
||||
$.list_expr,
|
||||
$.record_expr,
|
||||
$._ref,
|
||||
$._ident,
|
||||
$.switch_instr,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// TODO: workaround to move `fun_call` out of `expr` needed in bracket blocks
|
||||
_exprf: $ => choice($.fun_call, $._expr),
|
||||
|
||||
_annot_expr: $ =>
|
||||
par($.annot_expr),
|
||||
|
||||
annot_expr: $ =>
|
||||
seq(
|
||||
field("subject", $._expr),
|
||||
':',
|
||||
field("type", $._type_expr),
|
||||
),
|
||||
|
||||
// TODO: same as tuple_pattern
|
||||
// TODO: to annotate expression we do not need to enclose it in brackets
|
||||
// TODO: possible ((a : p) : q, b)
|
||||
tuple_expr: $ =>
|
||||
par(sepBy1(',',
|
||||
seq(
|
||||
field("element", choice(
|
||||
$.annot_expr,
|
||||
$.fun_call,
|
||||
$._expr,
|
||||
)),
|
||||
)
|
||||
)),
|
||||
|
||||
constructor_call: $ =>
|
||||
prec(PREC.CONSTR,
|
||||
seq(
|
||||
field("constructor",
|
||||
choice(
|
||||
$._constr,
|
||||
$.module_qualified,
|
||||
),
|
||||
),
|
||||
field("parameters", $.parameters),
|
||||
),
|
||||
),
|
||||
|
||||
lambda_call: $ =>
|
||||
seq(
|
||||
par(field("lambda", $.lambda)),
|
||||
repeat1(
|
||||
choice(
|
||||
field("arguments", $._expr),
|
||||
par(field("arguments", $.lambda))
|
||||
)
|
||||
), // TODO: workaround to move lambda out of expr
|
||||
),
|
||||
|
||||
fun_call: $ =>
|
||||
prec.right(PREC.CALL,
|
||||
seq(
|
||||
field("f", $.Name), // TODO: may be qualified
|
||||
field("arguments", $.parameters),
|
||||
)
|
||||
),
|
||||
|
||||
binary_call: $ => choice(
|
||||
...OPS
|
||||
.map(([op, precendence]) =>
|
||||
prec.left(precendence, seq(
|
||||
field("left", $._exprf),
|
||||
field("op", $[op]),
|
||||
field("right", $._exprf),
|
||||
))
|
||||
)
|
||||
),
|
||||
|
||||
// Workaround to make operators to be instructions as well
|
||||
// so that they won't be stripped when naming them as fields
|
||||
...OPS.reduce(
|
||||
(acc, [e, _]) => ({ ...acc, [e]: $ => seq(e) }), {}
|
||||
),
|
||||
|
||||
unary_call: $ => prec.right(8,
|
||||
seq(
|
||||
field("negate", $.negate),
|
||||
field("arg", $._exprf)
|
||||
)
|
||||
),
|
||||
|
||||
negate: $ => choice('-', '!'),
|
||||
|
||||
// TODO: refactor
|
||||
call: $ =>
|
||||
prec.left(1,
|
||||
choice(
|
||||
seq($.call, par($._expr)),
|
||||
par($._expr),
|
||||
),
|
||||
),
|
||||
|
||||
switch_instr: $ =>
|
||||
prec.left(0, // TODO
|
||||
seq(
|
||||
'switch',
|
||||
choice(
|
||||
field('subject', $.Name),
|
||||
par(field('subject', $._exprf)),
|
||||
),
|
||||
block(seq(
|
||||
optional('|'),
|
||||
sepBy1('|', field('case', $.alt)),
|
||||
)),
|
||||
),
|
||||
),
|
||||
|
||||
// TODO: it may parse expr with ';' attached to the end
|
||||
alt: $ =>
|
||||
seq(
|
||||
field("pattern", $._pattern),
|
||||
'=>',
|
||||
field("body", $._functional_block),
|
||||
optional(';'),
|
||||
),
|
||||
|
||||
|
||||
_literal: $ =>
|
||||
choice(
|
||||
$.Nat,
|
||||
$.Int,
|
||||
$.Bool,
|
||||
$.Tez,
|
||||
$.String,
|
||||
$.Bytes,
|
||||
$.Unit,
|
||||
$.Nil,
|
||||
$.wildcard,
|
||||
),
|
||||
|
||||
record_expr: $ =>
|
||||
seq(
|
||||
block(seq(
|
||||
sepBy1(',', field("assignment", choice(
|
||||
$.spread,
|
||||
$.record_field,
|
||||
))),
|
||||
optional($._ident), // TODO: not need to be here
|
||||
))
|
||||
),
|
||||
|
||||
spread: $ => seq(
|
||||
'...',
|
||||
field("name", $._ident), // TODO: may be possible expression
|
||||
),
|
||||
|
||||
record_field: $ =>
|
||||
seq(
|
||||
field("name", sepBy1('.', $.Name)),
|
||||
':',
|
||||
field("value", $._expr),
|
||||
),
|
||||
|
||||
_statement: $ => choice(
|
||||
$._instruction,
|
||||
),
|
||||
|
||||
_instruction: $ =>
|
||||
prec(PREC.EXPR, choice(
|
||||
$.conditional,
|
||||
$.switch_instr,
|
||||
$.let_declaration,
|
||||
)),
|
||||
|
||||
lambda: $ =>
|
||||
seq(
|
||||
field("lambda_head", seq(
|
||||
field("arguments", $.parameters),
|
||||
optional(seq(":",
|
||||
field("lambda_type",
|
||||
choice($._core_type, $.type_tuple),
|
||||
),
|
||||
))
|
||||
)),
|
||||
'=>',
|
||||
field("lambda_body", $._functional_block)
|
||||
),
|
||||
|
||||
parameters: $ =>
|
||||
par(
|
||||
sepBy(',', field("parameter", seq(
|
||||
choice($._exprf, $.lambda), // TODO: workaround to move lambda our of expr
|
||||
optional($._type_annotation), // TODO: move it somewhere
|
||||
)))
|
||||
),
|
||||
|
||||
_pattern: $ =>
|
||||
choice(
|
||||
$.cons_pattern,
|
||||
$.annot_pattern,
|
||||
$._core_pattern,
|
||||
),
|
||||
|
||||
cons_pattern: $ =>
|
||||
brackets(
|
||||
seq(
|
||||
field("head", $._core_pattern),
|
||||
',',
|
||||
field("tail", choice(
|
||||
$.spread,
|
||||
$._pattern,
|
||||
)),
|
||||
)
|
||||
),
|
||||
|
||||
annot_pattern: $ =>
|
||||
par(
|
||||
seq(
|
||||
field("subject", $._core_pattern),
|
||||
':',
|
||||
field("type", $._type_expr),
|
||||
)
|
||||
),
|
||||
|
||||
_core_pattern: $ =>
|
||||
prec.right(PREC.CONSTR,
|
||||
seq(
|
||||
choice(
|
||||
$.constr_pattern,
|
||||
$.tuple_pattern,
|
||||
$._literal,
|
||||
$.Name,
|
||||
),
|
||||
)
|
||||
),
|
||||
|
||||
tuple_pattern: $ =>
|
||||
par(tuple(field("element", $._pattern))),
|
||||
|
||||
constr_pattern: $ =>
|
||||
prec.right(PREC.CONSTR, // TODO: left precendence fails
|
||||
seq(
|
||||
field("constr", $._constr),
|
||||
optional(
|
||||
opar(
|
||||
field("arguments", $._pattern)
|
||||
),
|
||||
)),
|
||||
),
|
||||
|
||||
list_expr: $ => brackets(
|
||||
sepBy(',', field("element", choice(
|
||||
$.spread,
|
||||
$._expr,
|
||||
)))
|
||||
),
|
||||
|
||||
|
||||
conditional: $ =>
|
||||
prec.left(PREC.LET,
|
||||
seq(
|
||||
'if',
|
||||
par(field("selector", $._expr)),
|
||||
field("then", $.bracket_block),
|
||||
optional(seq(
|
||||
'else',
|
||||
field("else", $.bracket_block),
|
||||
)),
|
||||
),
|
||||
),
|
||||
|
||||
_ref: $ =>
|
||||
choice(
|
||||
$.module_qualified,
|
||||
$.struct_qualified,
|
||||
$._constr,
|
||||
$.list_access,
|
||||
),
|
||||
|
||||
module_qualified: $ =>
|
||||
seq(
|
||||
field("module", $._constr),
|
||||
nseq(seq('.', field("method", $.Name))), // TODO: capital letters
|
||||
),
|
||||
|
||||
// TODO: may be the same as `list_access`
|
||||
struct_qualified: $ =>
|
||||
seq(
|
||||
field("struct", $.Name),
|
||||
nseq(seq('.', field("method", $._accessor))),
|
||||
),
|
||||
|
||||
_accessor: $ => choice($.Name, $.Int),
|
||||
|
||||
list_access: $ =>
|
||||
// prec.left(8,
|
||||
seq(
|
||||
field("name", $.Name),
|
||||
repeat1(brackets(field("indexes", $.Int))),
|
||||
// ),
|
||||
),
|
||||
|
||||
_declaration: $ =>
|
||||
field("declaration",
|
||||
choice(
|
||||
$.type_decl,
|
||||
$.let_declaration,
|
||||
$.include,
|
||||
$.attr_decl,
|
||||
)
|
||||
),
|
||||
|
||||
attr_decl: $ =>
|
||||
prec.left(PREC.ATTR,
|
||||
nseq(brackets(
|
||||
seq('@', field("name", $.Name))
|
||||
))
|
||||
),
|
||||
|
||||
type_decl: $ =>
|
||||
seq(
|
||||
'type',
|
||||
field("type_name", $.TypeName),
|
||||
'=',
|
||||
field("type_value", $._type_expr),
|
||||
),
|
||||
|
||||
_type_expr: $ =>
|
||||
choice(
|
||||
$._fun_type,
|
||||
$.sum_type,
|
||||
$.record_type,
|
||||
),
|
||||
|
||||
_fun_type: $ =>
|
||||
choice(
|
||||
$.fun_type,
|
||||
$._core_type,
|
||||
$.type_tuple,
|
||||
),
|
||||
|
||||
fun_type: $ =>
|
||||
seq(
|
||||
field("domain", choice($._core_type, $.type_tuple)),
|
||||
'=>',
|
||||
field("codomain", $._fun_type),
|
||||
),
|
||||
|
||||
_core_type: $ =>
|
||||
choice(
|
||||
$.type_application,
|
||||
$.TypeName,
|
||||
$.type_string,
|
||||
$.module_TypeName,
|
||||
),
|
||||
|
||||
module_TypeName: $ =>
|
||||
seq(
|
||||
$.module_name,
|
||||
'.',
|
||||
$.TypeName,
|
||||
),
|
||||
|
||||
type_application: $ =>
|
||||
seq(
|
||||
field("functor", $._core_type),
|
||||
par(sepBy(',', field("parameter", $._type_expr))),
|
||||
),
|
||||
|
||||
type_string: $ => $.String,
|
||||
|
||||
type_tuple: $ =>
|
||||
par(sepBy1(',', field("element", $._type_expr))),
|
||||
|
||||
sum_type: $ =>
|
||||
seq(
|
||||
optional('|'),
|
||||
sepBy1('|', field("variant", $.variant)),
|
||||
),
|
||||
|
||||
variant: $ =>
|
||||
seq(
|
||||
field("constructor", $._constr),
|
||||
optional(par(field("arguments", $._fun_type))),
|
||||
),
|
||||
|
||||
record_type: $ =>
|
||||
seq(
|
||||
'{',
|
||||
sepBy(',', field("field", $.field_decl)),
|
||||
'}',
|
||||
),
|
||||
|
||||
field_decl: $ =>
|
||||
seq(
|
||||
field("field_name", $._field_name),
|
||||
':',
|
||||
field("field_type", $._type_expr),
|
||||
),
|
||||
|
||||
te: $ => choice(
|
||||
$.lambda,
|
||||
$._expr,
|
||||
),
|
||||
|
||||
_functional_block: $ =>
|
||||
choice(
|
||||
$._statement,
|
||||
$._expr,
|
||||
$.fun_call,
|
||||
$.bracket_block,
|
||||
),
|
||||
|
||||
_annot_fun_call: $ => // Workaround used only in bracket blocks
|
||||
par(seq(
|
||||
$.fun_call,
|
||||
':',
|
||||
$._type_expr,
|
||||
)),
|
||||
|
||||
bracket_block: $ =>
|
||||
prec.right(1000000, // TODO: precendence
|
||||
block(
|
||||
choice(
|
||||
seq(
|
||||
sepBy(';', field("statement", choice(
|
||||
$.constructor_call,
|
||||
seq(
|
||||
optional($.attr_decl),
|
||||
$._statement,
|
||||
),
|
||||
$.fun_call,
|
||||
// $._expr, // TODO: use only `fun_call` from there, somewhat fails if called directly
|
||||
))),
|
||||
optional(seq(
|
||||
opar(
|
||||
field("return",
|
||||
choice(
|
||||
$._expr,
|
||||
seq( // TODO: maybe not all returned function calls need to be annotated
|
||||
$.fun_call,
|
||||
':',
|
||||
$._type_expr, // TODO: maybe we'll need to annotate fields here, but so far we just return multiple 'return's
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
optional(';'),
|
||||
))),
|
||||
$.bracket_block,
|
||||
), // TODO conflict: _group bracket_block
|
||||
)
|
||||
),
|
||||
|
||||
let_declaration: $ =>
|
||||
prec.left(PREC.LET,
|
||||
seq(
|
||||
'let',
|
||||
optional($.rec),
|
||||
field("binding", choice(
|
||||
sepBy1(',', $._core_pattern),
|
||||
)),
|
||||
optional(seq(':', field("type", $._type_expr))),
|
||||
'=',
|
||||
field("let_value",
|
||||
choice(
|
||||
$.lambda,
|
||||
$._functional_block,
|
||||
),
|
||||
),
|
||||
)
|
||||
),
|
||||
|
||||
_type_annotation: $ =>
|
||||
seq(
|
||||
':',
|
||||
field("type", $._type_expr)
|
||||
),
|
||||
|
||||
pattern_term: $ =>
|
||||
choice(
|
||||
$.Name,
|
||||
$.pattern_grouped,
|
||||
),
|
||||
|
||||
pattern_grouped: $ =>
|
||||
seq(
|
||||
'(',
|
||||
$._core_pattern,
|
||||
optional($._type_annotation),
|
||||
')',
|
||||
),
|
||||
|
||||
pattern_list: $ => list__($._pattern),
|
||||
pattern_constant: $ =>
|
||||
choice(
|
||||
$.Nat,
|
||||
$.String,
|
||||
$.Bytes,
|
||||
$.Int,
|
||||
),
|
||||
|
||||
pattern_tuple: $ => sepBy1(',', $._construct),
|
||||
|
||||
_construct: $ =>
|
||||
choice(
|
||||
seq($._constr, nseq($.pattern_term)),
|
||||
par($.pattern_term),
|
||||
),
|
||||
|
||||
///////////////////////////////////////////
|
||||
|
||||
_field_name: $ => $.Name,
|
||||
fun_name: $ => $.Name,
|
||||
struct_name: $ => $.Name,
|
||||
var: $ => $.Name,
|
||||
module_name: $ => $.Name_Capital,
|
||||
_constr: $ => $.Name_Capital,
|
||||
// TODO: remove
|
||||
_ident: $ => $.Name,
|
||||
|
||||
comment: $ => choice(
|
||||
$.oneline_comment,
|
||||
$.block_comment
|
||||
),
|
||||
|
||||
oneline_comment: $ => token(seq('//', /.*/)),
|
||||
|
||||
block_comment: $ => seq(
|
||||
'/*',
|
||||
repeat(/./),
|
||||
'*/'
|
||||
),
|
||||
|
||||
include: $ => seq('#include', $.String),
|
||||
|
||||
String: $ => /\"(\\.|[^"])*\"/,
|
||||
Int: $ => /-?([1-9][0-9_]*|0)/,
|
||||
Nat: $ => /([1-9][0-9_]*|0)n/,
|
||||
Tez: $ => /([1-9][0-9_]*|0)(\.[0-9_]+)?(tz|tez|mutez)/,
|
||||
Bytes: $ => /0x[0-9a-fA-F]+/,
|
||||
Name: $ => /[a-z][a-zA-Z0-9_]*/,
|
||||
TypeName: $ => /[a-z][a-zA-Z0-9_]*/,
|
||||
Name_Capital: $ => /[A-Z][a-zA-Z0-9_]*/,
|
||||
Keyword: $ => /[A-Za-z][a-z]*/,
|
||||
Bool: $ => choice($.False, $.True),
|
||||
|
||||
include: $ => seq('#include', field("filename", $.String)),
|
||||
|
||||
False: $ => 'false',
|
||||
True: $ => 'true',
|
||||
Unit: $ => '()',
|
||||
Nil: $ => '[]',
|
||||
None: $ => 'None',
|
||||
Some: $ => 'Some',
|
||||
skip: $ => 'skip',
|
||||
rec: $ => 'rec',
|
||||
wildcard: $ => '_',
|
||||
|
||||
attr: $ => seq('[@@', $.Name, ']'),
|
||||
}
|
||||
});
|
13
tools/lsp/squirrel/grammar/reasonligo/index.js
Normal file
13
tools/lsp/squirrel/grammar/reasonligo/index.js
Normal file
@ -0,0 +1,13 @@
|
||||
try {
|
||||
module.exports = require("./build/Release/tree_sitter_CAMLigo_binding");
|
||||
} catch (error) {
|
||||
try {
|
||||
module.exports = require("./build/Debug/tree_sitter_CAMLigo_binding");
|
||||
} catch (_) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
module.exports.nodeTypeInfo = require("./src/node-types.json");
|
||||
} catch (_) {}
|
Loading…
Reference in New Issue
Block a user