Initial commit of LIGO tooling
This commit is contained in:
parent
0c0889f514
commit
510cda6613
16
.gitignore
vendored
16
.gitignore
vendored
@ -14,4 +14,18 @@ Version.ml
|
||||
/ligo.install
|
||||
*.coverage
|
||||
/_coverage/
|
||||
/_coverage_*/
|
||||
/_coverage_*/
|
||||
*.gyp
|
||||
tools/lsp/pascaligo/package.json
|
||||
tools/lsp/pascaligo/node_modules
|
||||
tools/lsp/pascaligo/log.html
|
||||
tools/lsp/pascaligo/src/
|
||||
tools/lsp/pascaligo/index.js
|
||||
tools/lsp/pascaligo/node_modules
|
||||
.stack-work
|
||||
tools/lsp/camligo/package.json
|
||||
tools/lsp/camligo/node_modules
|
||||
tools/lsp/camligo/log.html
|
||||
tools/lsp/camligo/src/
|
||||
tools/lsp/camligo/index.js
|
||||
tools/lsp/camligo/node_modules
|
||||
|
470
tools/lsp/camligo/grammar.js
Normal file
470
tools/lsp/camligo/grammar.js
Normal file
@ -0,0 +1,470 @@
|
||||
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 brackets = x => seq('[', x, ']')
|
||||
|
||||
let ne_injection = (Kind, element) =>
|
||||
choice(
|
||||
seq(
|
||||
Kind,
|
||||
sepBy1(';', element),
|
||||
'end',
|
||||
),
|
||||
seq(
|
||||
Kind,
|
||||
'[',
|
||||
sepBy1(';', element),
|
||||
']',
|
||||
),
|
||||
)
|
||||
|
||||
let injection = (Kind, element) =>
|
||||
choice(
|
||||
seq(
|
||||
Kind,
|
||||
sepBy(';', element),
|
||||
'end',
|
||||
),
|
||||
seq(
|
||||
Kind,
|
||||
'[',
|
||||
sepBy(';', element),
|
||||
']',
|
||||
),
|
||||
)
|
||||
|
||||
let tuple = x => seq(x, ',', x, repeat(seq(',', x)))
|
||||
let list__ = x => brackets(sepBy(';', x))
|
||||
|
||||
let nseq = x => seq(x, repeat(x))
|
||||
|
||||
let op = (l, x, r, def) =>
|
||||
choice(
|
||||
seq(l, x, r),
|
||||
def,
|
||||
)
|
||||
|
||||
let rop = (l, x, r) => op(l, x, r, r)
|
||||
let lop = (l, x, r) => op(l, x, r, l)
|
||||
|
||||
module.exports = grammar({
|
||||
name: 'CAMLigo',
|
||||
|
||||
word: $ => $.Keyword,
|
||||
extras: $ => [$.ocaml_comment, $.comment, /\s/],
|
||||
|
||||
conflicts: $ => [[$.call, $.if_then_else]],
|
||||
|
||||
rules: {
|
||||
// debug: $ => $.expr,
|
||||
|
||||
contract: $ => repeat($.declaration),
|
||||
|
||||
expr: $ =>
|
||||
choice(
|
||||
$.let_expr,
|
||||
$.op_call,
|
||||
),
|
||||
|
||||
let_expr: $ =>
|
||||
prec.left(0,
|
||||
seq(
|
||||
'let',
|
||||
$.let_binding,
|
||||
repeat($.attr),
|
||||
'in',
|
||||
$.expr,
|
||||
),
|
||||
),
|
||||
|
||||
op_call: $ =>
|
||||
$.tuple,
|
||||
|
||||
tuple: $ => prec.left(2, rop($.tuple, ',', $.disj)),
|
||||
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)),
|
||||
cons: $ => prec.right(7, lop($.add, $.consolidate, $.cons)),
|
||||
add: $ => prec.left(8, rop($.add, $.plus, $.mult)),
|
||||
mult: $ => prec.left(9, rop($.mult, $.times, $.unary)),
|
||||
|
||||
unary: $ =>
|
||||
seq(
|
||||
optional($.negate),
|
||||
$.call,
|
||||
),
|
||||
|
||||
or: $ => choice('||', 'or'),
|
||||
and: $ => '&&',
|
||||
compare: $ => choice('<', '<=', '>', '>=', '=', '<>'),
|
||||
catenate: $ => '^',
|
||||
consolidate: $ => '::',
|
||||
plus: $ => choice('+', '-'),
|
||||
times: $ => choice('*', '/', 'mod'),
|
||||
negate: $ => choice('-', 'not'),
|
||||
|
||||
call: $ =>
|
||||
prec.left(1,
|
||||
choice(
|
||||
seq($.call, $.term),
|
||||
$.term,
|
||||
),
|
||||
),
|
||||
|
||||
term: $ =>
|
||||
choice(
|
||||
$.ref,
|
||||
$.if_then_else,
|
||||
$.literal,
|
||||
$.match,
|
||||
),
|
||||
|
||||
match: $ =>
|
||||
prec.right(0,
|
||||
seq(
|
||||
'match',
|
||||
$.expr,
|
||||
'with',
|
||||
optional('|'),
|
||||
sepBy1('|', $.alt),
|
||||
),
|
||||
),
|
||||
|
||||
alt: $ =>
|
||||
prec.right(0,
|
||||
seq(
|
||||
$.pattern,
|
||||
'->',
|
||||
$.expr,
|
||||
),
|
||||
),
|
||||
|
||||
literal: $ =>
|
||||
choice(
|
||||
$.Nat,
|
||||
$.Int,
|
||||
$.Tez,
|
||||
$.String,
|
||||
$.Bytes,
|
||||
$.group,
|
||||
$.annotation,
|
||||
$.list,
|
||||
$.lambda,
|
||||
$.unit,
|
||||
$.record,
|
||||
$.record_update,
|
||||
),
|
||||
|
||||
record: $ =>
|
||||
seq(
|
||||
'{',
|
||||
sepBy1(';', $.record_field),
|
||||
'}',
|
||||
),
|
||||
|
||||
record_update: $ =>
|
||||
seq(
|
||||
'{',
|
||||
$.name,
|
||||
'with',
|
||||
sepBy1(';', $.record_field_update),
|
||||
'}',
|
||||
),
|
||||
|
||||
record_field_update: $ =>
|
||||
seq(
|
||||
sepBy1('.', $.name),
|
||||
'=',
|
||||
$.expr,
|
||||
),
|
||||
|
||||
record_field: $ =>
|
||||
seq(
|
||||
$.name,
|
||||
'=',
|
||||
$.expr,
|
||||
),
|
||||
|
||||
unit: $ => seq('(', ')'),
|
||||
|
||||
lambda: $ =>
|
||||
seq(
|
||||
'fun',
|
||||
repeat($.pattern_term),
|
||||
'->',
|
||||
$.expr,
|
||||
),
|
||||
|
||||
list: $ =>
|
||||
seq(
|
||||
'[',
|
||||
sepBy(';', $.expr),
|
||||
']',
|
||||
),
|
||||
|
||||
annotation: $ =>
|
||||
seq(
|
||||
'(',
|
||||
$.expr,
|
||||
':',
|
||||
$.type_expr,
|
||||
')',
|
||||
),
|
||||
|
||||
group: $ =>
|
||||
seq(
|
||||
'(',
|
||||
$.expr,
|
||||
')',
|
||||
),
|
||||
|
||||
if_then_else: $ =>
|
||||
prec.right(0,
|
||||
seq(
|
||||
'if',
|
||||
$.expr,
|
||||
'then',
|
||||
$.expr,
|
||||
'else',
|
||||
$.expr,
|
||||
),
|
||||
),
|
||||
|
||||
ref: $ =>
|
||||
choice(
|
||||
$.module_qualified,
|
||||
$.struct_qualified,
|
||||
$.name,
|
||||
$.constr,
|
||||
),
|
||||
|
||||
module_qualified: $ =>
|
||||
seq(
|
||||
$.constr,
|
||||
'.',
|
||||
$.name,
|
||||
),
|
||||
|
||||
struct_qualified: $ =>
|
||||
seq(
|
||||
$.name,
|
||||
nseq(seq('.', $.accessor)),
|
||||
),
|
||||
|
||||
accessor: $ => choice($.name, $.Int),
|
||||
|
||||
declaration: $ =>
|
||||
choice(
|
||||
$.type_decl,
|
||||
$.let_declaration,
|
||||
),
|
||||
|
||||
type_decl: $ =>
|
||||
seq(
|
||||
'type',
|
||||
$.type_name,
|
||||
'=',
|
||||
$.type_expr,
|
||||
),
|
||||
|
||||
type_expr: $ =>
|
||||
choice(
|
||||
$.fun_type,
|
||||
$.sum_type,
|
||||
$.record_type,
|
||||
),
|
||||
|
||||
fun_type: $ =>
|
||||
seq(
|
||||
$.cartesian,
|
||||
optional(seq('->', $.fun_type)),
|
||||
),
|
||||
|
||||
cartesian: $ =>
|
||||
prec.left(1,
|
||||
seq(
|
||||
$.core_type,
|
||||
optional(seq('*', sepBy('*', $.core_type))),
|
||||
),
|
||||
),
|
||||
|
||||
core_type: $ =>
|
||||
choice(
|
||||
$.type_name,
|
||||
par($.type_expr),
|
||||
$.module_type_name,
|
||||
$.type_application
|
||||
),
|
||||
|
||||
module_type_name: $ =>
|
||||
seq(
|
||||
$.module_name,
|
||||
'.',
|
||||
$.type_name,
|
||||
),
|
||||
|
||||
type_application: $ =>
|
||||
seq(
|
||||
choice($.core_type, $.type_tuple),
|
||||
$.type_name,
|
||||
),
|
||||
|
||||
type_tuple: $ =>
|
||||
par(tuple($.type_expr)),
|
||||
|
||||
sum_type: $ =>
|
||||
seq(
|
||||
optional('|'),
|
||||
sepBy1('|', $.variant),
|
||||
),
|
||||
|
||||
variant: $ =>
|
||||
seq(
|
||||
$.constr,
|
||||
optional(seq('of', $.fun_type)),
|
||||
),
|
||||
|
||||
record_type: $ =>
|
||||
seq(
|
||||
'{',
|
||||
sepBy(';', $.field_decl),
|
||||
'}',
|
||||
),
|
||||
|
||||
field_decl: $ =>
|
||||
seq(
|
||||
$.field_name,
|
||||
':',
|
||||
$.type_expr,
|
||||
),
|
||||
|
||||
let_declaration: $ =>
|
||||
seq(
|
||||
'let',
|
||||
optional($.rec),
|
||||
$.let_binding,
|
||||
repeat($.attr),
|
||||
),
|
||||
|
||||
let_binding: $ =>
|
||||
choice(
|
||||
seq(
|
||||
$.name,
|
||||
nseq($.pattern_term),
|
||||
optional($.type_annotation),
|
||||
'=',
|
||||
$.expr,
|
||||
),
|
||||
seq(
|
||||
$.pattern,
|
||||
optional($.type_annotation),
|
||||
'=',
|
||||
$.expr,
|
||||
),
|
||||
),
|
||||
|
||||
type_annotation: $ => seq(':', $.type_expr),
|
||||
|
||||
pattern_term: $ =>
|
||||
choice(
|
||||
$.pattern_record,
|
||||
$.constr,
|
||||
$.pattern_list,
|
||||
$.pattern_constant,
|
||||
$.name,
|
||||
$.pattern_grouped,
|
||||
),
|
||||
|
||||
pattern_grouped: $ =>
|
||||
seq(
|
||||
'(',
|
||||
$.pattern,
|
||||
optional($.type_annotation),
|
||||
')',
|
||||
),
|
||||
|
||||
pattern_list: $ => list__($.pattern),
|
||||
pattern_constant: $ =>
|
||||
choice(
|
||||
$.Nat,
|
||||
$.String,
|
||||
$.Bytes,
|
||||
$.Int,
|
||||
),
|
||||
|
||||
pattern_record: $ =>
|
||||
seq(
|
||||
'{',
|
||||
sepBy1(';', $.pattern_record_field),
|
||||
'}',
|
||||
),
|
||||
|
||||
pattern_record_field: $ =>
|
||||
seq(
|
||||
$.name,
|
||||
'=',
|
||||
$.pattern,
|
||||
),
|
||||
|
||||
pattern: $ => sepBy1('::', $.pattern_tuple),
|
||||
pattern_tuple: $ => sepBy1(',', $.construct),
|
||||
|
||||
construct: $ =>
|
||||
choice(
|
||||
seq($.constr, nseq($.pattern_term)),
|
||||
$.pattern_term,
|
||||
),
|
||||
|
||||
///////////////////////////////////////////
|
||||
|
||||
type_name: $ => $.ident,
|
||||
field_name: $ => $.ident,
|
||||
fun_name: $ => $.ident,
|
||||
struct_name: $ => $.ident,
|
||||
var: $ => $.ident,
|
||||
module_name: $ => $.Name_Capital,
|
||||
constr: $ => $.Name_Capital,
|
||||
ident: $ => $.Name,
|
||||
name: $ => $.Name,
|
||||
|
||||
comment: $ => /\/\/[^\n]*\n/,
|
||||
|
||||
ocaml_comment: $ => seq(
|
||||
'(*',
|
||||
repeat(choice(
|
||||
$.ocaml_comment,
|
||||
/[^\(]|\(?!\*/,
|
||||
)),
|
||||
'*)'
|
||||
),
|
||||
|
||||
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_]*/,
|
||||
Name_Capital: $ => /[A-Z][a-zA-Z0-9_]*/,
|
||||
Keyword: $ => /[A-Za-z][a-z]*/,
|
||||
|
||||
False: $ => 'False',
|
||||
True: $ => 'True',
|
||||
Unit: $ => 'Unit',
|
||||
None: $ => 'None',
|
||||
Some: $ => 'Some',
|
||||
skip: $ => 'skip',
|
||||
rec: $ => 'rec',
|
||||
|
||||
attr: $ => seq('[@@', $.name, ']'),
|
||||
}
|
||||
});
|
21
tools/lsp/pascaligo/LICENSE
Normal file
21
tools/lsp/pascaligo/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 LigoLANG SASU
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
840
tools/lsp/pascaligo/grammar.js
Normal file
840
tools/lsp/pascaligo/grammar.js
Normal file
@ -0,0 +1,840 @@
|
||||
let sepBy1 = (sep, rule) =>
|
||||
seq(
|
||||
rule,
|
||||
repeat(seq(sep, rule)),
|
||||
optional(sep)
|
||||
)
|
||||
|
||||
let sepBy = (sep, rule) => optional(sepBy1(sep, rule))
|
||||
|
||||
let op = (name, left, right, term) =>
|
||||
choice(
|
||||
seq(left, name, 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 par = x => seq('(', x, ')')
|
||||
let brackets = x => seq('[', x, ']')
|
||||
|
||||
let ne_injection = (Kind, element) =>
|
||||
choice(
|
||||
seq(
|
||||
Kind,
|
||||
sepBy1(';', element),
|
||||
'end',
|
||||
),
|
||||
seq(
|
||||
Kind,
|
||||
'[',
|
||||
sepBy1(';', element),
|
||||
']',
|
||||
),
|
||||
)
|
||||
|
||||
let injection = (Kind, element) =>
|
||||
choice(
|
||||
seq(
|
||||
Kind,
|
||||
sepBy(';', element),
|
||||
'end',
|
||||
),
|
||||
seq(
|
||||
Kind,
|
||||
'[',
|
||||
sepBy(';', element),
|
||||
']',
|
||||
),
|
||||
)
|
||||
|
||||
module.exports = grammar({
|
||||
name: 'PascaLigo',
|
||||
|
||||
word: $ => $.Keyword,
|
||||
extras: $ => [$.ocaml_comment, $.comment, /\s/],
|
||||
|
||||
rules: {
|
||||
// debug: $ => $.block,
|
||||
|
||||
contract: $ => repeat(field("declaration", $._declaration)),
|
||||
|
||||
_declaration: $ =>
|
||||
choice(
|
||||
$.type_decl,
|
||||
$.const_decl,
|
||||
$.fun_decl,
|
||||
$.attr_decl,
|
||||
$.include,
|
||||
),
|
||||
|
||||
attr_decl: $ =>
|
||||
seq(
|
||||
$._open_attr_decl,
|
||||
optional(';'),
|
||||
),
|
||||
|
||||
_open_attr_decl: $ =>
|
||||
injection("attributes",
|
||||
field("attribute", $.String)),
|
||||
|
||||
type_decl: $ =>
|
||||
seq(
|
||||
"type",
|
||||
field("typeName", $.Name),
|
||||
"is",
|
||||
field("typeValue", $._type_expr),
|
||||
optional(';'),
|
||||
),
|
||||
|
||||
type_expr : $ => $._type_expr,
|
||||
|
||||
_type_expr: $ =>
|
||||
choice(
|
||||
$.fun_type,
|
||||
$.sum_type,
|
||||
$.record_type,
|
||||
),
|
||||
|
||||
fun_type: $ =>
|
||||
choice(
|
||||
field("domain", $.cartesian),
|
||||
seq(
|
||||
field("domain", $.cartesian),
|
||||
'->',
|
||||
field("codomain", $.fun_type),
|
||||
),
|
||||
),
|
||||
|
||||
cartesian: $ =>
|
||||
sepBy1('*', field("element", $._core_type)),
|
||||
|
||||
_core_type: $ =>
|
||||
choice(
|
||||
$.Name,
|
||||
par($.type_expr),
|
||||
$.invokeBinary,
|
||||
$.invokeUnary,
|
||||
),
|
||||
|
||||
invokeBinary: $ =>
|
||||
seq(
|
||||
field("typeConstr", choice('map', 'big_map', $.Name)),
|
||||
field("arguments", $.type_tuple),
|
||||
),
|
||||
|
||||
invokeUnary: $ =>
|
||||
seq(
|
||||
field("typeConstr", choice('list', 'set')),
|
||||
field("arguments", par($._type_expr)),
|
||||
),
|
||||
|
||||
map: $ => 'map',
|
||||
big_map: $ => 'big_map',
|
||||
list: $ => 'list',
|
||||
set: $ => 'set',
|
||||
|
||||
type_tuple: $ => par(sepBy1(',', field("element", $._type_expr))),
|
||||
|
||||
sum_type: $ =>
|
||||
seq(
|
||||
optional('|'),
|
||||
sepBy1('|', field("variant", $.variant)),
|
||||
),
|
||||
|
||||
variant: $ =>
|
||||
choice(
|
||||
field("constructor", $.constr),
|
||||
seq(
|
||||
field("constructor", $.constr),
|
||||
'of',
|
||||
field("arguments", $.fun_type)
|
||||
),
|
||||
),
|
||||
|
||||
constr: $ => $.Name_Capital,
|
||||
|
||||
record_type: $ =>
|
||||
choice(
|
||||
seq('record', sepBy(';', field("field", $.field_decl)), 'end'),
|
||||
seq('record', '[', sepBy(';', field("field", $.field_decl)), ']'),
|
||||
),
|
||||
|
||||
field_decl: $ =>
|
||||
seq(
|
||||
field("fieldName", $.Name),
|
||||
':',
|
||||
field("fieldType", $._type_expr),
|
||||
),
|
||||
|
||||
fun_expr: $ =>
|
||||
seq(
|
||||
field("recursive", optional($.recursive)),
|
||||
'function',
|
||||
field("parameters", $.parameters),
|
||||
':',
|
||||
field("type", $._type_expr),
|
||||
'is',
|
||||
field("body", $._expr),
|
||||
),
|
||||
|
||||
_open_fun_decl: $ =>
|
||||
seq(
|
||||
field("recursive", optional($.recursive)),
|
||||
'function',
|
||||
field("name", $.Name),
|
||||
field("parameters", $.parameters),
|
||||
':',
|
||||
field("type", $._type_expr),
|
||||
'is',
|
||||
optional(seq(
|
||||
field("locals", $.block),
|
||||
'with',
|
||||
)),
|
||||
field("body", $._expr),
|
||||
),
|
||||
|
||||
fun_decl: $ =>
|
||||
seq(
|
||||
field("_open_fun_decl", $._open_fun_decl),
|
||||
optional(';'),
|
||||
),
|
||||
|
||||
parameters: $ => par(sepBy(';', field("parameter", $.param_decl))),
|
||||
|
||||
param_decl: $ =>
|
||||
seq(
|
||||
field("access", $.access),
|
||||
field("name", $.Name),
|
||||
':',
|
||||
field("type", $._param_type),
|
||||
),
|
||||
|
||||
access: $ => choice('var', 'const'),
|
||||
|
||||
_param_type: $ => $.fun_type,
|
||||
|
||||
_statement: $ =>
|
||||
choice(
|
||||
$._instruction,
|
||||
$._open_data_decl,
|
||||
$._open_attr_decl,
|
||||
),
|
||||
|
||||
_open_data_decl: $ =>
|
||||
choice(
|
||||
$.open_const_decl,
|
||||
$.open_var_decl,
|
||||
$._open_fun_decl,
|
||||
),
|
||||
|
||||
open_const_decl: $ =>
|
||||
seq(
|
||||
'const',
|
||||
field("name", $.Name),
|
||||
':',
|
||||
field("type", $._type_expr),
|
||||
'=',
|
||||
field("value", $._expr),
|
||||
),
|
||||
|
||||
open_var_decl: $ =>
|
||||
seq(
|
||||
'var',
|
||||
field("name", $.Name),
|
||||
':',
|
||||
field("type", $._type_expr),
|
||||
':=',
|
||||
field("value", $._expr),
|
||||
),
|
||||
|
||||
const_decl: $ =>
|
||||
seq(
|
||||
$.open_const_decl,
|
||||
optional(';'),
|
||||
),
|
||||
|
||||
_instruction: $ =>
|
||||
choice(
|
||||
$.conditional,
|
||||
$.case_instr,
|
||||
$.assignment,
|
||||
$.loop,
|
||||
$._proc_call,
|
||||
$.skip,
|
||||
$.record_patch,
|
||||
$.map_patch,
|
||||
$.set_patch,
|
||||
$.map_remove,
|
||||
$.set_remove,
|
||||
),
|
||||
|
||||
set_remove: $ =>
|
||||
seq(
|
||||
'remove',
|
||||
field("key", $._expr),
|
||||
'from',
|
||||
'set',
|
||||
field("container", $.path),
|
||||
),
|
||||
|
||||
map_remove: $ =>
|
||||
seq(
|
||||
'remove',
|
||||
field("key", $._expr),
|
||||
'from',
|
||||
'map',
|
||||
field("container", $.path),
|
||||
),
|
||||
|
||||
set_patch: $ =>
|
||||
seq(
|
||||
'patch',
|
||||
field("container", $.path),
|
||||
'with',
|
||||
ne_injection('set', field("key", $._expr)),
|
||||
),
|
||||
|
||||
map_patch: $ =>
|
||||
seq(
|
||||
'patch',
|
||||
field("container", $.path),
|
||||
'with',
|
||||
ne_injection('map', field("binding", $.binding)),
|
||||
),
|
||||
|
||||
binding: $ =>
|
||||
seq(
|
||||
field("key", $._expr),
|
||||
'->',
|
||||
field("value", $._expr),
|
||||
),
|
||||
|
||||
record_patch: $ =>
|
||||
seq(
|
||||
'patch',
|
||||
field("container", $.path),
|
||||
'with',
|
||||
ne_injection('record', field("binding", $.field_assignment)),
|
||||
),
|
||||
|
||||
_proc_call: $ =>
|
||||
$.fun_call,
|
||||
|
||||
conditional: $ =>
|
||||
seq(
|
||||
'if',
|
||||
field("selector", $._expr),
|
||||
'then',
|
||||
field("then", $.if_clause),
|
||||
optional(';'),
|
||||
'else',
|
||||
field("else", $.if_clause),
|
||||
),
|
||||
|
||||
if_clause: $ =>
|
||||
choice(
|
||||
$._instruction,
|
||||
$.clause_block,
|
||||
),
|
||||
|
||||
clause_block: $ =>
|
||||
choice(
|
||||
field("block", $.block),
|
||||
seq('{', sepBy1(';', field("statement", $._statement)), '}')
|
||||
),
|
||||
|
||||
block: $ =>
|
||||
choice(
|
||||
seq(
|
||||
'begin',
|
||||
sepBy(';', field("statement", $._statement)),
|
||||
'end',
|
||||
),
|
||||
seq(
|
||||
'block',
|
||||
'{',
|
||||
sepBy(';', field("statement", $._statement)),
|
||||
'}',
|
||||
),
|
||||
),
|
||||
|
||||
case_instr: $ =>
|
||||
choice(
|
||||
seq(
|
||||
'case',
|
||||
field("subject", $._expr),
|
||||
'of',
|
||||
optional('|'),
|
||||
sepBy1('|', field("case", $.case_clause_instr)),
|
||||
'end'
|
||||
),
|
||||
seq(
|
||||
'case',
|
||||
$._expr,
|
||||
'of',
|
||||
'[',
|
||||
optional('|'),
|
||||
sepBy1('|', field("case", $.case_clause_instr)),
|
||||
']'
|
||||
),
|
||||
),
|
||||
|
||||
case_clause_instr: $ =>
|
||||
seq(
|
||||
field("pattern", $.pattern),
|
||||
'->',
|
||||
field("body", $.if_clause),
|
||||
),
|
||||
|
||||
assignment: $ =>
|
||||
seq(
|
||||
field("LHS", $._lhs),
|
||||
':=',
|
||||
field("RHS", $._rhs),
|
||||
),
|
||||
|
||||
_rhs: $ => $._expr,
|
||||
_lhs: $ => choice($.path, $.map_lookup),
|
||||
|
||||
loop: $ => choice($.while_loop, $.for_loop),
|
||||
|
||||
while_loop: $ =>
|
||||
seq(
|
||||
'while',
|
||||
field("breaker", $._expr),
|
||||
field("body", $.block),
|
||||
),
|
||||
|
||||
for_loop: $ =>
|
||||
choice(
|
||||
seq(
|
||||
'for',
|
||||
field("name", $.Name),
|
||||
':=',
|
||||
field("begin", $._rhs),
|
||||
'to',
|
||||
field("end", $._expr),
|
||||
field("body", $.block),
|
||||
),
|
||||
seq(
|
||||
'for',
|
||||
field("key", $.Name),
|
||||
optional(seq('->', field("value", $.Name))),
|
||||
'in',
|
||||
field("kind", $.collection),
|
||||
field("collection", $._expr),
|
||||
field("body", $.block),
|
||||
),
|
||||
),
|
||||
|
||||
collection: $ => choice('map', 'set', 'list'),
|
||||
|
||||
interactive_expr: $ => $._expr,
|
||||
|
||||
_expr: $ =>
|
||||
choice(
|
||||
$.case_expr,
|
||||
$.cond_expr,
|
||||
$.disj_expr,
|
||||
$.fun_expr,
|
||||
),
|
||||
|
||||
case_expr: $ =>
|
||||
choice(
|
||||
seq(
|
||||
'case',
|
||||
field("subject", $._expr),
|
||||
'of',
|
||||
optional('|'),
|
||||
sepBy1('|', field("case", $.case_clause_expr)),
|
||||
'end'
|
||||
),
|
||||
seq(
|
||||
'case',
|
||||
field("subject", $._expr),
|
||||
'of',
|
||||
'[',
|
||||
optional('|'),
|
||||
sepBy1('|', field("case", $.case_clause_expr)),
|
||||
']'
|
||||
),
|
||||
),
|
||||
|
||||
case_clause_expr: $ =>
|
||||
seq(
|
||||
field("pattern", $.pattern),
|
||||
'->',
|
||||
field("body", $._expr),
|
||||
),
|
||||
|
||||
cond_expr: $ =>
|
||||
seq(
|
||||
'if',
|
||||
field("selector", $._expr),
|
||||
'then',
|
||||
field("then", $._expr),
|
||||
optional(';'),
|
||||
'else',
|
||||
field("else", $._expr),
|
||||
),
|
||||
|
||||
disj_expr: $ =>
|
||||
choice(
|
||||
field("the", $.conj_expr),
|
||||
seq(field("arg1", $.disj_expr), 'or', field("arg2", $.conj_expr)),
|
||||
),
|
||||
|
||||
conj_expr: $ =>
|
||||
choice(
|
||||
field("the", $.set_membership),
|
||||
seq(
|
||||
field("arg1", $.conj_expr),
|
||||
'and',
|
||||
field("arg2", $.set_membership)
|
||||
),
|
||||
),
|
||||
|
||||
set_membership: $ =>
|
||||
choice(
|
||||
field("the", $.comp_expr),
|
||||
seq(
|
||||
field("arg1", $._core_expr),
|
||||
'contains',
|
||||
field("arg2", $.set_membership)
|
||||
),
|
||||
),
|
||||
|
||||
comp_expr: $ =>
|
||||
choice(
|
||||
field("the", $.cat_expr),
|
||||
seq(
|
||||
field("arg1", $.comp_expr),
|
||||
field("compare", $.comparison),
|
||||
field("arg2", $.cat_expr),
|
||||
),
|
||||
),
|
||||
|
||||
comparison: $ => choice('<', '<=', '>', '>=', '=', '=/='),
|
||||
|
||||
cat_expr: $ =>
|
||||
choice(
|
||||
field("the", $.cons_expr),
|
||||
seq(
|
||||
field("arg1", $.cons_expr),
|
||||
'^',
|
||||
field("arg2", $.cat_expr),
|
||||
),
|
||||
),
|
||||
|
||||
cons_expr: $ =>
|
||||
choice(
|
||||
field("the", $.add_expr),
|
||||
seq(
|
||||
field("arg1", $.add_expr),
|
||||
'#',
|
||||
field("arg2", $.cons_expr)
|
||||
),
|
||||
),
|
||||
|
||||
add_expr: $ =>
|
||||
choice(
|
||||
field("the", $.mult_expr),
|
||||
seq(
|
||||
field("arg1", $.add_expr),
|
||||
field("add", $.adder),
|
||||
field("arg2", $.mult_expr),
|
||||
),
|
||||
),
|
||||
|
||||
adder: $ => choice('-', '+'),
|
||||
|
||||
mult_expr: $ =>
|
||||
choice(
|
||||
field("the", $.unary_expr),
|
||||
seq(
|
||||
field("arg1", $.mult_expr),
|
||||
field("multiply", $.multiplier),
|
||||
field("arg2", $.unary_expr),
|
||||
),
|
||||
),
|
||||
|
||||
multiplier: $ => choice('/', '*', 'mod'),
|
||||
|
||||
unary_expr: $ =>
|
||||
choice(
|
||||
field("the", $._core_expr),
|
||||
seq(
|
||||
field("negate", $.negate),
|
||||
field("arg", $._core_expr),
|
||||
),
|
||||
),
|
||||
|
||||
negate: $ => choice('-', 'not'),
|
||||
|
||||
_core_expr: $ =>
|
||||
choice(
|
||||
$.Int,
|
||||
$.Nat,
|
||||
$.Tez,
|
||||
$.Name,
|
||||
$.module_field,
|
||||
$.String,
|
||||
$.Bytes,
|
||||
$.False,
|
||||
$.True,
|
||||
$.Unit,
|
||||
$.annot_expr,
|
||||
$.tuple_expr,
|
||||
$.list_expr,
|
||||
$.None,
|
||||
$._fun_call_or_par_or_projection,
|
||||
$._map_expr,
|
||||
$.set_expr,
|
||||
$.record_expr,
|
||||
$.update_record,
|
||||
$.constr_call,
|
||||
$.Some_call,
|
||||
),
|
||||
|
||||
constr_call: $ =>
|
||||
seq(
|
||||
field("constr", $.constr),
|
||||
optional(
|
||||
field("arguments", $.arguments)
|
||||
),
|
||||
),
|
||||
|
||||
Some_call: $ =>
|
||||
seq(
|
||||
field("constr", 'Some'),
|
||||
field("arguments", $.arguments),
|
||||
),
|
||||
|
||||
_fun_call_or_par_or_projection: $ =>
|
||||
choice(
|
||||
$.par_call,
|
||||
$.projection_call,
|
||||
$.fun_call,
|
||||
),
|
||||
|
||||
par_call: $ =>
|
||||
prec.right(1, seq(
|
||||
par(field("f", $._expr)),
|
||||
optional(field("arguments", $.arguments))
|
||||
)),
|
||||
|
||||
projection_call: $ => seq(
|
||||
field("f", $._projection),
|
||||
optional(field("arguments", $.arguments)),
|
||||
),
|
||||
|
||||
annot_expr: $ =>
|
||||
par(seq(
|
||||
field("subject", $.disj_expr),
|
||||
':',
|
||||
field("type", $._type_expr)
|
||||
)),
|
||||
|
||||
set_expr: $ => injection('set', $._expr),
|
||||
|
||||
_map_expr: $ =>
|
||||
choice(
|
||||
$.map_lookup,
|
||||
$.map_injection,
|
||||
$.big_map_injection,
|
||||
),
|
||||
|
||||
map_injection: $ => injection('map', $.binding),
|
||||
big_map_injection: $ => injection('big_map', $.binding),
|
||||
|
||||
map_lookup: $ =>
|
||||
seq(
|
||||
field("container", $.path),
|
||||
brackets(field("index", $._expr)),
|
||||
),
|
||||
|
||||
path: $ => choice($.Name, $._projection),
|
||||
|
||||
module_field: $ =>
|
||||
seq(
|
||||
field("module", $.Name_Capital),
|
||||
'.',
|
||||
field("method", $._module_fun),
|
||||
),
|
||||
|
||||
_module_fun: $ =>
|
||||
choice(
|
||||
$.Name,
|
||||
$.map,
|
||||
$.or,
|
||||
$.and,
|
||||
$.remove,
|
||||
),
|
||||
|
||||
or: $ => 'or',
|
||||
and: $ => 'and',
|
||||
remove: $ => 'remove',
|
||||
|
||||
_projection: $ =>
|
||||
choice(
|
||||
$.data_projection,
|
||||
$.module_projection,
|
||||
),
|
||||
|
||||
data_projection: $ => seq(
|
||||
field("struct", $.Name),
|
||||
'.',
|
||||
sepBy1('.', field("index", $.selection)),
|
||||
),
|
||||
|
||||
module_projection: $ =>
|
||||
seq(
|
||||
field("module", $.Name_Capital),
|
||||
'.',
|
||||
field("index", $.Name),
|
||||
'.',
|
||||
sepBy1('.', field("index", $.selection)),
|
||||
),
|
||||
|
||||
selection: $ => choice($.Name, $.Int),
|
||||
|
||||
record_expr: $ =>
|
||||
choice(
|
||||
seq(
|
||||
'record',
|
||||
sepBy(';', field("assignment", $.field_assignment)),
|
||||
'end',
|
||||
),
|
||||
seq(
|
||||
'record',
|
||||
'[',
|
||||
sepBy(';', field("assignment", $.field_assignment)),
|
||||
']',
|
||||
),
|
||||
),
|
||||
|
||||
update_record: $ =>
|
||||
seq(
|
||||
field("record", $.path),
|
||||
'with',
|
||||
ne_injection('record', field("assignment", $.field_path_assignment)),
|
||||
),
|
||||
|
||||
field_assignment: $ =>
|
||||
seq(
|
||||
field("name", $.Name),
|
||||
'=',
|
||||
field("_rhs", $._expr),
|
||||
),
|
||||
|
||||
field_path_assignment: $ =>
|
||||
seq(
|
||||
sepBy1('.', field("index", $.Name)),
|
||||
'=',
|
||||
field("_rhs", $._expr),
|
||||
),
|
||||
|
||||
fun_call: $ =>
|
||||
seq(
|
||||
field("f", choice($.Name, $.module_field)),
|
||||
field("arguments", $.arguments),
|
||||
),
|
||||
|
||||
tuple_expr: $ => par(sepBy1(',', field("element", $._expr))),
|
||||
arguments: $ => par(sepBy(',', field("argument", $._expr))),
|
||||
|
||||
list_expr: $ => choice($.list_injection, 'nil'),
|
||||
|
||||
list_injection: $ => injection('list', field("element", $._expr)),
|
||||
|
||||
pattern: $ => sepBy1('#', field("arg", $._core_pattern)),
|
||||
|
||||
_core_pattern: $ =>
|
||||
choice(
|
||||
$.Name,
|
||||
'_',
|
||||
$.Int,
|
||||
$.Nat,
|
||||
$.String,
|
||||
$.list_pattern,
|
||||
$.tuple_pattern,
|
||||
$._constr_pattern,
|
||||
),
|
||||
|
||||
list_pattern: $ =>
|
||||
choice(
|
||||
injection("list", field("element", $._core_pattern)),
|
||||
'nil',
|
||||
par($.cons_pattern),
|
||||
),
|
||||
|
||||
cons_pattern: $ =>
|
||||
seq(
|
||||
field("head", $._core_pattern),
|
||||
'#',
|
||||
field("tail", $.pattern),
|
||||
),
|
||||
|
||||
tuple_pattern: $ =>
|
||||
par(sepBy1(',', field("element", $._core_pattern))),
|
||||
|
||||
_constr_pattern: $ => choice(
|
||||
$.Unit,
|
||||
$.False,
|
||||
$.True,
|
||||
$.None,
|
||||
$.Some_pattern,
|
||||
$.user_constr_pattern,
|
||||
),
|
||||
|
||||
Some_pattern: $ =>
|
||||
seq(
|
||||
field("constr", 'Some'),
|
||||
par(field("arg", $._core_pattern)),
|
||||
),
|
||||
|
||||
user_constr_pattern: $ =>
|
||||
seq(
|
||||
field("constr", $.constr),
|
||||
optional(field("arguments", $.tuple_pattern)),
|
||||
),
|
||||
|
||||
///////////////////////////////////////////
|
||||
|
||||
comment: $ => /\/\/[^\n]*\n/,
|
||||
|
||||
ocaml_comment: $ =>
|
||||
seq(
|
||||
'(*',
|
||||
repeat(choice(
|
||||
$.ocaml_comment,
|
||||
/'([^'\\]|\\[\\"'ntbr ]|\\[0-9][0-9][0-9]|\\x[0-9A-Fa-f][0-9A-Fa-f]|\\o[0-3][0-7][0-7])'/,
|
||||
/"([^\\"]|\\(.|\n))*"/,
|
||||
/[A-Za-z_][a-zA-Z0-9_']*/,
|
||||
/[^('"{*A-Za-z_]+/,
|
||||
'(', "'", '*',
|
||||
)),
|
||||
'*)'
|
||||
),
|
||||
|
||||
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_]*/,
|
||||
Name_Capital: $ => /[A-Z][a-zA-Z0-9_]*/,
|
||||
Keyword: $ => /[A-Za-z][a-z]*/,
|
||||
|
||||
False: $ => 'False',
|
||||
True: $ => 'True',
|
||||
Unit: $ => 'Unit',
|
||||
None: $ => 'None',
|
||||
skip: $ => 'skip',
|
||||
recursive: $ => 'recursive',
|
||||
}
|
||||
});
|
1
tools/lsp/pascaligo/test.ligo
Normal file
1
tools/lsp/pascaligo/test.ligo
Normal file
@ -0,0 +1 @@
|
||||
Some(Unit) # Some(Foo(Bar, Unit))
|
29
tools/lsp/pascaligo/test/corpus/examples.txt
Normal file
29
tools/lsp/pascaligo/test/corpus/examples.txt
Normal file
@ -0,0 +1,29 @@
|
||||
=========
|
||||
Includes
|
||||
=========
|
||||
|
||||
#include "foo.bar"
|
||||
#include "qux.ligo"
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(include
|
||||
(string))
|
||||
(include
|
||||
(string)))
|
||||
|
||||
=========
|
||||
Functions
|
||||
=========
|
||||
|
||||
function add (const a : int ; const b : int) : int is
|
||||
block { skip } with 1
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(include
|
||||
(string))
|
||||
(include
|
||||
(string)))
|
12
tools/lsp/squirrel/app/Main.hs
Normal file
12
tools/lsp/squirrel/app/Main.hs
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
import ParseTree
|
||||
import Parser
|
||||
import AST
|
||||
|
||||
import System.Environment
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
[fin] <- getArgs
|
||||
toParseTree fin >>= print
|
||||
runParser contract fin >>= print
|
1
tools/lsp/squirrel/examples/sanity.ligo
Normal file
1
tools/lsp/squirrel/examples/sanity.ligo
Normal file
@ -0,0 +1 @@
|
||||
function foo (var x : int) is 1
|
41
tools/lsp/squirrel/package.yaml
Normal file
41
tools/lsp/squirrel/package.yaml
Normal file
@ -0,0 +1,41 @@
|
||||
|
||||
name: squirrel
|
||||
|
||||
dependencies:
|
||||
- base
|
||||
- bytestring
|
||||
- mtl
|
||||
- text
|
||||
- tree-sitter
|
||||
- pretty
|
||||
|
||||
default-extensions:
|
||||
- LambdaCase
|
||||
- BlockArguments
|
||||
- OverloadedStrings
|
||||
- GeneralisedNewtypeDeriving
|
||||
- DerivingStrategies
|
||||
- NamedFieldPuns
|
||||
- BangPatterns
|
||||
|
||||
ghc-options: -freverse-errors -Wall
|
||||
|
||||
library:
|
||||
source-dirs:
|
||||
- src/
|
||||
|
||||
include-dirs:
|
||||
- vendor
|
||||
|
||||
c-sources:
|
||||
- vendor/parser.c
|
||||
|
||||
executables:
|
||||
squirrel:
|
||||
main: Main.hs
|
||||
|
||||
source-dirs:
|
||||
- app/
|
||||
|
||||
dependencies:
|
||||
- squirrel
|
53
tools/lsp/squirrel/squirrel.cabal
Normal file
53
tools/lsp/squirrel/squirrel.cabal
Normal file
@ -0,0 +1,53 @@
|
||||
cabal-version: 1.12
|
||||
|
||||
-- This file has been generated from package.yaml by hpack version 0.31.2.
|
||||
--
|
||||
-- see: https://github.com/sol/hpack
|
||||
--
|
||||
-- hash: 67ec249f56014b97ea36ef06bb0dad0986e0f632e7fe62dc4393a5a081cb0493
|
||||
|
||||
name: squirrel
|
||||
version: 0.0.0
|
||||
build-type: Simple
|
||||
|
||||
library
|
||||
exposed-modules:
|
||||
AST
|
||||
Parser
|
||||
ParseTree
|
||||
other-modules:
|
||||
Paths_squirrel
|
||||
hs-source-dirs:
|
||||
src/
|
||||
default-extensions: LambdaCase BlockArguments OverloadedStrings GeneralisedNewtypeDeriving DerivingStrategies NamedFieldPuns BangPatterns
|
||||
ghc-options: -freverse-errors -Wall
|
||||
include-dirs:
|
||||
vendor
|
||||
c-sources:
|
||||
vendor/parser.c
|
||||
build-depends:
|
||||
base
|
||||
, bytestring
|
||||
, mtl
|
||||
, pretty
|
||||
, text
|
||||
, tree-sitter
|
||||
default-language: Haskell2010
|
||||
|
||||
executable squirrel
|
||||
main-is: Main.hs
|
||||
other-modules:
|
||||
Paths_squirrel
|
||||
hs-source-dirs:
|
||||
app/
|
||||
default-extensions: LambdaCase BlockArguments OverloadedStrings GeneralisedNewtypeDeriving DerivingStrategies NamedFieldPuns BangPatterns
|
||||
ghc-options: -freverse-errors -Wall
|
||||
build-depends:
|
||||
base
|
||||
, bytestring
|
||||
, mtl
|
||||
, pretty
|
||||
, squirrel
|
||||
, text
|
||||
, tree-sitter
|
||||
default-language: Haskell2010
|
209
tools/lsp/squirrel/src/AST.hs
Normal file
209
tools/lsp/squirrel/src/AST.hs
Normal file
@ -0,0 +1,209 @@
|
||||
|
||||
{- annotate tree with ranges, add offsets to ranges, store verbatim in Wrong* -}
|
||||
|
||||
module AST where
|
||||
|
||||
import Control.Monad.State
|
||||
|
||||
import qualified Data.Text as Text
|
||||
import Data.Text (Text)
|
||||
import Data.Void
|
||||
|
||||
import Parser
|
||||
import ParseTree
|
||||
|
||||
import Debug.Trace
|
||||
|
||||
type TODO = Text
|
||||
|
||||
data Contract info
|
||||
= Contract info [Declaration info]
|
||||
| WrongContract Error
|
||||
deriving stock (Show)
|
||||
|
||||
instance Stubbed (Contract info) where stub = WrongContract
|
||||
|
||||
data Declaration info
|
||||
= ValueDecl info (Binding info)
|
||||
| WrongDecl Error
|
||||
deriving stock (Show)
|
||||
|
||||
instance Stubbed (Declaration info) where stub = WrongDecl
|
||||
|
||||
data Binding info
|
||||
= Irrefutable info (Pattern info) (Expr info)
|
||||
| Function info Bool (Name info) [VarDecl info] (Type info) TODO
|
||||
| WrongBinding Error
|
||||
deriving stock (Show)
|
||||
|
||||
instance Stubbed (Binding info) where stub = WrongBinding
|
||||
|
||||
data VarDecl info
|
||||
= Decl info (Mutable info) (Name info) (Type info)
|
||||
| WrongVarDecl Error
|
||||
deriving stock (Show)
|
||||
|
||||
instance Stubbed (VarDecl info) where stub = WrongVarDecl
|
||||
|
||||
data Mutable info
|
||||
= Mutable info
|
||||
| Immutable info
|
||||
| WrongMutable Error
|
||||
deriving stock (Show)
|
||||
|
||||
instance Stubbed (Mutable info) where stub = WrongMutable
|
||||
|
||||
data Type info
|
||||
= TArrow info (Type info) (Type info)
|
||||
| Record info [(Name info, Type info)]
|
||||
| TVar info (Name info)
|
||||
| Sum info [(Name info, [Type info])]
|
||||
| Product info [Type info]
|
||||
| TApply info (Name info) [Type info]
|
||||
| WrongType Error
|
||||
deriving stock (Show)
|
||||
|
||||
instance Stubbed (Type info) where stub = WrongType
|
||||
|
||||
data Expr info
|
||||
= Let info [Declaration info] (Expr info)
|
||||
| Apply info (Expr info) (Expr info)
|
||||
| Constant info (Constant info)
|
||||
| Ident info (QualifiedName info)
|
||||
| WrongExpr Error
|
||||
deriving stock (Show)
|
||||
|
||||
instance Stubbed (Expr info) where stub = WrongExpr
|
||||
|
||||
data Constant info
|
||||
= Int info Int
|
||||
| String info Text
|
||||
| Float info Double
|
||||
| Bytes info Text
|
||||
| WrongConstant Error
|
||||
deriving stock (Show)
|
||||
|
||||
instance Stubbed (Constant info) where stub = WrongConstant
|
||||
|
||||
data Pattern info
|
||||
= IsConstr info (Name info) [Pattern info]
|
||||
| IsConstant info (Constant info)
|
||||
| IsVar info (Name info)
|
||||
| WrongPattern Error
|
||||
deriving stock (Show)
|
||||
|
||||
instance Stubbed (Pattern info) where stub = WrongPattern
|
||||
|
||||
data QualifiedName info = QualifiedName
|
||||
{ source :: Name info
|
||||
, path :: [Name info]
|
||||
}
|
||||
| WrongQualifiedName Error
|
||||
deriving stock (Show)
|
||||
|
||||
instance Stubbed (QualifiedName info) where stub = WrongQualifiedName
|
||||
|
||||
data Name info = Name
|
||||
{ info :: info
|
||||
, raw :: Text
|
||||
}
|
||||
| WrongName Error
|
||||
|
||||
instance Stubbed (Name info) where stub = WrongName
|
||||
|
||||
instance Show (Name info) where
|
||||
show = \case
|
||||
Name _ raw -> Text.unpack raw
|
||||
WrongName r -> "(Name? " ++ show r ++ ")"
|
||||
|
||||
name :: Parser (Name Range)
|
||||
name = do
|
||||
(raw, info) <- range (token "Name")
|
||||
return Name {info, raw}
|
||||
|
||||
contract :: Parser (Contract Range)
|
||||
contract = subtree "contract" do
|
||||
(decls, info) <- range $ many "declaration" declaration
|
||||
return (Contract info decls)
|
||||
|
||||
declaration :: Parser (Declaration Range)
|
||||
declaration =
|
||||
field "declaration" do
|
||||
(b, info) <- range binding
|
||||
return (ValueDecl info b)
|
||||
|
||||
par x = do
|
||||
consume "("
|
||||
a <- x
|
||||
consume ")"
|
||||
return a
|
||||
|
||||
binding :: Parser (Binding Range)
|
||||
binding = do
|
||||
info <- getRange
|
||||
"fun_decl" `subtree` do
|
||||
recur <- optional do
|
||||
field "recursive" do
|
||||
token "recursive"
|
||||
consume "function"
|
||||
name <- field "name" do
|
||||
name
|
||||
params <- field "parameters" $ par (many "param" paramDecl)
|
||||
consume ":"
|
||||
ty <- field "type" type_
|
||||
consume "is"
|
||||
get >>= traceShowM
|
||||
expr <- field "locals" anything
|
||||
return (Function info (recur == Just "recursive") name params ty expr)
|
||||
|
||||
paramDecl :: Parser (VarDecl Range)
|
||||
paramDecl = do
|
||||
info <- getRange
|
||||
"parameter" `field` do
|
||||
info' <- getRange
|
||||
mutable <- do
|
||||
"access" `subtree` select
|
||||
[ do consume "var"
|
||||
return $ Mutable info'
|
||||
, do consume "const"
|
||||
return $ Immutable info'
|
||||
]
|
||||
name <- field "name" name
|
||||
consume ":"
|
||||
ty <- field "type" type_
|
||||
return (Decl info mutable name ty)
|
||||
|
||||
newtype_ = do
|
||||
type_
|
||||
|
||||
type_ :: Parser (Type Range)
|
||||
type_ =
|
||||
fun_type
|
||||
where
|
||||
fun_type :: Parser (Type Range)
|
||||
fun_type = do
|
||||
info <- getRange
|
||||
domain <- field "domain" cartesian
|
||||
codomain <- optional do
|
||||
consume "->"
|
||||
fun_type
|
||||
return case codomain of
|
||||
Just co -> TArrow info domain co
|
||||
Nothing -> domain
|
||||
|
||||
cartesian = do
|
||||
info <- getRange
|
||||
Product info <$> some "corety" core_type
|
||||
|
||||
core_type = do
|
||||
info <- getRange
|
||||
select
|
||||
[ TVar info <$> typename
|
||||
]
|
||||
|
||||
typename = name
|
||||
|
||||
tuple :: Text -> Parser a -> Parser [a]
|
||||
tuple msg = par . some msg
|
||||
|
||||
example = "../../ligo/src/test/contracts/address.ligo"
|
158
tools/lsp/squirrel/src/ParseTree.hs
Normal file
158
tools/lsp/squirrel/src/ParseTree.hs
Normal file
@ -0,0 +1,158 @@
|
||||
|
||||
{-# language Strict #-}
|
||||
|
||||
module ParseTree where
|
||||
|
||||
import Data.IORef
|
||||
import qualified Data.Text as Text
|
||||
import Data.Traversable (for)
|
||||
import Data.Text.Foreign (withCStringLen)
|
||||
import Data.Text.IO as IO
|
||||
|
||||
import TreeSitter.Parser
|
||||
import TreeSitter.Tree
|
||||
import TreeSitter.Language
|
||||
import TreeSitter.Node
|
||||
import Foreign.C.String (peekCString)
|
||||
import Foreign.Ptr ( Ptr
|
||||
, nullPtr
|
||||
)
|
||||
import Foreign.Marshal.Alloc ( alloca )
|
||||
import Foreign.Marshal.Array ( allocaArray )
|
||||
import Foreign.Storable ( peek
|
||||
, peekElemOff
|
||||
, poke
|
||||
)
|
||||
import Control.Monad ((>=>))
|
||||
|
||||
import Text.PrettyPrint hiding ((<>))
|
||||
|
||||
import Paths_squirrel
|
||||
|
||||
-- import Debug.Trace
|
||||
|
||||
foreign import ccall unsafe tree_sitter_PascaLigo :: Ptr Language
|
||||
|
||||
getNodeTypesPath :: IO FilePath
|
||||
getNodeTypesPath = getDataFileName "../pascaligo/src/node-types.json"
|
||||
|
||||
data ParseTree = ParseTree
|
||||
{ ptID :: Int
|
||||
, ptName :: Text.Text
|
||||
, ptStart :: Int
|
||||
, ptFinish :: Int
|
||||
, ptRange :: Range
|
||||
, ptChildren :: ParseForest
|
||||
}
|
||||
|
||||
data ParseForest = Forest
|
||||
{ pfID :: Int
|
||||
, pfGrove :: [(Text.Text, ParseTree)]
|
||||
, pfRange :: Range
|
||||
}
|
||||
|
||||
instance Show ParseTree where
|
||||
show = show . ppTree
|
||||
|
||||
instance Show ParseForest where
|
||||
show = show . vcat . map ppPair . pfGrove
|
||||
|
||||
data Range = Range
|
||||
{ rStart :: (Int, Int)
|
||||
, rFinish :: (Int, Int)
|
||||
}
|
||||
deriving stock (Show)
|
||||
|
||||
diffRange :: Range -> Range -> Range
|
||||
diffRange (Range ws wf) (Range ps _) = Range (max ws ps) wf
|
||||
|
||||
ppTree :: ParseTree -> Doc
|
||||
ppTree (ParseTree _ n _ _ (Range (sr, sc) (fr, fc)) (Forest _ cs _)) =
|
||||
parens
|
||||
( hang
|
||||
( quotes (text (Text.unpack n))
|
||||
<+> brackets
|
||||
( int sr <> ":" <> int sc
|
||||
<> " - "
|
||||
<> int fr <> ":" <> int fc
|
||||
)
|
||||
)
|
||||
2
|
||||
(vcat (map ppPair cs)))
|
||||
|
||||
ppPair (field, tree) =
|
||||
if field == Text.empty
|
||||
then nest 2 $ ppTree tree
|
||||
else hang (text (Text.unpack field) <> ": ") 2 (ppTree tree)
|
||||
|
||||
toParseTree :: FilePath -> IO ParseForest
|
||||
toParseTree fin = do
|
||||
parser <- ts_parser_new
|
||||
True <- ts_parser_set_language parser tree_sitter_PascaLigo
|
||||
|
||||
src <- IO.readFile fin
|
||||
|
||||
idCounter <- newIORef 0
|
||||
|
||||
withCStringLen src \(str, len) -> do
|
||||
tree <- ts_parser_parse_string parser nullPtr str len
|
||||
finalTree <- withRootNode tree (peek >=> go idCounter)
|
||||
return $ Forest 0 [("", finalTree)] (ptRange finalTree)
|
||||
|
||||
where
|
||||
nextID :: IORef Int -> IO Int
|
||||
nextID ref = do
|
||||
modifyIORef' ref (+ 1)
|
||||
readIORef ref
|
||||
|
||||
go :: IORef Int -> Node -> IO ParseTree
|
||||
go idCounter node = do
|
||||
let count = fromIntegral $ nodeChildCount node
|
||||
allocaArray count \children -> do
|
||||
alloca \tsNodePtr -> do
|
||||
poke tsNodePtr $ nodeTSNode node
|
||||
ts_node_copy_child_nodes tsNodePtr children
|
||||
nodes <- for [0.. count - 1] \i -> do
|
||||
peekElemOff children i
|
||||
|
||||
trees <- for nodes \node' -> do
|
||||
tree <- go idCounter node'
|
||||
field <-
|
||||
if nodeFieldName node' == nullPtr
|
||||
then return ""
|
||||
else peekCString $ nodeFieldName node'
|
||||
return (Text.pack field, tree)
|
||||
|
||||
ty <- peekCString $ nodeType node
|
||||
|
||||
TSNode start _ _ _ _ <- peek tsNodePtr
|
||||
|
||||
let
|
||||
start2D = nodeStartPoint node
|
||||
finish2D = nodeEndPoint node
|
||||
i = fromIntegral
|
||||
|
||||
treeID <- nextID idCounter
|
||||
fID <- nextID idCounter
|
||||
|
||||
let
|
||||
range = Range
|
||||
{ rStart =
|
||||
( i $ pointRow start2D + 1
|
||||
, i $ pointColumn start2D + 1
|
||||
)
|
||||
|
||||
, rFinish =
|
||||
( i $ pointRow finish2D + 1
|
||||
, i $ pointColumn finish2D + 1
|
||||
)
|
||||
}
|
||||
|
||||
return $ ParseTree
|
||||
{ ptID = treeID
|
||||
, ptName = Text.pack ty
|
||||
, ptStart = fromIntegral start
|
||||
, ptFinish = fromIntegral $ nodeEndByte node
|
||||
, ptRange = range
|
||||
, ptChildren = Forest fID trees range
|
||||
}
|
217
tools/lsp/squirrel/src/Parser.hs
Normal file
217
tools/lsp/squirrel/src/Parser.hs
Normal file
@ -0,0 +1,217 @@
|
||||
|
||||
module Parser where
|
||||
|
||||
import Control.Monad.State
|
||||
import Control.Monad.Writer
|
||||
import Control.Monad.Reader
|
||||
import Control.Monad.Except
|
||||
import Control.Monad.Identity
|
||||
|
||||
import Data.Text.Encoding
|
||||
-- import Data.Traversable (for)
|
||||
import Data.Text (Text, pack, unpack)
|
||||
|
||||
import qualified Data.ByteString as ByteString
|
||||
import Data.ByteString (ByteString)
|
||||
|
||||
import ParseTree
|
||||
|
||||
-- import Debug.Trace
|
||||
|
||||
data Error
|
||||
= Expected Text Range
|
||||
| Unexpected Range
|
||||
deriving stock (Show)
|
||||
|
||||
newtype Parser a = Parser
|
||||
{ unParser
|
||||
:: WriterT [Error]
|
||||
( ReaderT ParserEnv
|
||||
( StateT ParseForest
|
||||
( ExceptT Error
|
||||
( Identity ))))
|
||||
a
|
||||
}
|
||||
deriving newtype
|
||||
( Functor
|
||||
, Applicative
|
||||
, Monad
|
||||
, MonadState ParseForest
|
||||
, MonadWriter [Error]
|
||||
, MonadReader ParserEnv
|
||||
, MonadError Error
|
||||
)
|
||||
|
||||
takeNext :: Text -> Parser ParseTree
|
||||
takeNext msg = do
|
||||
st@Forest {pfGrove, pfRange} <- get
|
||||
case pfGrove of
|
||||
[] -> die msg
|
||||
(_, t) : f -> do
|
||||
put st
|
||||
{ pfRange = diffRange pfRange (ptRange t)
|
||||
, pfGrove = f
|
||||
}
|
||||
return t
|
||||
|
||||
field :: Stubbed a => Text -> Parser a -> Parser a
|
||||
field name parser = do
|
||||
grove <- gets pfGrove
|
||||
case grove of
|
||||
(name', t) : _
|
||||
| name == name' -> do
|
||||
sandbox True t
|
||||
|
||||
_ -> do
|
||||
case lookup name grove of
|
||||
Just tree -> sandbox False tree
|
||||
Nothing -> die name
|
||||
|
||||
where
|
||||
sandbox firstOne tree@ParseTree {ptID, ptRange} = do
|
||||
st@Forest {pfGrove = grove, pfRange = rng} <- get
|
||||
let grove' = delete name grove
|
||||
put Forest
|
||||
{ pfID = ptID
|
||||
, pfGrove = [(name, tree)]
|
||||
, pfRange = ptRange
|
||||
}
|
||||
|
||||
stubbed name parser <* put st
|
||||
{ pfGrove = grove'
|
||||
, pfRange = if firstOne then diffRange rng ptRange else rng
|
||||
}
|
||||
|
||||
fallback :: Stubbed a => Text -> Parser a
|
||||
fallback msg = (stub . Expected msg) <$> getRange
|
||||
|
||||
die :: Text -> Parser a
|
||||
die msg = throwError . Expected msg =<< getRange
|
||||
|
||||
stubbed :: Stubbed a => Text -> Parser a -> Parser a
|
||||
stubbed msg parser = do
|
||||
parser <|> fallback msg
|
||||
|
||||
subtree :: Text -> Parser a -> Parser a
|
||||
subtree msg parser = do
|
||||
ParseTree {ptChildren, ptName} <- takeNext msg
|
||||
if ptName == msg
|
||||
then do
|
||||
save <- get
|
||||
put ptChildren
|
||||
parser <* put save
|
||||
else do
|
||||
die msg
|
||||
|
||||
(<|>) :: Parser a -> Parser a -> Parser a
|
||||
Parser l <|> Parser r = Parser (l `catchError` const r)
|
||||
|
||||
select :: [Parser a] -> Parser a
|
||||
select = foldl1 (<|>)
|
||||
|
||||
optional :: Parser a -> Parser (Maybe a)
|
||||
optional p = fmap Just p <|> return Nothing
|
||||
|
||||
many :: Text -> Parser a -> Parser [a]
|
||||
many msg p = many'
|
||||
where
|
||||
many' = some' <|> pure []
|
||||
some' = (:) <$> (productive msg p) <*> many'
|
||||
|
||||
some :: Text -> Parser a -> Parser [a]
|
||||
some msg p = some'
|
||||
where
|
||||
many' = some' <|> pure []
|
||||
some' = (:) <$> (productive msg p) <*> many'
|
||||
|
||||
getTreeID :: Parser (Maybe Int)
|
||||
getTreeID = Parser do
|
||||
pfGrove <$> get >>= return . \case
|
||||
[] -> Nothing
|
||||
(_, tree) : _ -> Just (ptID tree)
|
||||
|
||||
productive :: Text -> Parser a -> Parser a
|
||||
productive msg p = do
|
||||
was <- getTreeID
|
||||
res <- p
|
||||
now <- getTreeID
|
||||
unless (was /= now) do
|
||||
error ("unproductive: " ++ unpack msg)
|
||||
return res
|
||||
|
||||
data ParserEnv = ParserEnv
|
||||
{ peRange :: Range
|
||||
, peSource :: ByteString
|
||||
}
|
||||
|
||||
runParser :: Parser a -> FilePath -> IO (a, [Error])
|
||||
runParser (Parser parser) fin = do
|
||||
pforest <- toParseTree fin
|
||||
text <- ByteString.readFile fin
|
||||
let
|
||||
res
|
||||
= runIdentity
|
||||
$ runExceptT
|
||||
$ flip runStateT pforest
|
||||
$ flip runReaderT (ParserEnv (pfRange pforest) text)
|
||||
$ runWriterT
|
||||
$ parser
|
||||
|
||||
either (error . show) (return . fst) res
|
||||
|
||||
token :: Text -> Parser Text
|
||||
token node = do
|
||||
tree@ParseTree {ptName, ptRange} <- takeNext node
|
||||
if ptName == node
|
||||
then do
|
||||
source <- asks peSource
|
||||
return (cutOut source tree)
|
||||
|
||||
else do
|
||||
throwError $ Expected node ptRange
|
||||
|
||||
anything :: Parser Text
|
||||
anything = do
|
||||
tree <- takeNext "anything"
|
||||
source <- asks peSource
|
||||
return (cutOut source tree)
|
||||
|
||||
consume :: Text -> Parser ()
|
||||
consume node = do
|
||||
ParseTree {ptName, ptRange} <- takeNext node
|
||||
when (ptName /= node) do
|
||||
tell [Expected node ptRange]
|
||||
|
||||
cutOut :: ByteString -> ParseTree -> Text
|
||||
cutOut bs (ParseTree _ _ s f _ _) =
|
||||
decodeUtf8 $ ByteString.take (f - s) (ByteString.drop s bs)
|
||||
|
||||
range :: Parser a -> Parser (a, Range)
|
||||
range parser =
|
||||
get >>= \case
|
||||
Forest {pfGrove = (,) _ ParseTree {ptRange} : _} -> do
|
||||
a <- parser
|
||||
return (a, ptRange)
|
||||
|
||||
Forest {pfRange} -> do
|
||||
a <- parser
|
||||
return (a, pfRange)
|
||||
|
||||
getRange :: Parser Range
|
||||
getRange = snd <$> range (return ())
|
||||
|
||||
delete :: Eq k => k -> [(k, v)] -> [(k, v)]
|
||||
delete _ [] = []
|
||||
delete k ((k', v) : rest) =
|
||||
if k == k'
|
||||
then rest
|
||||
else (k', v) : delete k rest
|
||||
|
||||
class Stubbed a where
|
||||
stub :: Error -> a
|
||||
|
||||
instance Stubbed [a] where
|
||||
stub _ = []
|
||||
|
||||
instance Stubbed Text where
|
||||
stub e = pack ("<" <> show e <> ">")
|
132
tools/lsp/squirrel/src/example.txt
Normal file
132
tools/lsp/squirrel/src/example.txt
Normal file
@ -0,0 +1,132 @@
|
||||
('contract' [1:1 - 4:1]
|
||||
('declaration' [1:1 - 3:25]
|
||||
('fun_decl' [1:1 - 3:25]
|
||||
('open_fun_decl' [1:1 - 3:25]
|
||||
('function' [1:1 - 1:9])
|
||||
('fun_name' [1:10 - 1:14]
|
||||
('ident' [1:10 - 1:14] ('Name' [1:10 - 1:14])))
|
||||
('parameters' [1:15 - 1:35]
|
||||
('(' [1:15 - 1:16])
|
||||
('param_decl' [1:16 - 1:34]
|
||||
('access' [1:16 - 1:21] ('const' [1:16 - 1:21]))
|
||||
('var' [1:22 - 1:23]
|
||||
('ident' [1:22 - 1:23] ('Name' [1:22 - 1:23])))
|
||||
(':' [1:24 - 1:25])
|
||||
('param_type' [1:26 - 1:34]
|
||||
('fun_type' [1:26 - 1:34]
|
||||
('cartesian' [1:26 - 1:34]
|
||||
('core_type' [1:26 - 1:34]
|
||||
('type_name' [1:26 - 1:34]
|
||||
('ident' [1:26 - 1:34] ('Name' [1:26 - 1:34]))))))))
|
||||
(')' [1:34 - 1:35]))
|
||||
(':' [1:36 - 1:37])
|
||||
('type_expr' [1:38 - 1:45]
|
||||
('fun_type' [1:38 - 1:45]
|
||||
('cartesian' [1:38 - 1:45]
|
||||
('core_type' [1:38 - 1:45]
|
||||
('type_name' [1:38 - 1:45]
|
||||
('ident' [1:38 - 1:45] ('Name' [1:38 - 1:45])))))))
|
||||
('is' [1:46 - 1:48])
|
||||
('block' [1:49 - 3:2]
|
||||
('block' [1:49 - 1:54])
|
||||
('{' [1:55 - 1:56])
|
||||
('statement' [2:3 - 2:57]
|
||||
('open_data_decl' [2:3 - 2:57]
|
||||
('open_const_decl' [2:3 - 2:57]
|
||||
('const' [2:3 - 2:8])
|
||||
('var' [2:9 - 2:10] ('ident' [2:9 - 2:10] ('Name' [2:9 - 2:10])))
|
||||
(':' [2:11 - 2:12])
|
||||
('type_expr' [2:13 - 2:28]
|
||||
('fun_type' [2:13 - 2:28]
|
||||
('cartesian' [2:13 - 2:28]
|
||||
('core_type' [2:13 - 2:28]
|
||||
('type_name' [2:13 - 2:21]
|
||||
('ident' [2:13 - 2:21] ('Name' [2:13 - 2:21])))
|
||||
('type_tuple' [2:22 - 2:28]
|
||||
('(' [2:22 - 2:23])
|
||||
('type_expr' [2:23 - 2:27]
|
||||
('fun_type' [2:23 - 2:27]
|
||||
('cartesian' [2:23 - 2:27]
|
||||
('core_type' [2:23 - 2:27]
|
||||
('type_name' [2:23 - 2:27]
|
||||
('ident' [2:23 - 2:27]
|
||||
('Name' [2:23 - 2:27])))))))
|
||||
(')' [2:27 - 2:28]))))))
|
||||
('=' [2:29 - 2:30])
|
||||
('expr' [2:31 - 2:57]
|
||||
('disj_expr' [2:31 - 2:57]
|
||||
('conj_expr' [2:31 - 2:57]
|
||||
('set_membership' [2:31 - 2:57]
|
||||
('comp_expr' [2:31 - 2:57]
|
||||
('cat_expr' [2:31 - 2:57]
|
||||
('cons_expr' [2:31 - 2:57]
|
||||
('add_expr' [2:31 - 2:57]
|
||||
('mult_expr' [2:31 - 2:57]
|
||||
('unary_expr' [2:31 - 2:57]
|
||||
('core_expr' [2:31 - 2:57]
|
||||
('fun_call_or_par_or_projection' [2:31 - 2:57]
|
||||
('fun_call' [2:31 - 2:57]
|
||||
('module_field' [2:31 - 2:53]
|
||||
('module_name' [2:31 - 2:36]
|
||||
('Name_Capital' [2:31 - 2:36]))
|
||||
('.' [2:36 - 2:37])
|
||||
('module_fun' [2:37 - 2:53]
|
||||
('field_name' [2:37 - 2:53]
|
||||
('ident' [2:37 - 2:53]
|
||||
('Name' [2:37 - 2:53])))))
|
||||
('arguments' [2:54 - 2:57]
|
||||
('(' [2:54 - 2:55])
|
||||
('expr' [2:55 - 2:56]
|
||||
('disj_expr' [2:55 - 2:56]
|
||||
('conj_expr' [2:55 - 2:56]
|
||||
('set_membership' [2:55 - 2:56]
|
||||
('comp_expr' [2:55 - 2:56]
|
||||
('cat_expr' [2:55 - 2:56]
|
||||
('cons_expr' [2:55 - 2:56]
|
||||
('add_expr' [2:55 - 2:56]
|
||||
('mult_expr' [2:55 - 2:56]
|
||||
('unary_expr' [2:55 - 2:56]
|
||||
('core_expr' [2:55 - 2:56]
|
||||
('ident' [2:55 - 2:56]
|
||||
('Name' [2:55 - 2:56])))))))))))))
|
||||
(')' [2:56 - 2:57]))))))))))))))))))
|
||||
(';' [2:57 - 2:58])
|
||||
('}' [3:1 - 3:2]))
|
||||
('with' [3:3 - 3:7])
|
||||
('expr' [3:8 - 3:25]
|
||||
('disj_expr' [3:8 - 3:25]
|
||||
('conj_expr' [3:8 - 3:25]
|
||||
('set_membership' [3:8 - 3:25]
|
||||
('comp_expr' [3:8 - 3:25]
|
||||
('cat_expr' [3:8 - 3:25]
|
||||
('cons_expr' [3:8 - 3:25]
|
||||
('add_expr' [3:8 - 3:25]
|
||||
('mult_expr' [3:8 - 3:25]
|
||||
('unary_expr' [3:8 - 3:25]
|
||||
('core_expr' [3:8 - 3:25]
|
||||
('fun_call_or_par_or_projection' [3:8 - 3:25]
|
||||
('fun_call' [3:8 - 3:25]
|
||||
('module_field' [3:8 - 3:21]
|
||||
('module_name' [3:8 - 3:13]
|
||||
('Name_Capital' [3:8 - 3:13]))
|
||||
('.' [3:13 - 3:14])
|
||||
('module_fun' [3:14 - 3:21]
|
||||
('field_name' [3:14 - 3:21]
|
||||
('ident' [3:14 - 3:21]
|
||||
('Name' [3:14 - 3:21])))))
|
||||
('arguments' [3:22 - 3:25]
|
||||
('(' [3:22 - 3:23])
|
||||
('expr' [3:23 - 3:24]
|
||||
('disj_expr' [3:23 - 3:24]
|
||||
('conj_expr' [3:23 - 3:24]
|
||||
('set_membership' [3:23 - 3:24]
|
||||
('comp_expr' [3:23 - 3:24]
|
||||
('cat_expr' [3:23 - 3:24]
|
||||
('cons_expr' [3:23 - 3:24]
|
||||
('add_expr' [3:23 - 3:24]
|
||||
('mult_expr' [3:23 - 3:24]
|
||||
('unary_expr' [3:23 - 3:24]
|
||||
('core_expr' [3:23 - 3:24]
|
||||
('ident' [3:23 - 3:24]
|
||||
('Name' [3:23 - 3:24])))))))))))))
|
||||
(')' [3:24 - 3:25])))))))))))))))))))
|
70
tools/lsp/squirrel/stack.yaml
Normal file
70
tools/lsp/squirrel/stack.yaml
Normal file
@ -0,0 +1,70 @@
|
||||
# This file was automatically generated by 'stack init'
|
||||
#
|
||||
# Some commonly used options have been documented as comments in this file.
|
||||
# For advanced use and comprehensive documentation of the format, please see:
|
||||
# https://docs.haskellstack.org/en/stable/yaml_configuration/
|
||||
|
||||
# Resolver to choose a 'specific' stackage snapshot or a compiler version.
|
||||
# A snapshot resolver dictates the compiler version and the set of packages
|
||||
# to be used for project dependencies. For example:
|
||||
#
|
||||
# resolver: lts-3.5
|
||||
# resolver: nightly-2015-09-21
|
||||
# resolver: ghc-7.10.2
|
||||
#
|
||||
# The location of a snapshot can be provided as a file or url. Stack assumes
|
||||
# a snapshot provided as a file might change, whereas a url resource does not.
|
||||
#
|
||||
# resolver: ./custom-snapshot.yaml
|
||||
# resolver: https://example.com/snapshots/2018-01-01.yaml
|
||||
resolver: lts-15.7
|
||||
|
||||
# User packages to be built.
|
||||
# Various formats can be used as shown in the example below.
|
||||
#
|
||||
# packages:
|
||||
# - some-directory
|
||||
# - https://example.com/foo/bar/baz-0.0.2.tar.gz
|
||||
# subdirs:
|
||||
# - auto-update
|
||||
# - wai
|
||||
packages:
|
||||
- .
|
||||
# Dependency packages to be pulled from upstream that are not in the resolver.
|
||||
# These entries can reference officially published versions as well as
|
||||
# forks / in-progress versions pinned to a git hash. For example:
|
||||
#
|
||||
extra-deps:
|
||||
- tree-sitter-0.9.0.0@sha256:4fd054b0a9651df9335c5fa0ffed723924dc4dcf7f2521c031323088ca719b05,3411
|
||||
- semantic-source-0.0.2.0@sha256:eac962ed1150d8647e703bc78369ecc4c1912db018e111f4ead8a62ae1a85542,2368
|
||||
- lingo-0.3.2.0@sha256:80b9ded65f2ddc0272a2872d9c3fc43c37934accae076d3e547dfc6c6b6e16d3,1899
|
||||
- semilattices-0.0.0.4@sha256:333707e460923711d1edbdd02ebe1c3957d4e0808eab9886747b52ee3e443639,1909
|
||||
# - acme-missiles-0.3
|
||||
# - git: https://github.com/commercialhaskell/stack.git
|
||||
# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a
|
||||
#
|
||||
# extra-deps: []
|
||||
|
||||
# Override default flag values for local packages and extra-deps
|
||||
# flags: {}
|
||||
|
||||
# Extra package databases containing global packages
|
||||
# extra-package-dbs: []
|
||||
|
||||
# Control whether we use the GHC we find on the path
|
||||
# system-ghc: true
|
||||
#
|
||||
# Require a specific version of stack, using version ranges
|
||||
# require-stack-version: -any # Default
|
||||
# require-stack-version: ">=2.1"
|
||||
#
|
||||
# Override the architecture used by stack, especially useful on Windows
|
||||
# arch: i386
|
||||
# arch: x86_64
|
||||
#
|
||||
# Extra directories used by stack for building
|
||||
# extra-include-dirs: [/path/to/dir]
|
||||
# extra-lib-dirs: [/path/to/dir]
|
||||
#
|
||||
# Allow a newer minor version of GHC than the snapshot specifies
|
||||
# compiler-check: newer-minor
|
40
tools/lsp/squirrel/stack.yaml.lock
Normal file
40
tools/lsp/squirrel/stack.yaml.lock
Normal file
@ -0,0 +1,40 @@
|
||||
# This file was autogenerated by Stack.
|
||||
# You should not edit this file by hand.
|
||||
# For more information, please see the documentation at:
|
||||
# https://docs.haskellstack.org/en/stable/lock_files
|
||||
|
||||
packages:
|
||||
- completed:
|
||||
hackage: tree-sitter-0.9.0.0@sha256:4fd054b0a9651df9335c5fa0ffed723924dc4dcf7f2521c031323088ca719b05,3411
|
||||
pantry-tree:
|
||||
size: 3765
|
||||
sha256: 6d8711529e12512dadb78eb9ea6854edea9a6e4d87e205d5213df221baf733ad
|
||||
original:
|
||||
hackage: tree-sitter-0.9.0.0@sha256:4fd054b0a9651df9335c5fa0ffed723924dc4dcf7f2521c031323088ca719b05,3411
|
||||
- completed:
|
||||
hackage: semantic-source-0.0.2.0@sha256:eac962ed1150d8647e703bc78369ecc4c1912db018e111f4ead8a62ae1a85542,2368
|
||||
pantry-tree:
|
||||
size: 727
|
||||
sha256: f3483c0b1495201bf4067091bfcb6c234d4cdb2068a8fd2edde4b94b3272975d
|
||||
original:
|
||||
hackage: semantic-source-0.0.2.0@sha256:eac962ed1150d8647e703bc78369ecc4c1912db018e111f4ead8a62ae1a85542,2368
|
||||
- completed:
|
||||
hackage: lingo-0.3.2.0@sha256:80b9ded65f2ddc0272a2872d9c3fc43c37934accae076d3e547dfc6c6b6e16d3,1899
|
||||
pantry-tree:
|
||||
size: 422
|
||||
sha256: c76e9e74eaa576e33c6f02eb8e26b19cc5fe35c514cce888d851184f91e1c156
|
||||
original:
|
||||
hackage: lingo-0.3.2.0@sha256:80b9ded65f2ddc0272a2872d9c3fc43c37934accae076d3e547dfc6c6b6e16d3,1899
|
||||
- completed:
|
||||
hackage: semilattices-0.0.0.4@sha256:333707e460923711d1edbdd02ebe1c3957d4e0808eab9886747b52ee3e443639,1909
|
||||
pantry-tree:
|
||||
size: 801
|
||||
sha256: f3b6dd7ac1fa1b7a259334ff342405263da053af5c115bd86499227e2373d8ec
|
||||
original:
|
||||
hackage: semilattices-0.0.0.4@sha256:333707e460923711d1edbdd02ebe1c3957d4e0808eab9886747b52ee3e443639,1909
|
||||
snapshots:
|
||||
- completed:
|
||||
size: 491389
|
||||
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/15/7.yaml
|
||||
sha256: 92ab6303fe20ec928461c82ce0980b4d17c06f4e66205a2967e476474f686c17
|
||||
original: lts-15.7
|
1
tools/lsp/squirrel/vendor/parser.c
vendored
Symbolic link
1
tools/lsp/squirrel/vendor/parser.c
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../../pascaligo/src/parser.c
|
Loading…
Reference in New Issue
Block a user