From 6945601ef3c064d4a3bc6a921452fff56d45f055 Mon Sep 17 00:00:00 2001 From: William Carroll Date: Fri, 20 Jan 2023 15:28:55 -0800 Subject: 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 Autosubmit: wpcarro --- users/wpcarro/slx.js/index.js | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) (limited to 'users/wpcarro/slx.js') diff --git a/users/wpcarro/slx.js/index.js b/users/wpcarro/slx.js/index.js index 8f6eff3c43bd..d255bb99f92b 100644 --- a/users/wpcarro/slx.js/index.js +++ b/users/wpcarro/slx.js/index.js @@ -92,6 +92,9 @@ function compile(ast, config) { }; } } + if (ast.type === 'GROUPING') { + return compile(ast.content); + } if (ast.type === 'STRING') { return function(x) { 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) { return { i: 0, tokens }; } @@ -292,6 +302,12 @@ function conjunction(p, config) { const lhs = selection(p, config); 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) { return lhs; } @@ -305,7 +321,7 @@ function conjunction(p, config) { p.i += 1; } skipWhitespace(p); - let rhs = conjunction(p, config); + const rhs = conjunction(p, config); return { 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) { // column:value OR -column:value 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"); 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)}`; } -- cgit 1.4.1