Skip to content

Commit

Permalink
(treesitter) Add CHR, Effect Handler syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
Memorytaco committed Oct 23, 2024
1 parent 7399069 commit fc02cb5
Show file tree
Hide file tree
Showing 11 changed files with 272,217 additions and 115,308 deletions.
154 changes: 108 additions & 46 deletions utils/tree-sitter-yolang/grammar.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

module.exports = grammar({
name: "yolang",
extras: $ => [/\s|\\\r?\n/, $.comment],
// extras: $ => [/\s|\\\r?\n/, $.comment],
extras: $ => [/\s/, $.comment],
rules: {
source_file: $ => seq($.module, repeat($._top)),

Expand All @@ -14,12 +15,12 @@ module.exports = grammar({
),

// module declaration and its exporting list
module: $ => statement("module", optional($.module_attr), $.module_path, optional(choice(
module: $ => statement("module", optional($.attribute), $.namespace, optional(choice(
// inside parenthesis
wrapsep("(", ")", ",", choice(
$.qualified_id,
$.id,
$.module_export,
$.export,
seq("*", optional(seq("exclude", wrapsep("(", ")", ",", choice(
$.operator_id,
$.force_id,
Expand All @@ -32,29 +33,30 @@ module.exports = grammar({
$.operator_id,
)))))
))),
module_attr: $ => $.string,
module_annotation: _$ => /[A-Za-z_]\w*:/,
module_path: _$ => token(sep1("/", /[A-Za-z_]\w*/)),
module_export: $ => seq("module", choice(
seq($.module_id, optional(choice(
export: $ => seq("module", choice(
seq($.absolute_id, optional(choice(
wrap("(", ")", sep(",", $.identifier)),
seq("*", optional(seq("exclude", wrap("(", ")", sep(",", $.identifier)))))
))),
wrap("(", ")", sep(",", $.module_id)),
seq("*", optional(seq("exclude", wrap("(", ")", sep(",", $.module_id)))))
wrap("(", ")", sep(",", $.absolute_id)),
seq("*", optional(seq("exclude", wrap("(", ")", sep(",", $.absolute_id)))))
)),
module_id: _$ => /#[A-Za-z_]\w*(#[A-Za-z_]\w*)*/,

// use statement
use: $ => statement("use", optional($.module_attr), optional($.module_annotation), $.use_piece),
use_piece: $ => seq(
alias($.module_path, $.use_path),
use: $ => statement("use", optional($.attribute), optional($.module_annotation), $.piece),
piece: $ => seq(
$.namespace,
optional(choice(
seq(alias("as", $.use_keyword_as), $.id),
seq(alias("alias", $.use_keyword_alias), $.id),
alias("self", $.use_keyword_self))),
optional(choice(
wrap("{", "}", sep(",", choice($.use_piece, $.operator_id, $.force_id))),
wrap("{", "}", sep(",", choice($.piece, $.operator_id, $.force_id))),
wrap("(", ")", choice(
sep(",", choice($.id, $.operator_id, $.force_id)),
".."
)),
seq(
alias("*", $.use_keyword_star),
optional(seq(alias("exclude", $.use_keyword_exclude), wrapsep("(", ")", ",", choice(
Expand All @@ -74,10 +76,12 @@ module.exports = grammar({
$.let_binding,
$.fixity,
$.effect,
$.binding,
$.constraint
),

// type declaration
data: $ => statement("data", alias($.id, $.type_constructor), repeat(alias($.id, $.type_param)), optional(choice(
data: $ => statement("data", repeat($.type_annotation_var), alias($.id, $.type_constructor), repeat(alias($.id, $.type_param)), optional(choice(
seq("=",
optional(seq(
alias($.id, $.newtype_evidence),
Expand All @@ -86,23 +90,27 @@ module.exports = grammar({
)),
$.type
),
repeat1(seq("|", alias($.id, $.data_constructor), repeat(choice($.id, $.type_unit, $.type_tuple)))),
wrap("{", "}", sep1(",", seq($.id, ":", $.type)))
repeat1(seq("|", repeat($.type_annotation_var), alias($.id, $.data_constructor), choice(
seq(":", $.type),
repeat(choice($.id, $.unit, wrap("(", ")", $.type), $.tuple_type))
))),
wrap("{", "}", sep1(",", seq(repeat($.type_annotation_var), $.id, ":", $.type)))
))),

// type expression
type: $ => prec.left(1, seq(
choice(
seq("forall", repeat1(choice(
wrapsep("{", "}", ",", $.type_annotation_var),
alias($.id, $.type_var_id),
// TODO: refine semantic of ":", after it should be kind expression instead of type
wrap("(", ")", seq(alias($.id, $.type_var_id), choice("=", "~", ":"), $.type))
)),".", $.type),
alias(choice("->", "=>"), $.type_reserved_operator),
$.operator,
$.type_var,
$.type_unit,
$.type_tuple,
$.unit,
$.tuple_type,
wrap("(", ")", $.type),
$.handler_type,
$.record_type,
Expand All @@ -111,18 +119,18 @@ module.exports = grammar({
repeat(choice($.type, $.type_effect_suffix)),
)),

handler_type: $ => wrap("{", "}", seq(sep1(",", seq(optional(".."), $.type)), ";;", $.type)),
handler_type: $ => wrap("{", "}", seq(sep1(",", seq(optional(".."), $.type)), ";;", $.type, optional(seq(",", $.type)))),
record_type: $ => wrapsep("{", "}", ",", seq(alias($.identifier, $.record_field), "=", $.type)),
tuple_type: $ => tuple($.type),

// type effect suffix
type_effect_suffix: $ => choice(
alias(seq("!", token.immediate(/'?[A-Za-z_]\w*/)), $.type_eff_name),
wrapsep("!{", "}", ",", choice($.type, seq("..", choice($.identifier, $.type_implicit_var))))
),
type_unit: _$ => /\(\s*\)/,
type_tuple: $ => wrap("(", ")", sep1(",", $.type)),
type_var: $ => choice(alias($.id, $.type_var_id), $.type_implicit_var),
type_var: $ => choice(alias($.id, $.type_var_id), $.type_implicit_var, $.type_annotation_var),
type_implicit_var: _$ => /'[A-Za-z_]\w*/,
type_annotation_var: _$ => /%[A-Za-z_]\w*/,

primitive_type: $ => choice(
alias($.primitive_reverse_atom, $.primitive_reverse_atom_prim),
Expand All @@ -145,16 +153,43 @@ module.exports = grammar({
)))
)),

constraint: $ => statement("rule", sep1(",", seq(alias(choice($.id, $.force_id, $.operator_id), $.rulename), repeat("_"))),
wrap("{", "}", repeat(choice(
seq(alias($.id, $.property), optional(seq("forall", repeat1($.id))), wrap("@", ".", seq(
sep1(",", $.chr),
optional(seq("\\", sep1(",", $.chr))),
repeat1(seq(optional(seq("|", $.chr)), choice("<=>", "==>"), sep1(",", $.chr)))
))),
$.fixity
)))) ,

// operator fixity declaration
fixity: $ => statement("fixity", /\d+/,
choice(seq("_", repeat1($.operator)), seq(repeat1($.operator), "_")),
repeat(choice("infix", "postfix", "prefix"))
chr: $ => seq(
choice($.identifier, $.operator, $.force_operator_id, $.number, wrap("(", ")", $.chr)),
optional($.chr)
),

// pattern synomym
binding: $ => statement("bind", optional(wrap("{", "}", repeat(alias($.id, $.type_id)))),
alias($.id, $.cons),
repeat(choice(wrap("(", ")", seq($.id, ":", $.type)), $.id)),
optional(seq(":", $.type)),
"<-",
$.pattern
),

// operator fixity declaration
fixity: $ => {
const operators = repeat1(choice($.operator, $.force_operator_id))
return statement("fixity", /\d+/,
choice(seq("_", operators), seq(operators, "_")),
repeat(choice("infix", "postfix", "prefix"))
)
},

// let binding includes effect block, value definition and function definition
let_binding: $ => statement("let", choice($.id, $.force_id, $.operator_id), optional(seq(":", $.type)), choice(
seq("=", $.expression),
seq(wrapsep("|", "|", ",", $.or_pattern), $.expression),
repeat1(seq("|", sep1(",", $.or_pattern), "=", $.expression)),
seq("do", choice($.do_block, $.expression))
)),
Expand All @@ -164,29 +199,40 @@ module.exports = grammar({
choice(
$.macro_id, $.identifier, $.number,
$.string, $.string_cons, $.operator,
$.operator_id, $.force_operator_id,
$.handler,
seq("forall", repeat1($.id), ".", $.expression),
seq("let", sep1(",", seq($.or_pattern, "=", $.expression)), "in", $.expression),
seq(wrapsep1("|", "|", ",", $.or_pattern), $.expression),
seq(optional(seq("with", sep1(",", $.expression))), "do", choice($.do_block, $.expression)),
seq(optional(seq("with", sep1(",", choice("auto", $.expression)))), "do", choice($.do_block, $.expression)),
wrapsep1("[", "]", "|", seq(sep1(",", $.or_pattern), "=", $.expression)),
wrapsep("(", ")", ",", $.expression),
$.unit,
$.unlift_type,
wrapsep1("(", ")", ",", $.expression),
), optional(choice(seq(":", $.type), repeat1($.expression)))
)),

unit: _$ => token(seq("(", ")")),
unlift_type: $ => choice(
wrapsep("@(", ")", ",", $.type),
seq("@", alias(token.immediate(/'?[A-Za-z_]\w*/), $.unlift_var))
),

or_pattern: $ => seq($.pattern, optional(seq("or", $.expression))),

do_block: $ => wrapsep("{", "}", ";;", choice(
seq("let", $.or_pattern, "<-", $.expression),
seq("const", sep1(",", seq($.or_pattern, "=", $.expression))),
seq("bind", sep1(",", seq($.or_pattern, "=", $.expression))),
$.expression
)),

handler: $ => prec(1, seq("handler", choice(
seq(sep1(",", alias($.id, $.method)), alias($.id, $.handler_resume), "=", $.expression),
seq("with", wrapsep("{", "}", ",", $.expression)),
seq("auto", "with", wrapsep("{", "}", ",", $.type)),
seq(sep1(",", alias($.id, $.method)), alias($.id, $.handler_resume), "=", wrapsep("|", "|", ",", $.or_pattern), $.expression),
seq(optional(seq("forall", repeat(choice($.id, $.force_id)))), wrapsep1("|", "|", ",", $.type), wrapsep("{", "}", ",",
seq(alias($.id, $.method), alias($.id, $.handler_resume), choice(
seq(alias($.id, $.method), choice(alias($.id, $.handler_resume), wrap("(", ")", seq(alias($.id, $.handler_resume), ":", $.type))), choice(
seq("=", $.expression),
seq(wrapsep("|", "|", ",", $.or_pattern), $.expression),
repeat1(seq("|", sep1(",", $.or_pattern), "=", $.expression)))
)))
))),
Expand All @@ -196,26 +242,29 @@ module.exports = grammar({
choice(
seq(choice(alias("_", $.pattern_wildcard), $.pattern_var), optional(seq(
token.immediate("@"),
choice($.pattern_unit, wrapsep("(", ")", ",", $.pattern))
choice($.unit, wrapsep("(", ")", ",", $.pattern))
))),
$.pattern_cons,
$.pattern_unit,
$.unit,
$.string_cons,
$.string,
$.number,
seq("!", $.expression, "->", $.pattern),
// seq("!", $.expression, "->", $.pattern),
wrapsep1("(", ")", ",", $.pattern)
), optional(choice(seq(":", $.type), repeat1($.pattern)))
),
optional(choice(seq(":", $.type), repeat1($.pattern))),
optional(seq("<-", $.expression))
)),
pattern_var: _$ => seq("?", token.immediate(/[A-Za-z_]\w*/)),
pattern_cons: $ => prec(1, $.id),
pattern_unit: _$ => /\(\s*\)/,

pattern_cons: $ => prec(1, $.identifier),

// effect
effect: $ => statement("effect", choice(
seq(optional(seq(repeat($.id), ".")), sep1(",", alias($.id, $.method)), ":", $.type),
seq(repeat1($.id), wrapsep("{", "}", ",", seq(alias($.id, $.method), ":", $.type)))
seq(optional(seq("forall", repeat1($.id), ".")), sep1(",", alias($.id, $.method)), ":", sep1(",", $.type)),
seq("auto", sep1(",", seq($.id, repeat(choice($.id, $.type_annotation_var))))),
seq($.id, repeat(choice($.id, $.type_annotation_var)), wrapsep("{", "}", ";;",
seq(optional(seq("forall", repeat1($.id), ".")), alias($.id, $.method), ":", sep1(",", $.type)))
)
)),

// definition of terminal symbol
Expand All @@ -234,7 +283,7 @@ module.exports = grammar({
alias(token.immediate(prec(1, /[^\\"\n]+/)), $.string_content),
$._escape_sequence,
))),
_escape_sequence: _ => token(prec(1, seq(
_escape_sequence: _$ => token(prec(1, seq(
'\\',
choice(
/[^xuU]/,
Expand All @@ -244,21 +293,34 @@ module.exports = grammar({
/U[0-9a-fA-F]{8}/,
),
))),

string_cons: $ => seq($.string, alias(token.immediate(/\.[A-Za-z_]\w*/), $.string_cons_var)),
attribute: $ => $.string,

absolute_id: _$ => /#[A-Za-z_]\w*(#[A-Za-z_]\w*)*/,
namespace: _$ => token(sep1("/", /[A-Za-z_]\w*/)),

// operator
operator: _$ => /[+\-*/\\!@#$%^&=|?.><;:]+/,
operator_id: _$ => /\([+:;\-*/\\!@#$%^&=|?.><]+\)/,
operator: _$ => /[+\-*/\\!~@#$%^&=|?.><;:]+/,
operator_id: _$ => /\([+:;\-*/\\!~@#$%^&=|?.><]+\)/,
force_operator_id: _$ => /#\([+:;\-*/\\!~@#$%^&=|?.><]+\)/,
macro_id: _$ => /#[A-Za-z_]\w*(#[A-Za-z_]\w*)*!/,

id: _$ => /[A-Za-z_]\w*/,
// #prefix#name or #prefix#name#(++) simple operator
qualified_id: _$ => /#[A-Za-z_]\w*(#[A-Za-z_]\w*)*(#\([+:\-*/\\!@#$%^&=|?.><]+\))?/,
qualified_id: _$ => /#[A-Za-z_]\w*(#[A-Za-z_]\w*)*(#\([+:;\-*/\\!~@#$%^&=|?.><]+\))?/,
force_id: _$ => /##[A-Za-z_]\w*/,
identifier: $ => choice($.force_id, $.qualified_id, $.id)
}
})

/**
* @param {RuleOrLiteral} rule
*/
function tuple(rule) {
return wrap("(", ")", seq(rule, repeat1(seq(",", rule))))
}

/**
* @param {RuleOrLiteral} delimiter
* @param {RuleOrLiteral} rule
Expand Down
2 changes: 1 addition & 1 deletion utils/tree-sitter-yolang/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"license": "MIT",
"devDependencies": {
"prebuildify": "^6.0.0",
"tree-sitter-cli": "^0.22.6"
"tree-sitter-cli": "^0.24.3"
},
"dependencies": {
"node-addon-api": "^7.1.0",
Expand Down
Loading

0 comments on commit fc02cb5

Please sign in to comment.