112 lines
2.8 KiB
JavaScript
112 lines
2.8 KiB
JavaScript
// Minimal Tree-sitter grammar for Ferro syntax highlighting in Zed.
|
|
// `parser.c` is normative; this file is the editor-copy.
|
|
|
|
module.exports = grammar({
|
|
name: "ferro",
|
|
|
|
extras: $ => [
|
|
/[\s\uFEFF\u2060\u200B]/,
|
|
],
|
|
|
|
rules: {
|
|
source_file: $ => repeat(choice(
|
|
$.unit_decl,
|
|
$.import_decl,
|
|
$.line_comment,
|
|
$.block_comment,
|
|
$.string_literal,
|
|
$.char_literal,
|
|
$.integer_literal,
|
|
$.builtin,
|
|
$.builtin_type,
|
|
$.keyword,
|
|
$.identifier,
|
|
$.operator,
|
|
$.punctuation,
|
|
)),
|
|
|
|
line_comment: _ => token(seq("//", /[^\n]*/)),
|
|
|
|
unit_decl: $ => seq("unit", $.dotted_identifier, ";"),
|
|
|
|
import_decl: $ => seq("import", $.dotted_identifier,
|
|
optional(seq("as", $.identifier)), ";"),
|
|
|
|
// Ferro block comments may nest. Keeping this rule recursive makes syntax
|
|
// highlighting follow the compiler lexer instead of flattening nested /* */.
|
|
block_comment: $ => seq(
|
|
"/*",
|
|
repeat(choice(
|
|
$.block_comment,
|
|
/[^*/]+/,
|
|
/\*[^/]/,
|
|
/\/[^*]/,
|
|
)),
|
|
"*/",
|
|
),
|
|
|
|
string_literal: _ => token(seq(
|
|
'"',
|
|
repeat(choice(
|
|
/[^"\\\n\r]/,
|
|
/\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|[nrt\\'"0])/,
|
|
)),
|
|
'"',
|
|
)),
|
|
|
|
char_literal: _ => token(seq(
|
|
"'",
|
|
choice(
|
|
/[^'\\\n\r]/,
|
|
/\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|[nrt\\'"0])/,
|
|
),
|
|
"'",
|
|
)),
|
|
|
|
integer_literal: _ => token(prec(2, choice(
|
|
/0[xX][0-9A-Fa-f_]+/,
|
|
/0[bB][01_]+/,
|
|
/0[oO][0-7_]+/,
|
|
/[0-9][0-9_]*/,
|
|
))),
|
|
|
|
builtin: _ => token(prec(3, /@[A-Za-z_][A-Za-z0-9_]*/)),
|
|
|
|
builtin_type: _ => token(prec(3, choice(
|
|
"i8", "i16", "i32",
|
|
"u8", "u16", "u32",
|
|
"usize", "isize",
|
|
"bool", "char", "void", "str",
|
|
))),
|
|
|
|
keyword: _ => token(prec(3, choice(
|
|
"unit", "import", "pub", "fn", "struct", "packed", "enum", "error",
|
|
"const", "static", "var", "let", "mut",
|
|
"if", "else", "while", "for", "in", "match",
|
|
"return", "break", "continue", "defer",
|
|
"unsafe", "critical", "shared", "atomic", "comptime", "asm",
|
|
"try", "catch", "orelse", "as", "extern",
|
|
"interrupt", "interrupt_safe", "far",
|
|
"true", "false", "null", "undefined",
|
|
"self", "Self", "type",
|
|
"and", "or", "not",
|
|
))),
|
|
|
|
identifier: _ => /[A-Za-z_][A-Za-z0-9_]*/,
|
|
|
|
operator: _ => token(choice(
|
|
"<<=", ">>=",
|
|
"+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=",
|
|
"==", "!=", "<=", ">=", "<<", ">>", "->", "=>", "..",
|
|
"+%", "-%", "*%",
|
|
"+", "-", "*", "/", "%", "=", "<", ">", "&", "|", "^", "!", "?",
|
|
)),
|
|
|
|
dotted_identifier: _ => /[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_]*)*/,
|
|
|
|
punctuation: _ => token(choice(
|
|
"(", ")", "{", "}", "[", "]", ",", ";", ":", ".",
|
|
)),
|
|
},
|
|
});
|