feat: add 'reserved word' construct

Co-authored-by: Amaan Qureshi <amaanq12@gmail.com>
This commit is contained in:
Max Brunsfeld 2024-12-23 00:06:32 -08:00 committed by GitHub
parent 2a63077cac
commit 201b41cf11
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 2367 additions and 1628 deletions

View file

@ -16,6 +16,7 @@ function alias(rule, value) {
result.value = value.symbol.name;
return result;
case Object:
case GrammarSymbol:
if (typeof value.type === 'string' && value.type === 'SYMBOL') {
result.named = true;
result.value = value.name;
@ -153,11 +154,26 @@ function seq(...elements) {
};
}
function sym(name) {
class GrammarSymbol {
constructor(name) {
this.type = "SYMBOL";
this.name = name;
}
}
function reserved(wordset, rule) {
if (typeof wordset !== 'string') {
throw new Error('Invalid reserved word set name: ' + wordset)
}
return {
type: "SYMBOL",
name
};
type: "RESERVED",
content: normalize(rule),
context_name: wordset,
}
}
function sym(name) {
return new GrammarSymbol(name);
}
function token(value) {
@ -236,6 +252,7 @@ function grammar(baseGrammar, options) {
inline: [],
supertypes: [],
precedences: [],
reserved: {},
};
} else {
baseGrammar = baseGrammar.grammar;
@ -309,6 +326,28 @@ function grammar(baseGrammar, options) {
}
}
let reserved = baseGrammar.reserved;
if (options.reserved) {
if (typeof options.reserved !== "object") {
throw new Error("Grammar's 'reserved' property must be an object.");
}
for (const reservedWordSetName of Object.keys(options.reserved)) {
const reservedWordSetFn = options.reserved[reservedWordSetName]
if (typeof reservedWordSetFn !== "function") {
throw new Error(`Grammar reserved word sets must all be functions. '${reservedWordSetName}' is not.`);
}
const reservedTokens = reservedWordSetFn.call(ruleBuilder, ruleBuilder, baseGrammar.reserved[reservedWordSetName]);
if (!Array.isArray(reservedTokens)) {
throw new Error(`Grammar's reserved word set functions must all return arrays of rules. '${reservedWordSetName}' does not.`);
}
reserved[reservedWordSetName] = reservedTokens.map(normalize);
}
}
let extras = baseGrammar.extras.slice();
if (options.extras) {
if (typeof options.extras !== "function") {
@ -439,6 +478,7 @@ function grammar(baseGrammar, options) {
externals,
inline,
supertypes,
reserved,
},
};
}
@ -478,6 +518,7 @@ globalThis.optional = optional;
globalThis.prec = prec;
globalThis.repeat = repeat;
globalThis.repeat1 = repeat1;
global.reserved = reserved;
globalThis.seq = seq;
globalThis.sym = sym;
globalThis.token = token;