Files

78 lines
2.0 KiB
JavaScript

module.exports = grammar({
name: "ebnf",
// Extras are tokens that can appear anywhere (like whitespace and comments)
extras: ($) => [/\s/, $.comment],
rules: {
// The entry point: a file is a repeating list of syntax rules
source_file: ($) => repeat($.syntax_rule),
// e.g., letter = "A" | "B" | "C" ;
syntax_rule: ($) =>
seq($.meta_identifier, "=", optional($.definitions_list), ";"),
// e.g., "A" | "B" | "C"
definitions_list: ($) =>
seq($.single_definition, repeat(seq("|", $.single_definition))),
// e.g., "A" , "B"
single_definition: ($) =>
seq($.syntactic_term, repeat(seq(",", $.syntactic_term))),
// e.g., factor - exception
syntactic_term: ($) =>
seq($.syntactic_factor, optional(seq("-", $.syntactic_factor))),
// e.g., 3 * "A"
syntactic_factor: ($) =>
seq(optional(seq($.integer, "*")), $.syntactic_primary),
syntactic_primary: ($) =>
choice(
$.optional_sequence,
$.repeated_sequence,
$.grouped_sequence,
$.meta_identifier,
$.terminal_string,
$.special_sequence,
$.empty_sequence,
),
// [ ... ] or (/ ... /)
optional_sequence: ($) =>
choice(
seq("[", $.definitions_list, "]"),
seq("(/", $.definitions_list, "/)"),
),
// { ... } or (: ... :)
repeated_sequence: ($) =>
choice(
seq("{", $.definitions_list, "}"),
seq("(:", $.definitions_list, ":)"),
),
// ( ... )
grouped_sequence: ($) => seq("(", $.definitions_list, ")"),
// ? ... ?
special_sequence: ($) => seq("?", /[^?]*/, "?"),
empty_sequence: ($) => "()",
// Identifiers (e.g., rule_name)
meta_identifier: ($) => /[a-zA-Z][a-zA-Z0-9_]*/,
// Strings (e.g., "hello" or 'world')
terminal_string: ($) =>
choice(seq("'", /[^']*/, "'"), seq('"', /[^"]*/, '"')),
// Numbers (used for repetition limits)
integer: ($) => /[0-9]+/,
// Comments (* ... *)
comment: ($) => seq("(*", /[^*]*\*+([^)*][^*]*\*+)*/, ")"),
},
});