mirror of https://github.com/Wilfred/difftastic/
123 lines
2.8 KiB
JavaScript
123 lines
2.8 KiB
JavaScript
const foreign = ($, kw, pent) => seq(
|
|
'foreign',
|
|
kw,
|
|
$._foreign_pre,
|
|
optional(pent),
|
|
$.signature,
|
|
)
|
|
|
|
module.exports = {
|
|
// ------------------------------------------------------------------------
|
|
// decl
|
|
// ------------------------------------------------------------------------
|
|
|
|
_funpat_infix: $ => seq(field('lhs', $._pat), field('op', $.varop), field('rhs', $._pat)),
|
|
|
|
_funpat: $ => seq(
|
|
field('pattern', $._typed_pat),
|
|
$._funrhs,
|
|
),
|
|
|
|
/**
|
|
* The `implicit_parid` here is for:
|
|
* g = let ?par = Impy 5 in f
|
|
*/
|
|
_fun_name: $ => field('name', choice($._var, $.implicit_parid)),
|
|
|
|
guard_equation: $ => seq($.guards, '=', $._exp),
|
|
|
|
_fun_guards: $ => repeat1($.guard_equation),
|
|
|
|
_funrhs: $ => seq(
|
|
choice(
|
|
seq('=', field('rhs', $._exp)),
|
|
$._fun_guards,
|
|
),
|
|
optional(seq($.where, optional($.decls))),
|
|
),
|
|
|
|
_fun_patterns: $ => repeat1($._apat),
|
|
|
|
_funvar: $ => seq($._fun_name, field('patterns', optional(alias($._fun_patterns, $.patterns)))),
|
|
|
|
_funlhs: $ => choice(
|
|
prec.dynamic(2, $._funvar),
|
|
prec.dynamic(1, field('infix', alias($._funpat_infix, $.infix))),
|
|
),
|
|
|
|
function: $ => seq(
|
|
$._funlhs,
|
|
$._funrhs,
|
|
),
|
|
|
|
fixity: $ => seq(
|
|
choice('infixl', 'infixr', 'infix'),
|
|
optional($.integer),
|
|
sep1($.comma, $._op),
|
|
),
|
|
|
|
signature: $ => seq(
|
|
field('lhs', sep1($.comma, field('name', $._var))),
|
|
field('type', $._type_annotation),
|
|
),
|
|
|
|
_gendecl: $ => choice(
|
|
$.signature,
|
|
$.fixity,
|
|
),
|
|
|
|
/**
|
|
* in the reference, `apat` is a choice in `lpat`, but this creates a conflict:
|
|
* `decl` allows the lhs to be a `pat`, as in:
|
|
* let Just 5 = prog
|
|
* let a = prog
|
|
* Since patterns can be `variable`s, the `funpat` lhs of the second example cannot be distinguished from a `funvar`.
|
|
* The precedences here and in `_funlhs` solve this.
|
|
*/
|
|
_decl_fun: $ => choice(
|
|
$.function,
|
|
prec.dynamic(1, alias($._funpat, $.function)),
|
|
),
|
|
|
|
_decl: $ => choice(
|
|
$._gendecl,
|
|
$._decl_fun,
|
|
),
|
|
|
|
decls: $ => layouted($, $._decl),
|
|
|
|
// ------------------------------------------------------------------------
|
|
// foreign
|
|
// ------------------------------------------------------------------------
|
|
|
|
calling_convention: _ => choice(
|
|
'ccall',
|
|
'stdcall',
|
|
'cplusplus',
|
|
'jvm',
|
|
'dotnet',
|
|
'prim',
|
|
'capi',
|
|
),
|
|
|
|
safety: _ => choice('unsafe', 'safe', 'interruptible'),
|
|
|
|
impent: $ => $.string,
|
|
|
|
expent: $ => $.string,
|
|
|
|
_foreign_pre: $ => seq(
|
|
$.calling_convention,
|
|
optional($.safety),
|
|
),
|
|
|
|
decl_foreign_import: $ => foreign($, 'import', $.impent),
|
|
|
|
decl_foreign_export: $ => foreign($, 'export', $.expent),
|
|
|
|
_decl_foreign: $ => choice(
|
|
alias($.decl_foreign_import, $.foreign_import),
|
|
alias($.decl_foreign_export, $.foreign_export)
|
|
),
|
|
}
|