Browse Source

Parse identifiers

master
Dylan Baker 4 years ago
parent
commit
5dbee92f4d
5 changed files with 63 additions and 4 deletions
  1. 6
    0
      src/ast.ts
  2. 7
    0
      src/ast/identifier.ts
  3. 2
    2
      src/ast/statement.ts
  4. 22
    2
      src/parser.ts
  5. 26
    0
      test/parser.test.ts

+ 6
- 0
src/ast.ts View File

@@ -1,2 +1,8 @@
1
+import { Identifier } from "./ast/identifier";
2
+import { Number as _Number } from "./ast/number";
3
+
4
+export * from "./ast/identifier";
1 5
 export * from "./ast/number";
2 6
 export * from "./ast/statement";
7
+
8
+export type Primary = _Number | Identifier;

+ 7
- 0
src/ast/identifier.ts View File

@@ -0,0 +1,7 @@
1
+export class Identifier {
2
+  public value: string;
3
+
4
+  constructor(value: string) {
5
+    this.value = value;
6
+  }
7
+}

+ 2
- 2
src/ast/statement.ts View File

@@ -6,12 +6,12 @@ export enum StatementType {
6 6
 
7 7
 export interface IStatementOptions {
8 8
   type: StatementType;
9
-  arguments: AST.Number[];
9
+  arguments: AST.Primary[];
10 10
 }
11 11
 
12 12
 export class Statement {
13 13
   public type: StatementType;
14
-  public arguments: AST.Number[];
14
+  public arguments: AST.Primary[];
15 15
 
16 16
   constructor(opts: IStatementOptions) {
17 17
     this.type = opts.type;

+ 22
- 2
src/parser.ts View File

@@ -49,11 +49,11 @@ export default class Parser {
49 49
     });
50 50
   }
51 51
 
52
-  private args(): AST.Number[] | Error {
52
+  private args(): AST.Primary[] | Error {
53 53
     const args = [];
54 54
 
55 55
     while (true) {
56
-      const arg = this.number();
56
+      const arg = this.primary();
57 57
       if (isError(arg)) {
58 58
         return arg;
59 59
       }
@@ -69,6 +69,26 @@ export default class Parser {
69 69
     return args;
70 70
   }
71 71
 
72
+  private primary(): AST.Primary | Error {
73
+    const token = this.currentToken();
74
+    switch (token.kind) {
75
+      case TokenKind.NUMBER:
76
+        return this.number();
77
+      case TokenKind.IDENTIFIER:
78
+        return this.identifier();
79
+    }
80
+
81
+    return new Error(`Unexpected token ${token.kind} ${token.value}`, token.line);
82
+  }
83
+
84
+  private identifier(): AST.Identifier | Error {
85
+    const identifier = this.eat(TokenKind.IDENTIFIER);
86
+    if (isError(identifier)) {
87
+      return identifier;
88
+    }
89
+    return new AST.Identifier(identifier.value || "");
90
+  }
91
+
72 92
   private number(): AST.Number | Error {
73 93
     const n = this.eat(TokenKind.NUMBER);
74 94
     if (isError(n)) {

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

@@ -42,4 +42,30 @@ describe("Parser", () => {
42 42
       }),
43 43
     ]);
44 44
   });
45
+
46
+  it("should parse a selection of identifiers", () => {
47
+    const tree = parse("select a, b");
48
+    expect(tree).to.deep.equal([
49
+      new AST.Statement({
50
+        arguments: [
51
+          new AST.Identifier("a"),
52
+          new AST.Identifier("b"),
53
+        ],
54
+        type: AST.StatementType.SELECT,
55
+      }),
56
+    ]);
57
+  });
58
+
59
+  it("should parse a selection of identifiers and numbers", () => {
60
+    const tree = parse("select a, 5");
61
+    expect(tree).to.deep.equal([
62
+      new AST.Statement({
63
+        arguments: [
64
+          new AST.Identifier("a"),
65
+          new AST.Number(5),
66
+        ],
67
+        type: AST.StatementType.SELECT,
68
+      }),
69
+    ]);
70
+  });
45 71
 });

Loading…
Cancel
Save