Skip to content

Instantly share code, notes, and snippets.

@Munksgaard
Created February 11, 2022 09:26
Show Gist options
  • Save Munksgaard/409a9168de705154d82a7f62208907fc to your computer and use it in GitHub Desktop.
Save Munksgaard/409a9168de705154d82a7f62208907fc to your computer and use it in GitHub Desktop.
futhark tree-sitter grammar
module.exports = grammar({
name: 'futhark',
rules: {
source_file: $ => repeat($.dec),
identifier: $ => /_?[A-Za-z][A-Za-z0-9_\']*/,
_quals: $ => repeat1(
seq($.identifier, '.')
),
qualid: $ => choice(
$.identifier,
seq($._quals, $.identifier)
),
binop: $ => seq(
$.opstartchar,
repeat($.opchar)
),
qualbinop: $ => choice(
$.binop,
seq($._quals, $.binop),
seq('`', $.qualid, '`')
),
fieldid: $ => choice(
$._decimal,
$.identifier
),
opstartchar: $ => choice(
'+',
'-',
'*',
'/',
'%',
'=',
'!',
'>',
'>',
'|',
'&',
'^'
),
opchar: $ => choice(
$.opstartchar,
'.'
),
constructor: $ => seq(
'#',
$.identifier
),
literal: $ => choice(
$.intnumber,
$.floatnumber,
'true',
'false'
),
int_type: $ => choice(
'i8',
'i16',
'i32',
'i64',
'u8',
'u16',
'u32',
'u64'
),
float_type: $ => choice(
'f16',
'f32',
'f64'
),
intnumber: $ => seq(
choice($._decimal,
$._hexadecimal,
$._binary),
optional($.int_type)
),
_decimal: $ => /[0-9][0-9_]*/,
_hexadecimal: $ => /0[xX][0-9a-fA-F][0-9a-fA-F_]*/,
_binary: $ => /0[bB][01][01_]*/,
floatnumber: $ => seq(
choice($._pointfloat, $._exponentfloat, $._hexadecimalfloat),
optional($.float_type)
),
_pointfloat: $ => seq(
optional($._decimal),
$._fraction
),
_exponentfloat: $ => seq(
choice($._decimal, $._pointfloat),
$._exponent
),
_hexadecimalfloat: $ => seq(
/0[xX]/,
$._hexintpart,
$._hexfraction,
/[pP][\+\-]?[0-9]+/
),
_fraction: $ => /\.[0-9][0-9_]*/,
_hexintpart: $ => /[0-9a-fA-F][0-9a-fA-F_]*/,
_hexfraction: $ => /.[0-9a-fA-F][0-9a-fA-F_]*/,
_exponent: $ => /[eE][\+\-]?[0-9]+/,
type: $ => choice(
$.qualid,
$.array_type,
$.tuple_type,
$.record_type,
$.sum_type,
// $.function_type,
// $.type_application,
// $.existential_size
),
tuple_type: $ => choice(
seq('(', ')'),
seq('(', $.type, repeat1(seq(',', $.type)), ')')
),
array_type: $ => seq(
'[',
optional($.dim),
']',
$.type
),
dim: $ => choice(
$.qualid,
$._decimal
),
sum_type: $ => prec.left(seq(
$.constructor,
repeat($.type),
repeat(seq('|',
$.constructor,
repeat($.type)))
)),
record_type: $ => choice(
seq('{', '}'),
seq('{',
$.fieldid,
':',
$.type,
repeat(seq(',',
$.fieldid,
':',
$.type)),
'}')
),
type_application: $ => prec.left(3, choice(
seq($.type, $.type_arg),
seq('*', $.type)
)),
type_arg: $ => choice(
seq('[', optional($.dim), ']'),
$.type
),
function_type: $ => seq(
$.param_type,
'->',
$.type
),
param_type: $ => prec(2, choice(
$.type,
seq('(', $.identifier, ':', $.type, ')')
)),
stringlit: $ => token(
seq('"', repeat(choice(/[^"\\\n]/, seq("\\", /([^\n]|[0-9]+)/))), '"')
),
charlit: $ => token(
seq('\'', repeat(choice(/[^'\\\n]/, seq("\\", /([^\n]|[0-9]+)/))), '\'')
),
existential_size: $ => seq(
'?',
repeat1(seq('[', $.identifier, ']')),
'.',
$.type
),
dec: $ => choice(
// $.val_bind,
$.type_bind,
// $.mod_bind,
// $.mod_type_bind,
// seq('open', $.mod_exp),
// seq('import', $.stringlit),
// seq('local', $.dec),
// seq('#[', $.attr, ']', $.dec),
),
val_bind: $ => choice(
seq(choice('def', 'entry', 'let'),
choice($.identifier, seq('(', $.binop, ')')),
repeat($.type_param),
repeat1($.pat),
optional(seq(':', $.type)),
'=',
$.exp),
seq(choice('def', 'entry', 'let'),
$.pat,
$.binop,
$.pat,
optional(seq(':', $.type)),
'=',
$.exp)
),
type_bind: $ => seq(
'type',
optional(choice('^', '~')),
$.identifier,
repeat($.type_param),
'=',
$.type
),
type_param: $ => choice(
seq('[', $.identifier, ']'),
seq('\'', $.identifier),
seq('\'~', $.identifier),
seq('\'^', $.identifier)
),
atom: $ => choice(
$.literal,
seq($.qualid, repeat(seq('.', $.fieldid))),
$.stringlit,
$.charlit,
seq('(', ')'),
seq('(', $.exp, ')', repeat(seq('.', $.fieldid))),
seq('(', $.exp, repeat(seq(',', $.exp)), ')'),
seq('{', '}'),
seq('{', $.field, repeat(seq(',', $.field)), '}'),
seq($.qualid, '[', $.index, repeat(seq(',', $.index)), ']'),
seq('(', $.exp, ')', '[', $.index, repeat(seq(',', $.index)), ']'),
seq($._quals, '.', '(', $.exp, ')'),
seq('[', $.exp, repeat(seq(',', $.exp)), ']'),
seq('[', $.exp, optional(seq('..', $.exp)), '...', $.exp, ']'),
seq('(', $.qualbinop, ')'),
seq('(', $.exp, $.qualbinop, ')'),
seq('(', $.qualbinop, $.exp, ')'),
seq('(', repeat1(seq('.', $.field)), ')'),
seq('(', '.', '[', $.index, repeat(seq(',', $.index)), ']', ')'),
),
exp: $ => choice(
$.atom,
seq($.exp, $.qualbinop, $.exp),
seq($.exp, $.exp),
seq('!', $.exp),
seq('-', $.exp),
seq($.constructor, repeat($.exp)),
seq($.exp, ':', $.type),
seq($.exp, ':>', $.type),
seq($.exp, optional(seq('..', $.exp)), '...', $.exp),
seq($.exp, optional(seq('..', $.exp)), '..<', $.exp),
seq($.exp, optional(seq('..', $.exp)), '..>', $.exp),
seq('if', $.exp, 'then', $.exp, 'else', $.exp),
seq('let', repeat($.size), $.pat, '=', $.exp, 'in', $.exp),
seq('let', $.identifier, '[', $.index, repeat(seq(',', $.index)), ']', '=', $.exp, 'in', $.exp),
seq('let', $.identifier, repeat($.type_param), repeat1($.pat), optional(seq(':', $.type)), '=', $.exp, 'in', $.exp),
seq('(', '\\', repeat1($.pat), optional(seq('=', $.exp)), $.loopform, 'do', $.exp),
seq('#[', $.attr, ']', $.exp),
seq('unsafe', $.exp),
seq('assert', $.atom, $.atom),
seq($.exp, 'with', '[', $.index, repeat(seq(',', $.index)), ']', '=', $.exp),
seq($.exp, 'with', $.fieldid, repeat(seq('.', $.fieldid)), '=', $.exp),
seq('match', $.exp, repeat1(seq('case', $.pat, '->', $.exp))),
),
index: $ => $.literal,
loopform: $ => seq(
'for',
$.identifier,
'<',
$.exp,
),
field: $ => choice(
seq($.fieldid, '=', $.exp),
$.identifier
),
size: $ => seq(
'[', $.identifier, ']'
),
pat: $ => choice(
$.identifier,
$.pat_literal,
'_',
seq('(', ')'),
seq('(', $.pat, ')'),
seq('(', $.pat, repeat1(seq(',', $.pat)), ')'),
seq('{', '}'),
seq('{', $.fieldid, optional(seq('=', $.pat)), repeat(seq(',', $.fieldid, optional(seq('=', $.pat)))), '}'),
seq($.constructor, repeat($.pat)),
seq($.pat, ':', $.type),
seq('#[', $.attr, ']', $.pat),
),
pat_literal: $ => seq(
optional('-'),
$.intnumber,
),
mod_bind: $ => seq(
'module',
$.identifier,
repeat($.mod_param),
'=',
optional(seq(':', $.mod_type_exp)),
'=',
$.mod_exp,
),
mod_param: $ => seq(
'(',
$.identifier,
':',
$.mod_type_exp,
')',
),
mod_type_bind: $ => seq(
'module',
'type',
$.identifier,
'=',
$.mod_type_exp,
),
mod_exp: $ => choice(
$.qualid,
seq($.mod_exp, ':', $.mod_type_exp),
seq('\\', '(', $.identifier, ':', $.mod_type_exp, ')', optional(seq(':', $.mod_type_exp)), '->', $.mod_exp),
seq($.mod_exp, $.mod_exp),
seq('(', $.mod_exp, ')'),
seq('{', repeat($.dec), '}'),
seq('import', $.stringlit),
),
mod_type_exp: $ => choice(
$.qualid,
seq('{', repeat($.spec), '}'),
seq($.mod_type_exp, 'with', $.qualid, repeat($.type_param), '=', $.type),
seq('(', $.mod_type_exp, ')'),
seq('(', $.identifier, ':', $.mod_type_exp, ')', '->', $.mod_type_exp),
seq($.mod_type_exp, '->', $.mod_type_exp),
),
spec: $ => choice(
seq('val', $.identifier, repeat($.type_param), ':', $.spec_type),
seq('val', $.binop, repeat($.type_param), ':', $.spec_type),
seq('type', optional('^'), $.identifier, repeat($.type_param), '=', $.type),
seq('type', optional('^'), $.identifier, repeat($.type_param)),
seq('module', $.identifier, ':', $.mod_type_exp),
seq('include', $.mod_type_exp),
seq('#[', $.attr, ']', $.spec),
),
spec_type: $ => choice(
$.type,
seq($.type, '->', $.spec_type),
),
attr: $ => choice(
$.identifier,
$._decimal,
seq($.identifier, '(', optional(seq($.attr, repeat(seq(',', $.attr)))), ')'),
),
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment