tree-sitter-bp/grammar.js

223 lines
4.6 KiB
JavaScript
Raw Normal View History

function commaSeparatedOptTrailing(elem) {
2024-04-08 00:24:14 +02:00
return seq(elem, repeat(seq(",", elem)), optional(","))
}
function commaSeparatedNoTrailing(elem) {
return seq(elem, repeat(seq(",", elem)))
}
function commaSeparatedTrailing(elem) {
return repeat(seq(elem, ","))
}
2024-04-07 20:59:34 +02:00
module.exports = grammar({
name: "bp",
2024-04-07 20:59:34 +02:00
2024-04-07 22:37:52 +02:00
extras: ($) => [
/\s+/,
$.comment,
2024-04-07 22:37:52 +02:00
],
2024-04-07 20:59:34 +02:00
rules: {
2024-04-07 22:37:52 +02:00
source_file: ($) => repeat($._definition),
_definition: ($) => choice(
$.assignment,
2024-04-08 02:36:27 +02:00
$.module,
2024-04-07 22:37:52 +02:00
),
comment: (_) => choice(
seq("//", /(\\+(.|\r?\n)|[^\\\n])*/),
seq("/*", /[^*]*\*+([^/*][^*]*\*+)*/, "/"),
),
2024-04-08 09:48:10 +02:00
2024-04-07 22:37:52 +02:00
// Definitions {{{
assignment: ($) => seq(
field("left", $.identifier),
2024-04-08 03:13:43 +02:00
field("operator", alias(choice("=", "+="), $.operator)),
2024-04-07 22:37:52 +02:00
field("right", $._expr),
),
2024-04-08 02:36:27 +02:00
module: ($) => choice(
$._old_module,
$._new_module,
),
// This syntax is deprecated, but still accepted
_old_module: ($) => seq(
field("type", $.identifier),
"{",
optional(commaSeparatedOptTrailing(
alias(field("property", $._colon_property), $.property)
)),
2024-04-08 02:36:27 +02:00
"}",
),
_new_module: ($) => seq(
field("type", $.identifier),
2024-04-08 02:36:27 +02:00
"(",
optional(commaSeparatedOptTrailing(
alias(field("property", $._equal_property), $.property)
)),
2024-04-08 02:36:27 +02:00
")",
),
2024-04-07 22:37:52 +02:00
// }}}
// Expressions {{{
_expr: ($) => choice(
// Literals
$.identifier,
2024-04-08 00:39:47 +02:00
$.boolean_literal,
2024-04-07 22:37:52 +02:00
$.integer_literal,
$._string_literal,
// Conditionals
$.select_expression,
2024-04-08 00:24:14 +02:00
// Composites
$.list_expression,
2024-04-08 00:36:21 +02:00
$.map_expression,
2024-04-08 03:12:22 +02:00
// Operators
$.binary_expression,
2024-04-07 22:37:52 +02:00
),
// The Blueprint scanner makes use of Go's lexer, so copy their rule
identifier: (_) => /[_\p{XID_Start}][_\p{XID_Continue}]*/,
2024-04-08 00:39:47 +02:00
boolean_literal: (_) => choice("true", "false"),
2024-04-07 23:49:15 +02:00
integer_literal: (_) => seq(optional("-"), /[0-9]+/),
2024-04-07 22:37:52 +02:00
// The Blueprint scanner makes use of Go's lexer, so copy their rule
_string_literal: ($) => choice(
$.raw_string_literal,
$.interpreted_string_literal,
),
raw_string_literal: (_) => token(seq(
"`",
/[^`]+/,
"`",
)),
interpreted_string_literal: $ => seq(
'"',
repeat(choice(
// Allow all characters without special meaning, disallow newlines
/[^"\n\\]+/,
$.escape_sequence,
)),
token.immediate('"'),
),
escape_sequence: (_) => token.immediate(seq(
'\\',
choice(
/[^xuU]/,
/\d{2,3}/,
/x[0-9a-fA-F]{2,}/,
/u[0-9a-fA-F]{4}/,
/U[0-9a-fA-F]{8}/,
),
)),
select_expression: ($) => seq(
"select",
"(",
$.select_value,
",",
$.select_cases,
")",
),
2024-04-23 17:43:10 +02:00
select_value: ($) => choice(
2024-04-23 17:47:30 +02:00
$.condition,
seq("(", commaSeparatedOptTrailing($.condition), ")"),
2024-04-23 17:43:10 +02:00
),
2024-04-23 17:47:30 +02:00
condition: ($) => seq(
2024-04-23 16:56:10 +02:00
field("name", $.identifier),
2024-04-08 02:25:09 +02:00
"(",
field("arguments", optional(commaSeparatedNoTrailing($._string_literal))),
2024-04-08 02:25:09 +02:00
")",
),
select_cases: ($) => seq(
"{",
optional(commaSeparatedOptTrailing($.select_case)),
"}",
),
select_case: ($) => seq(
2024-04-23 17:43:10 +02:00
field("pattern", $.select_pattern),
":",
field("value", $._case_value)
),
2024-04-23 17:43:10 +02:00
select_pattern: ($) => choice(
$._select_pattern,
seq("(", commaSeparatedOptTrailing($._select_pattern), ")"),
),
_select_pattern: ($) => choice(
$._string_literal,
$.boolean_literal,
2024-07-01 15:46:22 +02:00
alias("any", $.any),
2024-07-01 15:53:48 +02:00
$.pattern_binding,
2024-04-23 17:43:10 +02:00
alias("default", $.default),
),
2024-07-01 15:53:48 +02:00
pattern_binding: ($) => seq(
field("value", alias("any", $.any)),
field("operator", alias("@", $.operator)),
field("binding", $.identifier),
),
_case_value: ($) => choice(
alias("unset", $.unset),
$._expr,
),
2024-04-08 00:24:14 +02:00
list_expression: ($) => seq(
"[",
optional(commaSeparatedOptTrailing(field("element", $._expr))),
2024-04-08 00:24:14 +02:00
"]",
),
2024-04-08 00:36:21 +02:00
map_expression: ($) => seq(
"{",
optional(commaSeparatedOptTrailing(
alias(field("property", $._colon_property), $.property)
)),
2024-04-08 00:36:21 +02:00
"}",
),
2024-04-08 03:12:22 +02:00
binary_expression: ($) => prec.left(seq(
field("left", $._expr),
2024-04-08 03:13:43 +02:00
field("operator", alias("+", $.operator)),
2024-04-08 03:12:22 +02:00
field("right", $._expr),
)),
2024-04-08 00:36:21 +02:00
// }}}
// Properties {{{
_colon_property: ($) => seq(
field("field", $.identifier),
":",
field("value", $._expr),
),
2024-04-08 02:36:27 +02:00
_equal_property: ($) => seq(
field("field", $.identifier),
"=",
field("value", $._expr),
),
2024-04-07 22:37:52 +02:00
// }}}
2024-04-07 20:59:34 +02:00
}
});
// vim: foldmethod=marker sw=2