Browse Source

WIP Parser

master
Dylan Baker 6 years ago
parent
commit
bdf7527409
3 changed files with 73 additions and 2 deletions
  1. 2
    0
      src/node.js
  2. 55
    0
      src/parser.js
  3. 16
    2
      src/tokenStream.js

+ 2
- 0
src/node.js View File

@@ -0,0 +1,2 @@
1
+module.exports = class Node {
2
+}

+ 55
- 0
src/parser.js View File

@@ -0,0 +1,55 @@
1
+const Node = require('./node')
2
+const tokenTypes = require('./tokenTypes')
3
+
4
+module.exports = class Parser {
5
+  constructor(tokens) {
6
+    this.tokens = tokens
7
+  }
8
+
9
+  parse() {
10
+    let tree = []
11
+    while (this.tokens.peek().type !== tokenTypes.EOF) {
12
+      tree.push(this.expr())
13
+    }
14
+    return tree
15
+  }
16
+
17
+  expr() {
18
+    this.tokens.eat(tokenTypes.OPAREN)
19
+
20
+    let tokenTypesToEndTheLoop = [
21
+      tokenTypes.OPAREN,
22
+      tokenTypes.CPAREN,
23
+      tokenTypes.EOF,
24
+    ]
25
+
26
+    let functionCallNode = new Node()
27
+    functionCallNode.functionName = this.tokens.eat(tokenTypes.LITERAL).value
28
+    functionCallNode.args = []
29
+    functionCallNode.subtree = []
30
+
31
+    while (!tokenTypesToEndTheLoop.includes(this.tokens.peek().type)) {
32
+      if (this.tokens.peek().type === tokenTypes.ATTRIBUTE) {
33
+        functionCallNode.args.push(this.attribute())
34
+      }
35
+    }
36
+
37
+    this.tokens.eat(tokenTypes.CPAREN)
38
+
39
+    return functionCallNode
40
+  }
41
+
42
+  attribute() {
43
+    let attributeNode = new Node()
44
+    attributeNode.attributeName = this.tokens.eat(tokenTypes.ATTRIBUTE).value
45
+    attributeNode.attributeValue = this.string()
46
+    return attributeNode
47
+  }
48
+
49
+  string() {
50
+    this.tokens.eat(tokenTypes.QUOTE)
51
+    let stringValue = this.tokens.eat(tokenTypes.LITERAL).value
52
+    this.tokens.eat(tokenTypes.QUOTE)
53
+    return stringValue
54
+  }
55
+}

+ 16
- 2
src/tokenStream.js View File

@@ -1,8 +1,22 @@
1 1
 module.exports = class TokenStream extends Array {
2
+  constructor() {
3
+    super()
4
+    this.position = 0
5
+  }
6
+
7
+  advance() {
8
+    this.position++
9
+  }
10
+
2 11
   eat(tokenType) {
3
-    if (this[0] && this[0].type === tokenType) {
4
-      return this[0]
12
+    if (this.peek() && this.peek().type === tokenType) {
13
+      this.advance()
14
+      return this.peek(-1)
5 15
     }
6 16
     return false
7 17
   }
18
+
19
+  peek(step = 0) {
20
+    return this[this.position + step]
21
+  }
8 22
 }

Loading…
Cancel
Save