about summary refs log tree commit diff
diff options
context:
space:
mode:
authorWilliam Carroll <wpcarro@gmail.com>2023-01-20T23·28-0800
committerclbot <clbot@tvl.fyi>2023-01-20T23·33+0000
commit6945601ef3c064d4a3bc6a921452fff56d45f055 (patch)
tree01691f68a21ab7644462fc896dbbf64a96e2b5fa
parent7442558b33b3f1ebcf356924b0345cb73d0524ab (diff)
feat(wpcarro/slx): Support grouping r/5716
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>
-rw-r--r--users/wpcarro/slx.js/index.js34
1 files changed, 26 insertions, 8 deletions
diff --git a/users/wpcarro/slx.js/index.js b/users/wpcarro/slx.js/index.js
index 8f6eff3c43..d255bb99f9 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)}`;
 }