feat(wpcarro/slx): Support grouping
I'm considering rearchitecting the parser to align with the "Crafting Interpreters" wisdom. I don't really want to do that right now, and the current implementation fits my use-case. If I discover bugs or want to add more features, I'll revisit the issue. Change-Id: Ia767933519ea9fc0fe954cb142f21b02e13a1f40 Reviewed-on: https://cl.tvl.fyi/c/depot/+/7883 Tested-by: BuildkiteCI Reviewed-by: wpcarro <wpcarro@gmail.com> Autosubmit: wpcarro <wpcarro@gmail.com>
This commit is contained in:
parent
7442558b33
commit
6945601ef3
1 changed files with 26 additions and 8 deletions
|
|
@ -92,6 +92,9 @@ function compile(ast, config) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ast.type === 'GROUPING') {
|
||||||
|
return compile(ast.content);
|
||||||
|
}
|
||||||
if (ast.type === 'STRING') {
|
if (ast.type === 'STRING') {
|
||||||
return function(x) {
|
return function(x) {
|
||||||
if (config.caseSensitive) {
|
if (config.caseSensitive) {
|
||||||
|
|
@ -276,6 +279,13 @@ function skipWhitespace(p) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function peekType(n, p) {
|
||||||
|
if (p.i + n < p.tokens.length) {
|
||||||
|
return p.tokens[p.i + n][0];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
function parser(tokens) {
|
function parser(tokens) {
|
||||||
return { i: 0, tokens };
|
return { i: 0, tokens };
|
||||||
}
|
}
|
||||||
|
|
@ -292,6 +302,12 @@ function conjunction(p, config) {
|
||||||
const lhs = selection(p, config);
|
const lhs = selection(p, config);
|
||||||
skipWhitespace(p);
|
skipWhitespace(p);
|
||||||
|
|
||||||
|
// TODO(wpcarro): Consider re-architecting the parser to avoid smells like
|
||||||
|
// this.
|
||||||
|
if (peekType(0, p) === 'RPAREN') {
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
if (p.i >= p.tokens.length) {
|
if (p.i >= p.tokens.length) {
|
||||||
return lhs;
|
return lhs;
|
||||||
}
|
}
|
||||||
|
|
@ -305,7 +321,7 @@ function conjunction(p, config) {
|
||||||
p.i += 1;
|
p.i += 1;
|
||||||
}
|
}
|
||||||
skipWhitespace(p);
|
skipWhitespace(p);
|
||||||
let rhs = conjunction(p, config);
|
const rhs = conjunction(p, config);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'CONJUNCTION',
|
type: 'CONJUNCTION',
|
||||||
|
|
@ -315,13 +331,6 @@ function conjunction(p, config) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function peekType(n, p) {
|
|
||||||
if (p.i + n < p.tokens.length) {
|
|
||||||
return p.tokens[p.i + n][0];
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function selection(p, config) {
|
function selection(p, config) {
|
||||||
// column:value OR -column:value
|
// column:value OR -column:value
|
||||||
if ((peekType(0, p) === 'ATOM' && peekType(1, p) === 'COLON') ||
|
if ((peekType(0, p) === 'ATOM' && peekType(1, p) === 'COLON') ||
|
||||||
|
|
@ -401,6 +410,15 @@ function matchAll(p, config) {
|
||||||
const regex = config.caseSensitive ? new RegExp(val) : new RegExp(val, "i");
|
const regex = config.caseSensitive ? new RegExp(val) : new RegExp(val, "i");
|
||||||
return { type: 'MATCH_ALL', matchType: 'REGEX', val: regex };
|
return { type: 'MATCH_ALL', matchType: 'REGEX', val: regex };
|
||||||
}
|
}
|
||||||
|
if (type === 'LPAREN') {
|
||||||
|
p.i += 1;
|
||||||
|
const content = conjunction(p, config);
|
||||||
|
expect((type, _) => type === 'RPAREN', 'a closing parenthesis', p);
|
||||||
|
return {
|
||||||
|
type: 'GROUPING',
|
||||||
|
content,
|
||||||
|
};
|
||||||
|
}
|
||||||
throw `Parse Error: Expected a regular expression or a string, but got: ${p.tokens[p.i]}; ${JSON.stringify(p)}`;
|
throw `Parse Error: Expected a regular expression or a string, but got: ${p.tokens[p.i]}; ${JSON.stringify(p)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue