108 lines
2.2 KiB
JavaScript
108 lines
2.2 KiB
JavaScript
/**
|
|
* @file SCL grammar for tree-sitter
|
|
* @author Jacob Signorovitch <jacob.signorovitch@gmail.com>
|
|
* @license MIT
|
|
*/
|
|
|
|
/// <reference types="tree-sitter-cli/dsl" />
|
|
// @ts-check
|
|
|
|
module.exports = grammar({
|
|
name: "scl",
|
|
|
|
conflicts: ($) => [[$.params, $._exp]],
|
|
|
|
rules: {
|
|
source_file: ($) => repeat($._exp),
|
|
|
|
_exp: ($) =>
|
|
choice(
|
|
$.num,
|
|
$.bool,
|
|
$.word,
|
|
$.binexp,
|
|
$.callexp,
|
|
$.parexp,
|
|
$.block,
|
|
$.vardef,
|
|
$.lambda,
|
|
$.funcdef,
|
|
$.ifexp,
|
|
),
|
|
|
|
num: (_) => /\d+/,
|
|
bool: (_) => choice("TRUE", "T", "FALSE", "F"),
|
|
word: (_) => /[a-zA-Z_]\w*/,
|
|
|
|
binexp: ($) =>
|
|
prec.left(
|
|
1,
|
|
seq(
|
|
field("left", $._exp),
|
|
field("op", choice("+", "-", "*", "/", "eq")),
|
|
field("right", $._exp),
|
|
),
|
|
),
|
|
|
|
callexp: ($) =>
|
|
prec.left(
|
|
1, // lower than funcdef
|
|
seq(field("fn", $.word), "(", optional(commaSep($._exp)), ")"),
|
|
),
|
|
|
|
parexp: ($) => seq("(", $._exp, ")"),
|
|
block: ($) => seq("{", repeat($._exp), "}"),
|
|
|
|
vardef: ($) =>
|
|
prec.right(1, seq(field("name", $.word), "=", field("value", $._exp))),
|
|
|
|
lambda: ($) =>
|
|
prec.right(
|
|
2,
|
|
seq("\\", field("params", $.params), field("body", $._exp)),
|
|
),
|
|
|
|
funcdef: ($) =>
|
|
prec.right(
|
|
3, // higher precedence than call
|
|
seq(
|
|
field("name", $.word),
|
|
field("params", $.params),
|
|
field("body", $._exp),
|
|
),
|
|
),
|
|
|
|
params: ($) => seq("(", optional(commaSep($.word)), ")"),
|
|
|
|
ifexp: ($) =>
|
|
choice(
|
|
seq(
|
|
"_if",
|
|
"(",
|
|
field("cond", $._exp),
|
|
",",
|
|
field("then", $._exp),
|
|
",",
|
|
field("else", $._exp),
|
|
")",
|
|
),
|
|
seq(
|
|
"if",
|
|
field("cond", $._exp),
|
|
field("then", $._exp),
|
|
choice(seq("else", field("else", $._exp)), field("else", $._exp)),
|
|
),
|
|
seq(
|
|
"?",
|
|
field("cond", $._exp),
|
|
field("then", $._exp),
|
|
field("else", $._exp),
|
|
),
|
|
),
|
|
},
|
|
});
|
|
|
|
function commaSep(rule) {
|
|
return seq(rule, repeat(seq(",", rule)));
|
|
}
|