Browse Source

Parse chained AND and OR

master
Dylan Baker 4 years ago
parent
commit
80f8bb450a
2 changed files with 46 additions and 6 deletions
  1. 8
    6
      src/parser.ts
  2. 38
    0
      test/parser.test.ts

+ 8
- 6
src/parser.ts View File

@@ -96,18 +96,19 @@ export default class Parser {
96 96
   }
97 97
 
98 98
   private or(): AST.Expr | Error {
99
-    const left = this.and();
99
+    let left = this.and();
100 100
     if (isError(left)) {
101 101
       return left;
102 102
     }
103 103
 
104
-    if (this.match(TokenKind.OR)) {
104
+    while (this.match(TokenKind.OR)) {
105 105
       this.eat(TokenKind.OR);
106 106
       const right = this.and();
107 107
       if (isError(right)) {
108 108
         return right;
109 109
       }
110
-      return new AST.Binary({
110
+
111
+      left = new AST.Binary({
111 112
         left,
112 113
         right,
113 114
         type: AST.BinaryExpressionTypes.OR,
@@ -118,18 +119,19 @@ export default class Parser {
118 119
   }
119 120
 
120 121
   private and(): AST.Expr | Error {
121
-    const left = this.equality();
122
+    let left = this.equality();
122 123
     if (isError(left)) {
123 124
       return left;
124 125
     }
125 126
 
126
-    if (this.match(TokenKind.AND)) {
127
+    while (this.match(TokenKind.AND)) {
127 128
       this.eat(TokenKind.AND);
128 129
       const right = this.equality();
129 130
       if (isError(right)) {
130 131
         return right;
131 132
       }
132
-      return new AST.Binary({
133
+
134
+      left = new AST.Binary({
133 135
         left,
134 136
         right,
135 137
         type: AST.BinaryExpressionTypes.AND,

+ 38
- 0
test/parser.test.ts View File

@@ -222,4 +222,42 @@ describe("Parser", () => {
222 222
       }),
223 223
     ]);
224 224
   });
225
+
226
+  it("should parse chained ANDs", () => {
227
+    const tree = parse("select a from b where c and d and e");
228
+    expect(tree).to.deep.equal([
229
+      new AST.SelectStatement({
230
+        arguments: [new AST.Identifier("a")],
231
+        from: new AST.Identifier("b"),
232
+        where: new AST.Binary({
233
+          left: new AST.Binary({
234
+            left: new AST.Identifier("c"),
235
+            right: new AST.Identifier("d"),
236
+            type: AST.BinaryExpressionTypes.AND,
237
+          }),
238
+          right: new AST.Identifier("e"),
239
+          type: AST.BinaryExpressionTypes.AND,
240
+        }),
241
+      }),
242
+    ]);
243
+  });
244
+
245
+  it("should parse chained ORs", () => {
246
+    const tree = parse("select a from b where c or d or e");
247
+    expect(tree).to.deep.equal([
248
+      new AST.SelectStatement({
249
+        arguments: [new AST.Identifier("a")],
250
+        from: new AST.Identifier("b"),
251
+        where: new AST.Binary({
252
+          left: new AST.Binary({
253
+            left: new AST.Identifier("c"),
254
+            right: new AST.Identifier("d"),
255
+            type: AST.BinaryExpressionTypes.OR,
256
+          }),
257
+          right: new AST.Identifier("e"),
258
+          type: AST.BinaryExpressionTypes.OR,
259
+        }),
260
+      }),
261
+    ]);
262
+  });
225 263
 });

Loading…
Cancel
Save