Browse Source

Prettier

master
Dylan Baker 5 years ago
parent
commit
3b6525e29f
3 changed files with 123 additions and 117 deletions
  1. 36
    32
      src/compiler.js
  2. 48
    48
      src/lexer.js
  3. 39
    37
      src/parser.js

+ 36
- 32
src/compiler.js View File

1
-const selfClosingTags = require('./util/selfClosingTags')
1
+const selfClosingTags = require("./util/selfClosingTags");
2
 
2
 
3
 module.exports = class Compiler {
3
 module.exports = class Compiler {
4
   constructor(tree, context) {
4
   constructor(tree, context) {
5
-    this.tree = tree
6
-    this.context = context
7
-    this.pos = 0
8
-    this.result = ''
5
+    this.tree = tree;
6
+    this.context = context;
7
+    this.pos = 0;
8
+    this.result = "";
9
   }
9
   }
10
 
10
 
11
   compile() {
11
   compile() {
12
     this.tree.forEach(node => {
12
     this.tree.forEach(node => {
13
       switch (node.constructor.name) {
13
       switch (node.constructor.name) {
14
-        case 'Application':
15
-          this.result += this.application(node)
14
+        case "Application":
15
+          this.result += this.application(node);
16
           break;
16
           break;
17
-        case 'Identifier':
18
-          this.result += this.lookup(node)
17
+        case "Identifier":
18
+          this.result += this.lookup(node);
19
           break;
19
           break;
20
-        case 'String':
20
+        case "String":
21
           this.result += node.value;
21
           this.result += node.value;
22
           break;
22
           break;
23
       }
23
       }
24
-    })
24
+    });
25
 
25
 
26
-    return this.result
26
+    return this.result;
27
   }
27
   }
28
 
28
 
29
   application(node) {
29
   application(node) {
30
-    let result = `<${node.functionName.name}`
30
+    let result = `<${node.functionName.name}`;
31
 
31
 
32
-    node.args.filter(arg => arg.constructor.name === 'Attribute').forEach(arg => {
33
-      result += ` ${arg.name}`
32
+    node.args
33
+      .filter(arg => arg.constructor.name === "Attribute")
34
+      .forEach(arg => {
35
+        result += ` ${arg.name}`;
34
 
36
 
35
-      let compiler = new Compiler([arg.value], this.context)
36
-      let attrValue = compiler.compile()
37
+        let compiler = new Compiler([arg.value], this.context);
38
+        let attrValue = compiler.compile();
37
 
39
 
38
-      if (attrValue) {
39
-       result += `="${attrValue}"`
40
-      }
41
-    })
40
+        if (attrValue) {
41
+          result += `="${attrValue}"`;
42
+        }
43
+      });
42
 
44
 
43
-    result += '>'
45
+    result += ">";
44
 
46
 
45
-    node.args.filter(arg => arg.constructor.name !== 'Attribute').forEach(arg => {
46
-      let compiler = new Compiler([arg], this.context)
47
-      result += compiler.compile()
48
-    })
47
+    node.args
48
+      .filter(arg => arg.constructor.name !== "Attribute")
49
+      .forEach(arg => {
50
+        let compiler = new Compiler([arg], this.context);
51
+        result += compiler.compile();
52
+      });
49
 
53
 
50
     if (!selfClosingTags.includes(node.functionName.name)) {
54
     if (!selfClosingTags.includes(node.functionName.name)) {
51
-      result += `</${node.functionName.name}>`
55
+      result += `</${node.functionName.name}>`;
52
     }
56
     }
53
 
57
 
54
-    return result
58
+    return result;
55
   }
59
   }
56
 
60
 
57
   lookup(identifier) {
61
   lookup(identifier) {
58
-    let result = this.context[identifier.name]
62
+    let result = this.context[identifier.name];
59
 
63
 
60
     if (!result) {
64
     if (!result) {
61
-      throw `Undefined variable '${identifier.name}'`
65
+      throw `Undefined variable '${identifier.name}'`;
62
     }
66
     }
63
 
67
 
64
-    return result
68
+    return result;
65
   }
69
   }
66
-}
70
+};

+ 48
- 48
src/lexer.js View File

1
-const TokenStream = require('./tokenStream')
2
-const tokenTypes = require('./tokenTypes')
1
+const TokenStream = require("./tokenStream");
2
+const tokenTypes = require("./tokenTypes");
3
 
3
 
4
 module.exports = class Lexer {
4
 module.exports = class Lexer {
5
   scan(source) {
5
   scan(source) {
6
-    let pos = 0
7
-    let line = 1
8
-    let tokenStream = new TokenStream()
9
-    let allowSpecialCharactersInLiterals = false
6
+    let pos = 0;
7
+    let line = 1;
8
+    let tokenStream = new TokenStream();
9
+    let allowSpecialCharactersInLiterals = false;
10
 
10
 
11
     while (pos < source.length) {
11
     while (pos < source.length) {
12
       if (source[pos].match(/\(/) && !allowSpecialCharactersInLiterals) {
12
       if (source[pos].match(/\(/) && !allowSpecialCharactersInLiterals) {
13
         tokenStream.tokens.push({
13
         tokenStream.tokens.push({
14
           type: tokenTypes.OPAREN,
14
           type: tokenTypes.OPAREN,
15
-          line: line,
16
-        })
17
-        pos++
15
+          line: line
16
+        });
17
+        pos++;
18
       } else if (source[pos].match(/\)/)) {
18
       } else if (source[pos].match(/\)/)) {
19
         tokenStream.tokens.push({
19
         tokenStream.tokens.push({
20
           type: tokenTypes.CPAREN,
20
           type: tokenTypes.CPAREN,
21
-          line: line,
22
-        })
23
-        pos++
21
+          line: line
22
+        });
23
+        pos++;
24
       } else if (source[pos].match(/["]/)) {
24
       } else if (source[pos].match(/["]/)) {
25
-        allowSpecialCharactersInLiterals = !allowSpecialCharactersInLiterals
25
+        allowSpecialCharactersInLiterals = !allowSpecialCharactersInLiterals;
26
         tokenStream.tokens.push({
26
         tokenStream.tokens.push({
27
           type: tokenTypes.QUOTE,
27
           type: tokenTypes.QUOTE,
28
-          line: line,
29
-        })
30
-        pos++
28
+          line: line
29
+        });
30
+        pos++;
31
       } else if (source[pos].match(/:/)) {
31
       } else if (source[pos].match(/:/)) {
32
-        let value = /:([^()'"\s]+)/.exec(source.slice(pos))[1].trim()
32
+        let value = /:([^()'"\s]+)/.exec(source.slice(pos))[1].trim();
33
         tokenStream.tokens.push({
33
         tokenStream.tokens.push({
34
           type: tokenTypes.ATTRIBUTE,
34
           type: tokenTypes.ATTRIBUTE,
35
           line: line,
35
           line: line,
36
-          value: value,
37
-        })
38
-        pos += value.length + 1 // the +1 is to account for the colon
36
+          value: value
37
+        });
38
+        pos += value.length + 1; // the +1 is to account for the colon
39
       } else if (source[pos].match(/\'/)) {
39
       } else if (source[pos].match(/\'/)) {
40
-        let value = /'([^()"\s]+)/.exec(source.slice(pos))[1].trim()
40
+        let value = /'([^()"\s]+)/.exec(source.slice(pos))[1].trim();
41
         tokenStream.tokens.push({
41
         tokenStream.tokens.push({
42
           type: tokenTypes.SYMBOL,
42
           type: tokenTypes.SYMBOL,
43
           line: line,
43
           line: line,
44
-          value: value,
45
-        })
46
-        pos += value.length + 1 // the +1 is to account for the apostrophe
44
+          value: value
45
+        });
46
+        pos += value.length + 1; // the +1 is to account for the apostrophe
47
       } else if (source[pos].match(/\d/)) {
47
       } else if (source[pos].match(/\d/)) {
48
-        let number = ''
48
+        let number = "";
49
         while (source[pos] && source[pos].match(/\d/)) {
49
         while (source[pos] && source[pos].match(/\d/)) {
50
-          number += source[pos]
51
-          pos++
50
+          number += source[pos];
51
+          pos++;
52
         }
52
         }
53
         tokenStream.tokens.push({
53
         tokenStream.tokens.push({
54
           type: tokenTypes.NUMBER,
54
           type: tokenTypes.NUMBER,
55
           line: line,
55
           line: line,
56
-          value: parseFloat(number),
57
-        })
56
+          value: parseFloat(number)
57
+        });
58
       } else if (source.slice(pos).match(/^#(t|f)/)) {
58
       } else if (source.slice(pos).match(/^#(t|f)/)) {
59
-        pos++
59
+        pos++;
60
         tokenStream.tokens.push({
60
         tokenStream.tokens.push({
61
           type: tokenTypes.BOOLEAN,
61
           type: tokenTypes.BOOLEAN,
62
           line: line,
62
           line: line,
63
-          value: source[pos] === 't' ? true : false
64
-        })
65
-        pos++
63
+          value: source[pos] === "t" ? true : false
64
+        });
65
+        pos++;
66
       } else if (source[pos].match(/\n/)) {
66
       } else if (source[pos].match(/\n/)) {
67
-        line++
68
-        pos++
67
+        line++;
68
+        pos++;
69
       } else if (source[pos].match(/\s/)) {
69
       } else if (source[pos].match(/\s/)) {
70
-        pos++
70
+        pos++;
71
       } else {
71
       } else {
72
-        let endPattern = /[^()"':\s]+/
72
+        let endPattern = /[^()"':\s]+/;
73
 
73
 
74
         if (allowSpecialCharactersInLiterals) {
74
         if (allowSpecialCharactersInLiterals) {
75
-          endPattern = /[^"']+/
75
+          endPattern = /[^"']+/;
76
         }
76
         }
77
 
77
 
78
-        let value = endPattern.exec(source.slice(pos))[0].trim()
78
+        let value = endPattern.exec(source.slice(pos))[0].trim();
79
 
79
 
80
         if (allowSpecialCharactersInLiterals) {
80
         if (allowSpecialCharactersInLiterals) {
81
           tokenStream.tokens.push({
81
           tokenStream.tokens.push({
82
             type: tokenTypes.LITERAL,
82
             type: tokenTypes.LITERAL,
83
             line: line,
83
             line: line,
84
-            value: value,
85
-          })
84
+            value: value
85
+          });
86
         } else {
86
         } else {
87
           tokenStream.tokens.push({
87
           tokenStream.tokens.push({
88
             type: tokenTypes.IDENTIFIER,
88
             type: tokenTypes.IDENTIFIER,
89
             line: line,
89
             line: line,
90
-            value: value.trim(),
91
-          })
90
+            value: value.trim()
91
+          });
92
         }
92
         }
93
 
93
 
94
-        pos += value.length
94
+        pos += value.length;
95
       }
95
       }
96
     }
96
     }
97
 
97
 
98
     tokenStream.tokens.push({
98
     tokenStream.tokens.push({
99
       type: tokenTypes.EOF,
99
       type: tokenTypes.EOF,
100
-      line: line,
101
-    })
102
-    return tokenStream
100
+      line: line
101
+    });
102
+    return tokenStream;
103
   }
103
   }
104
-}
104
+};

+ 39
- 37
src/parser.js View File

1
-const Error = require('./Error')
1
+const Error = require("./Error");
2
 
2
 
3
-const AST = require('./ast')
3
+const AST = require("./ast");
4
 
4
 
5
-const tokenTypes = require('./tokenTypes')
5
+const tokenTypes = require("./tokenTypes");
6
 
6
 
7
 module.exports = class Parser {
7
 module.exports = class Parser {
8
   constructor(tokenStream) {
8
   constructor(tokenStream) {
9
-    this.tokenStream = tokenStream
9
+    this.tokenStream = tokenStream;
10
   }
10
   }
11
 
11
 
12
   parse() {
12
   parse() {
13
-    let tree = []
13
+    let tree = [];
14
     while (this.tokenStream.peek().type !== tokenTypes.EOF) {
14
     while (this.tokenStream.peek().type !== tokenTypes.EOF) {
15
-      tree.push(this.expr())
15
+      tree.push(this.expr());
16
       if (this.tokenStream.error) {
16
       if (this.tokenStream.error) {
17
         return {
17
         return {
18
-          error: this.tokenStream.error,
19
-        }
18
+          error: this.tokenStream.error
19
+        };
20
       }
20
       }
21
     }
21
     }
22
-    return tree
22
+    return tree;
23
   }
23
   }
24
 
24
 
25
   expr() {
25
   expr() {
26
-    let token = this.tokenStream.peek()
26
+    let token = this.tokenStream.peek();
27
     switch (token.type) {
27
     switch (token.type) {
28
       case tokenTypes.ATTRIBUTE:
28
       case tokenTypes.ATTRIBUTE:
29
-        return this.attribute()
29
+        return this.attribute();
30
       case tokenTypes.BOOLEAN:
30
       case tokenTypes.BOOLEAN:
31
-        return this.bool()
31
+        return this.bool();
32
       case tokenTypes.IDENTIFIER:
32
       case tokenTypes.IDENTIFIER:
33
-        return this.identifier()
33
+        return this.identifier();
34
       case tokenTypes.NUMBER:
34
       case tokenTypes.NUMBER:
35
-        return this.number()
35
+        return this.number();
36
       case tokenTypes.QUOTE:
36
       case tokenTypes.QUOTE:
37
-        return this.string()
37
+        return this.string();
38
       case tokenTypes.SYMBOL:
38
       case tokenTypes.SYMBOL:
39
-        return this.symbol()
39
+        return this.symbol();
40
       case tokenTypes.OPAREN:
40
       case tokenTypes.OPAREN:
41
-        return this.form()
41
+        return this.form();
42
       default:
42
       default:
43
-        this.tokenStream.error = `Unexpected ${token.type} on line ${token.line}`
43
+        this.tokenStream.error = `Unexpected ${token.type} on line ${
44
+          token.line
45
+        }`;
44
         break;
46
         break;
45
     }
47
     }
46
   }
48
   }
47
 
49
 
48
   form() {
50
   form() {
49
-    this.tokenStream.eat(tokenTypes.OPAREN)
51
+    this.tokenStream.eat(tokenTypes.OPAREN);
50
 
52
 
51
-    let node = new AST.Application()
53
+    let node = new AST.Application();
52
 
54
 
53
-    node.functionName = this.identifier()
54
-    node.args = []
55
+    node.functionName = this.identifier();
56
+    node.args = [];
55
 
57
 
56
     while (this.tokenStream.peek().type !== tokenTypes.CPAREN) {
58
     while (this.tokenStream.peek().type !== tokenTypes.CPAREN) {
57
-      node.args.push(this.expr())
59
+      node.args.push(this.expr());
58
     }
60
     }
59
 
61
 
60
-    this.tokenStream.eat(tokenTypes.CPAREN)
62
+    this.tokenStream.eat(tokenTypes.CPAREN);
61
 
63
 
62
-    return node
64
+    return node;
63
   }
65
   }
64
 
66
 
65
   attribute() {
67
   attribute() {
66
     return new AST.Attribute({
68
     return new AST.Attribute({
67
       name: this.tokenStream.eat(tokenTypes.ATTRIBUTE).value,
69
       name: this.tokenStream.eat(tokenTypes.ATTRIBUTE).value,
68
       value: this.expr()
70
       value: this.expr()
69
-    })
71
+    });
70
   }
72
   }
71
 
73
 
72
   bool() {
74
   bool() {
73
     return new AST.Boolean({
75
     return new AST.Boolean({
74
       value: this.tokenStream.eat(tokenTypes.BOOLEAN).value
76
       value: this.tokenStream.eat(tokenTypes.BOOLEAN).value
75
-    })
77
+    });
76
   }
78
   }
77
 
79
 
78
   identifier() {
80
   identifier() {
79
     return new AST.Identifier({
81
     return new AST.Identifier({
80
       name: this.tokenStream.eat(tokenTypes.IDENTIFIER).value
82
       name: this.tokenStream.eat(tokenTypes.IDENTIFIER).value
81
-    })
83
+    });
82
   }
84
   }
83
 
85
 
84
   number() {
86
   number() {
85
     return new AST.Number({
87
     return new AST.Number({
86
       value: this.tokenStream.eat(tokenTypes.NUMBER).value
88
       value: this.tokenStream.eat(tokenTypes.NUMBER).value
87
-    })
89
+    });
88
   }
90
   }
89
 
91
 
90
   string() {
92
   string() {
91
-    this.tokenStream.eat(tokenTypes.QUOTE)
93
+    this.tokenStream.eat(tokenTypes.QUOTE);
92
 
94
 
93
-    let value = ''
95
+    let value = "";
94
 
96
 
95
     if (this.tokenStream.peek().type === tokenTypes.LITERAL) {
97
     if (this.tokenStream.peek().type === tokenTypes.LITERAL) {
96
-      value = this.tokenStream.eat(tokenTypes.LITERAL).value
98
+      value = this.tokenStream.eat(tokenTypes.LITERAL).value;
97
     }
99
     }
98
 
100
 
99
     let node = new AST.String({
101
     let node = new AST.String({
100
       value: value
102
       value: value
101
-    })
103
+    });
102
 
104
 
103
-    this.tokenStream.eat(tokenTypes.QUOTE)
105
+    this.tokenStream.eat(tokenTypes.QUOTE);
104
 
106
 
105
-    return node
107
+    return node;
106
   }
108
   }
107
 
109
 
108
   symbol() {
110
   symbol() {
109
     return new AST.Symbol({
111
     return new AST.Symbol({
110
       value: this.tokenStream.eat(tokenTypes.SYMBOL).value
112
       value: this.tokenStream.eat(tokenTypes.SYMBOL).value
111
-    })
113
+    });
112
   }
114
   }
113
-}
115
+};

Loading…
Cancel
Save