|
@@ -34,7 +34,7 @@ export default class Parser {
|
34
|
34
|
return this.select();
|
35
|
35
|
}
|
36
|
36
|
|
37
|
|
- return new Error(`Unexpected token ${token.kind}`, token.line);
|
|
37
|
+ return new Error(`Unexpected token: ${token.repr()}`, token.line);
|
38
|
38
|
}
|
39
|
39
|
|
40
|
40
|
private select(): AST.Statement | Error {
|
|
@@ -61,11 +61,11 @@ export default class Parser {
|
61
|
61
|
});
|
62
|
62
|
}
|
63
|
63
|
|
64
|
|
- private args(): AST.Secondary[] | Error {
|
|
64
|
+ private args(): AST.Expr[] | Error {
|
65
|
65
|
const args = [];
|
66
|
66
|
|
67
|
67
|
while (true) {
|
68
|
|
- const arg = this.alias();
|
|
68
|
+ const arg = this.expr();
|
69
|
69
|
if (isError(arg)) {
|
70
|
70
|
return arg;
|
71
|
71
|
}
|
|
@@ -81,14 +81,57 @@ export default class Parser {
|
81
|
81
|
return args;
|
82
|
82
|
}
|
83
|
83
|
|
84
|
|
- private from(): AST.Secondary | Error {
|
|
84
|
+ private from(): AST.FromTarget | Error {
|
85
|
85
|
this.eat(TokenKind.FROM);
|
86
|
86
|
|
87
|
|
- if (this.match(TokenKind.BACKTICK)) {
|
88
|
|
- return this.alias(this.backtick);
|
|
87
|
+ return this.fromTarget();
|
|
88
|
+ }
|
|
89
|
+
|
|
90
|
+ private fromTarget(): AST.FromTarget | Error {
|
|
91
|
+ const token = this.currentToken();
|
|
92
|
+ switch (token.kind) {
|
|
93
|
+ case TokenKind.BACKTICK:
|
|
94
|
+ const backtick = this.backtick();
|
|
95
|
+ if (isError(backtick)) {
|
|
96
|
+ return backtick;
|
|
97
|
+ }
|
|
98
|
+
|
|
99
|
+ if (this.match(TokenKind.AS)) {
|
|
100
|
+ return this.fromTargetAlias(backtick);
|
|
101
|
+ }
|
|
102
|
+
|
|
103
|
+ return backtick;
|
|
104
|
+ case TokenKind.IDENTIFIER:
|
|
105
|
+ const identifier = this.identifier();
|
|
106
|
+ if (isError(identifier)) {
|
|
107
|
+ return identifier;
|
|
108
|
+ }
|
|
109
|
+
|
|
110
|
+ if (this.match(TokenKind.AS)) {
|
|
111
|
+ return this.fromTargetAlias(identifier);
|
|
112
|
+ }
|
|
113
|
+
|
|
114
|
+ return identifier;
|
89
|
115
|
}
|
90
|
116
|
|
91
|
|
- return this.alias(this.identifier);
|
|
117
|
+ return new Error(`Unexpected token: ${token.repr()}`, token.line);
|
|
118
|
+ }
|
|
119
|
+
|
|
120
|
+ private fromTargetAlias(obj: AST.Identifier | AST.Backtick): AST.Alias | Error {
|
|
121
|
+ this.eat(TokenKind.AS);
|
|
122
|
+
|
|
123
|
+ const token = this.currentToken();
|
|
124
|
+ const alias = this.match(TokenKind.BACKTICK)
|
|
125
|
+ ? this.backtick()
|
|
126
|
+ : this.match(TokenKind.IDENTIFIER)
|
|
127
|
+ ? this.identifier()
|
|
128
|
+ : new Error(`Unexpected token: ${token.repr()}`, token.line);
|
|
129
|
+
|
|
130
|
+ if (isError(alias)) {
|
|
131
|
+ return alias;
|
|
132
|
+ }
|
|
133
|
+
|
|
134
|
+ return new AST.Alias(obj, alias);
|
92
|
135
|
}
|
93
|
136
|
|
94
|
137
|
private where(): AST.Expr | Error {
|
|
@@ -214,7 +257,7 @@ export default class Parser {
|
214
|
257
|
|
215
|
258
|
if (this.match(TokenKind.STAR)) {
|
216
|
259
|
this.eat(TokenKind.STAR);
|
217
|
|
- const right = this.primary();
|
|
260
|
+ const right = this.alias();
|
218
|
261
|
if (isError(right)) {
|
219
|
262
|
return right;
|
220
|
263
|
}
|
|
@@ -228,7 +271,7 @@ export default class Parser {
|
228
|
271
|
|
229
|
272
|
if (this.match(TokenKind.SLASH)) {
|
230
|
273
|
this.eat(TokenKind.SLASH);
|
231
|
|
- const right = this.primary();
|
|
274
|
+ const right = this.alias();
|
232
|
275
|
if (isError(right)) {
|
233
|
276
|
return right;
|
234
|
277
|
}
|
|
@@ -243,8 +286,8 @@ export default class Parser {
|
243
|
286
|
return left;
|
244
|
287
|
}
|
245
|
288
|
|
246
|
|
- private alias(fn: () => AST.Primary | Error = this.primary): AST.Secondary | Error {
|
247
|
|
- const primary = fn.bind(this)();
|
|
289
|
+ private alias(): AST.Expr | Error {
|
|
290
|
+ const primary = this.primary();
|
248
|
291
|
if (isError(primary)) {
|
249
|
292
|
return primary;
|
250
|
293
|
}
|
|
@@ -264,21 +307,52 @@ export default class Parser {
|
264
|
307
|
return primary;
|
265
|
308
|
}
|
266
|
309
|
|
267
|
|
- private primary(): AST.Primary | Error {
|
|
310
|
+ private primary(): AST.Expr | Error {
|
268
|
311
|
const token = this.currentToken();
|
269
|
|
- switch (token.kind) {
|
270
|
|
- case TokenKind.NUMBER:
|
271
|
|
- return this.number();
|
272
|
|
- case TokenKind.IDENTIFIER:
|
273
|
|
- return this.identifier();
|
274
|
|
- case TokenKind.BACKTICK:
|
275
|
|
- return this.backtick();
|
|
312
|
+
|
|
313
|
+ const primary = (() => {
|
|
314
|
+ switch (token.kind) {
|
|
315
|
+ case TokenKind.NUMBER:
|
|
316
|
+ return this.number();
|
|
317
|
+ case TokenKind.IDENTIFIER:
|
|
318
|
+ return this.identifier();
|
|
319
|
+ case TokenKind.BACKTICK:
|
|
320
|
+ return this.backtick();
|
|
321
|
+ default:
|
|
322
|
+ return new Error(`Unexpected token: ${token.repr()}`, token.line);
|
|
323
|
+ }
|
|
324
|
+ })();
|
|
325
|
+
|
|
326
|
+ if (isError(primary)) {
|
|
327
|
+ return primary;
|
276
|
328
|
}
|
277
|
329
|
|
278
|
|
- return new Error(
|
279
|
|
- `Unexpected token ${token.kind} ${token.value}`,
|
280
|
|
- token.line,
|
281
|
|
- );
|
|
330
|
+ if (this.match(TokenKind.AS)) {
|
|
331
|
+ this.eat(TokenKind.AS);
|
|
332
|
+
|
|
333
|
+ const name = this.match(TokenKind.BACKTICK) ? this.backtick() : this.identifier();
|
|
334
|
+
|
|
335
|
+ if (isError(name)) {
|
|
336
|
+ return name;
|
|
337
|
+ }
|
|
338
|
+
|
|
339
|
+ return new AST.Alias(primary, name);
|
|
340
|
+ } else if (this.match(TokenKind.DOT)) {
|
|
341
|
+ this.eat(TokenKind.DOT);
|
|
342
|
+
|
|
343
|
+ const right = this.match(TokenKind.BACKTICK) ? this.backtick() : this.identifier();
|
|
344
|
+ if (isError(right)) {
|
|
345
|
+ return right;
|
|
346
|
+ }
|
|
347
|
+
|
|
348
|
+ return new AST.Binary({
|
|
349
|
+ left: primary,
|
|
350
|
+ right,
|
|
351
|
+ type: AST.BinaryExpressionTypes.DOT,
|
|
352
|
+ });
|
|
353
|
+ }
|
|
354
|
+
|
|
355
|
+ return primary;
|
282
|
356
|
}
|
283
|
357
|
|
284
|
358
|
private backtick(): AST.Backtick | Error {
|
|
@@ -319,9 +393,7 @@ export default class Parser {
|
319
|
393
|
return token;
|
320
|
394
|
}
|
321
|
395
|
|
322
|
|
- const repr = `{ kind: ${token.kind}${token.value ? `, value: ${token.value} }` : " }"}`;
|
323
|
|
-
|
324
|
|
- return new Error(`Unexpected token: ${repr}`, token.line);
|
|
396
|
+ return new Error(`Unexpected token: ${token.repr()}`, token.line);
|
325
|
397
|
}
|
326
|
398
|
|
327
|
399
|
private match(kind: TokenKind): boolean {
|