Skip to content

Commit e029e4d

Browse files
so far so good
1 parent b40b276 commit e029e4d

File tree

5 files changed

+831534
-449682
lines changed

5 files changed

+831534
-449682
lines changed

crates/pgls_treesitter_grammar/grammar.js

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -913,7 +913,9 @@ module.exports = grammar({
913913

914914
select: ($) =>
915915
seq(
916-
$.keyword_select,
916+
completableKeyword($, "select", {
917+
minLength: 3,
918+
}),
917919
seq(optional($.keyword_distinct), $.select_expression)
918920
),
919921

@@ -1086,7 +1088,10 @@ module.exports = grammar({
10861088
),
10871089

10881090
reset_statement: ($) =>
1089-
seq($.keyword_reset, choice($.keyword_all, $.any_identifier)),
1091+
seq(
1092+
completableKeyword($, "reset", { minLength: 3 }),
1093+
choice($.keyword_all, $.any_identifier)
1094+
),
10901095

10911096
_transaction_mode: ($) =>
10921097
seq(
@@ -2994,7 +2999,7 @@ module.exports = grammar({
29942999
revoke_statement: ($) =>
29953000
prec.left(
29963001
seq(
2997-
$.keyword_revoke,
3002+
completableKeyword($, "revoke", { minLength: 3 }),
29983003
optional(
29993004
choice(
30003005
seq($.keyword_grant, $.keyword_option, $.keyword_for),
@@ -3616,3 +3621,47 @@ function partialSeq(...rules) {
36163621

36173622
return prec.left(finishedRule);
36183623
}
3624+
3625+
/**
3626+
*
3627+
* @typedef {Object} CompletableKeywordOpts
3628+
* @property {number} [minLength]
3629+
* @property {boolean} [unambiguous]
3630+
*/
3631+
3632+
/**
3633+
* @param {RuleRecord} $
3634+
* @param {string} keyword
3635+
* @param {CompletableKeywordOpts} [opts={}]
3636+
*/
3637+
function completableKeyword($, keyword, opts = {}) {
3638+
let matcher = "";
3639+
3640+
const minLength = opts.minLength ?? 1;
3641+
const unambiguous = opts.unambiguous ?? false;
3642+
3643+
for (let i = minLength; i < keyword.length; i++) {
3644+
if (matcher.length > 0) {
3645+
matcher += "|";
3646+
}
3647+
3648+
matcher += keyword.substring(0, i);
3649+
}
3650+
3651+
const reversedMatcher = matcher.split("|").toReversed().join("|");
3652+
const partialMatch = new RegExp(reversedMatcher, "ig");
3653+
3654+
const noMatchAlias = `partial_keyword:${keyword}`;
3655+
3656+
const options = [$[`keyword_${keyword}`], alias(partialMatch, noMatchAlias)];
3657+
3658+
if (unambiguous) {
3659+
options.push(alias(new RegExp("REPLACED_TOKEN", "i"), noMatchAlias));
3660+
3661+
options.push(
3662+
alias(new RegExp("REPLACED_TOKEN_WITH_QUOTE", "i"), noMatchAlias)
3663+
);
3664+
}
3665+
3666+
return choice(...options);
3667+
}

0 commit comments

Comments
 (0)