1
0
dust/grammar.js

409 lines
6.7 KiB
JavaScript
Raw Normal View History

2023-11-30 00:23:42 +00:00
module.exports = grammar({
name: "dust",
word: $ => $.identifier,
extras: $ => [/\s/, $._comment],
rules: {
root: $ =>
prec(1, repeat1($.statement)),
_comment: $ => /[#][^#\n]*[#|\n]/,
block: $ =>
seq(
optional("async"),
"{",
repeat1($.statement),
"}",
),
statement: $ =>
prec.left(
seq(
choice(
$.assignment,
$.block,
$.expression,
$.for,
$.if_else,
$.index_assignment,
$.match,
$.return,
$.use,
$.while,
),
optional(";"),
),
),
expression: $ =>
prec.right(
choice(
$._expression_kind,
seq(
"(",
$._expression_kind,
")",
),
),
),
_expression_kind: $ =>
prec.right(
choice(
$.function_call,
$.identifier,
$.index,
$.logic,
$.math,
$.value,
$.yield,
),
),
_expression_list: $ =>
repeat1(
prec.right(
seq(
$.expression,
optional(","),
),
),
),
identifier: $ =>
/[_a-zA-Z]+[_a-zA-Z0-9]?/,
value: $ =>
choice(
$.integer,
$.float,
$.string,
$.boolean,
$.list,
$.function,
$.table,
$.map,
),
integer: $ =>
token(
prec.left(
seq(
optional("-"),
repeat1(
choice(
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"0",
),
),
),
),
),
float: $ =>
token(
prec.left(
seq(
optional("-"),
repeat1(
choice(
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"0",
),
),
".",
repeat1(
choice(
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"0",
),
),
),
),
),
string: $ =>
/("[^"]*?")|('[^']*?')|(`[^`]*?`)/,
boolean: $ =>
choice("true", "false"),
list: $ =>
seq(
"[",
repeat(
prec.left(
seq(
$.expression,
optional(","),
),
),
),
"]",
),
map: $ =>
seq(
"{",
repeat(
seq(
$.identifier,
"=",
$.statement,
optional(","),
),
),
"}",
),
index: $ =>
prec.left(
1,
seq(
$.expression,
":",
$.expression,
optional(
seq("..", $.expression),
),
),
),
math: $ =>
prec.left(
seq(
$.expression,
$.math_operator,
$.expression,
),
),
math_operator: $ =>
choice("+", "-", "*", "/", "%"),
logic: $ =>
prec.right(
seq(
$.expression,
$.logic_operator,
$.expression,
),
),
logic_operator: $ =>
choice(
"==",
"!=",
"&&",
"||",
">",
"<",
">=",
"<=",
),
assignment: $ =>
seq(
field(
"identifier",
$.identifier,
),
optional(
field(
"type",
$.type_definition,
),
),
field(
"assignment_operator",
$.assignment_operator,
),
field("statement", $.statement),
),
index_assignment: $ =>
seq(
$.index,
$.assignment_operator,
$.statement,
),
assignment_operator: $ =>
prec.right(
choice("=", "+=", "-="),
),
if_else: $ =>
prec.right(
seq(
$.if,
repeat($.else_if),
optional($.else),
),
),
if: $ =>
seq("if", $.expression, $.block),
else_if: $ =>
seq(
"else if",
$.expression,
$.block,
),
else: $ => seq("else", $.block),
match: $ =>
prec.right(
seq(
"match",
$.expression,
repeat1(
seq(
$.expression,
"=>",
$.block,
),
),
),
),
while: $ =>
seq(
"while",
$.expression,
$.block,
),
for: $ =>
seq(
choice("for", "async for"),
$.identifier,
"in",
$.expression,
$.block,
),
identifier_list: $ =>
prec.right(
choice(
seq(
"|",
repeat(
seq(
$.identifier,
optional(","),
),
),
"|",
),
),
),
table: $ =>
prec.right(
seq(
"table",
$.identifier_list,
$.expression,
),
),
return: $ =>
seq("return", $.expression),
use: $ => seq("use", $.string),
type_definition: $ =>
seq("<", $.type, ">"),
type: $ =>
prec.right(
choice(
"any",
"bool",
2023-11-30 03:54:46 +00:00
"float",
2023-11-30 00:23:42 +00:00
seq(
"fn",
repeat(
seq(
$.type,
optional(","),
),
),
optional(seq("->", $.type)),
),
"int",
seq("list", $.type),
"map",
"num",
"str",
),
),
function: $ =>
seq(
"|",
repeat(
seq(
$.identifier,
optional(","),
),
),
"|",
$.block,
),
function_call: $ =>
prec.right(
1,
seq(
"(",
$.expression,
optional($._expression_list),
")",
),
),
yield: $ =>
prec.left(
seq(
$.expression,
"->",
"(",
$.expression,
optional($._expression_list),
")",
),
),
},
});