[logging] Fix string parser

The string parser wasn't correctly handling escaped quotes and backward
slashes.

Fixed: 112994

Change-Id: I73362977df351c1dd7191aa6fbf168943ed2719d
Reviewed-on: https://fuchsia-review.googlesource.com/c/vscode-plugins/+/746083
Reviewed-by: Amy Hu <amyhu@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/webviews/logging/parsing/filters.pegjs b/webviews/logging/parsing/filters.pegjs
index b8b9757..58f87be 100644
--- a/webviews/logging/parsing/filters.pegjs
+++ b/webviews/logging/parsing/filters.pegjs
@@ -289,10 +289,27 @@
   = [0-9]+ { return parseInt(text(), 10); }
 
 String
-  = [^"\\|\\(\\): ]+ { return text(); }
-  / '"' [^"]+ '"' {
-    let t = text();
-    return t.slice(1, t.length - 1);
+  = '"' chars:CharWithinQuotes* '"' {
+    return chars.join('');
+  }
+  /  chars:CharNotInQuotes+ { return chars.join(''); }
+
+CharWithinQuotes
+  = [^"\\]
+  / '\\"' { return '"'; }
+  / "\\\\" { return "\\"; }
+
+CharNotInQuotes
+  = [^"\\|\\(\\): ]
+  / "\\" char:(
+      '"'
+    / '\\'
+    / '('
+    / ')'
+    / ':'
+    / ' '
+  ) {
+    return char;
   }
 
 Not = "!" / "not"i
diff --git a/webviews/logging/test/parser.test.ts b/webviews/logging/test/parser.test.ts
index 96c5c46..9072ba0 100644
--- a/webviews/logging/test/parser.test.ts
+++ b/webviews/logging/test/parser.test.ts
@@ -407,6 +407,40 @@
       });
     });
 
+    it('handles escaped chars', () => {
+      parseFilter('foo"').ok.should.be.false;
+      parseFilter('foo\\"').should.deep.equal({
+        ok: true,
+        value: new FilterExpression([
+          [
+            new Filter({
+              category: 'any',
+              subCategory: undefined,
+              operator: 'contains',
+              values: ['foo"'],
+              not: false,
+            })
+          ]
+        ])
+      });
+
+      parseFilter('"foo""').ok.should.be.false;
+      parseFilter('"foo\\""').should.deep.equal({
+        ok: true,
+        value: new FilterExpression([
+          [
+            new Filter({
+              category: 'any',
+              subCategory: undefined,
+              operator: 'contains',
+              values: ['foo"'],
+              not: false,
+            })
+          ]
+        ])
+      });
+    });
+
     it('accepts multiple raw strings form a conjunction', () => {
       parseFilter('foo bar').should.deep.equal({
         ok: true,