Browse Source

Prettier

master
Dylan Baker 4 years ago
parent
commit
90d84dbb6f
6 changed files with 184 additions and 184 deletions
  1. 8
    8
      src/index.js
  2. 51
    51
      src/lexer.js
  3. 60
    60
      src/parser.js
  4. 12
    12
      src/tokenTypes.js
  5. 10
    10
      test/helpers.js
  6. 43
    43
      test/parserTest.js

+ 8
- 8
src/index.js View File

@@ -1,11 +1,11 @@
1
-const Lexer = require("./lexer");
2
-const Parser = require("./parser");
1
+const Lexer = require('./lexer')
2
+const Parser = require('./parser')
3 3
 
4 4
 module.exports = function oslo(source, context) {
5
-  const lexer = new Lexer();
6
-  const tokens = lexer.scan(source);
7
-  const parser = new Parser(tokens);
8
-  const tree = parser.parse();
5
+  const lexer = new Lexer()
6
+  const tokens = lexer.scan(source)
7
+  const parser = new Parser(tokens)
8
+  const tree = parser.parse()
9 9
 
10
-  return tree;
11
-};
10
+  return tree
11
+}

+ 51
- 51
src/lexer.js View File

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

+ 60
- 60
src/parser.js View File

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

+ 12
- 12
src/tokenTypes.js View File

@@ -1,14 +1,14 @@
1 1
 module.exports = {
2
-  ATTRIBUTE: "attribute",
3
-  BOOLEAN: "boolean",
4
-  COMMA: ",",
5
-  CPAREN: ")",
6
-  EOF: "EOF",
7
-  IDENTIFIER: "identifier",
8
-  KEYWORD: "keyword",
9
-  LITERAL: "literal",
10
-  NUMBER: "number",
11
-  OPAREN: "(",
2
+  ATTRIBUTE: 'attribute',
3
+  BOOLEAN: 'boolean',
4
+  COMMA: ',',
5
+  CPAREN: ')',
6
+  EOF: 'EOF',
7
+  IDENTIFIER: 'identifier',
8
+  KEYWORD: 'keyword',
9
+  LITERAL: 'literal',
10
+  NUMBER: 'number',
11
+  OPAREN: '(',
12 12
   QUOTE: '"',
13
-  SYMBOL: "symbol"
14
-};
13
+  SYMBOL: 'symbol',
14
+}

+ 10
- 10
test/helpers.js View File

@@ -1,17 +1,17 @@
1
-const Lexer = require("../src/lexer");
2
-const Parser = require("../src/parser");
1
+const Lexer = require('../src/lexer')
2
+const Parser = require('../src/parser')
3 3
 
4 4
 const scan = source => {
5
-  const lexer = new Lexer();
6
-  return lexer.scan(source);
7
-};
5
+  const lexer = new Lexer()
6
+  return lexer.scan(source)
7
+}
8 8
 
9 9
 const parse = source => {
10
-  const parser = new Parser(scan(source));
11
-  return parser.parse();
12
-};
10
+  const parser = new Parser(scan(source))
11
+  return parser.parse()
12
+}
13 13
 
14 14
 module.exports = {
15 15
   scan: scan,
16
-  parse: parse
17
-};
16
+  parse: parse,
17
+}

+ 43
- 43
test/parserTest.js View File

@@ -1,69 +1,69 @@
1
-const test = require("tape");
2
-const helpers = require("./helpers");
1
+const test = require('tape')
2
+const helpers = require('./helpers')
3 3
 
4
-const AST = require("../src/ast/index");
5
-const tt = require("../src/tokenTypes");
4
+const AST = require('../src/ast/index')
5
+const tt = require('../src/tokenTypes')
6 6
 
7
-test("parses token stream into a tree", t => {
8
-  t.plan(1);
7
+test('parses token stream into a tree', t => {
8
+  t.plan(1)
9 9
   const tree = helpers.parse(`
10 10
     (div :class "foobar"
11 11
       (p :class (cond #t "primary" "secondary")))
12
-  `);
12
+  `)
13 13
 
14 14
   t.deepEqual(tree, [
15 15
     new AST.Application({
16
-      functionName: new AST.Identifier({ name: "div" }),
16
+      functionName: new AST.Identifier({ name: 'div' }),
17 17
       args: [
18 18
         new AST.Attribute({
19
-          name: "class",
20
-          value: new AST.String({ value: "foobar" })
19
+          name: 'class',
20
+          value: new AST.String({ value: 'foobar' }),
21 21
         }),
22 22
         new AST.Application({
23
-          functionName: new AST.Identifier({ name: "p" }),
23
+          functionName: new AST.Identifier({ name: 'p' }),
24 24
           args: [
25 25
             new AST.Attribute({
26
-              name: "class",
26
+              name: 'class',
27 27
               value: new AST.Application({
28
-                functionName: new AST.Identifier({ name: "cond" }),
28
+                functionName: new AST.Identifier({ name: 'cond' }),
29 29
                 args: [
30 30
                   new AST.Boolean({ value: true }),
31
-                  new AST.String({ value: "primary" }),
32
-                  new AST.String({ value: "secondary" })
33
-                ]
34
-              })
35
-            })
36
-          ]
37
-        })
38
-      ]
39
-    })
40
-  ]);
41
-});
31
+                  new AST.String({ value: 'primary' }),
32
+                  new AST.String({ value: 'secondary' }),
33
+                ],
34
+              }),
35
+            }),
36
+          ],
37
+        }),
38
+      ],
39
+    }),
40
+  ])
41
+})
42 42
 
43
-test("allow empty strings", t => {
44
-  t.plan(1);
45
-  const tree = helpers.parse('(p "")');
43
+test('allow empty strings', t => {
44
+  t.plan(1)
45
+  const tree = helpers.parse('(p "")')
46 46
 
47 47
   t.deepEqual(tree, [
48 48
     new AST.Application({
49
-      functionName: new AST.Identifier({ name: "p" }),
50
-      args: [new AST.String({ value: "" })]
51
-    })
52
-  ]);
53
-});
49
+      functionName: new AST.Identifier({ name: 'p' }),
50
+      args: [new AST.String({ value: '' })],
51
+    }),
52
+  ])
53
+})
54 54
 
55
-test("parses calls to define into a function definition", t => {
56
-  t.plan(1);
57
-  const tree = helpers.parse("(define plusOne (n) (+ n 1))");
55
+test('parses calls to define into a function definition', t => {
56
+  t.plan(1)
57
+  const tree = helpers.parse('(define plusOne (n) (+ n 1))')
58 58
 
59 59
   t.deepEqual(tree, [
60 60
     new AST.FunctionDefinition({
61
-      name: new AST.Identifier({ name: "plusOne" }),
62
-      parameters: [new AST.Identifier({ name: "n" })],
61
+      name: new AST.Identifier({ name: 'plusOne' }),
62
+      parameters: [new AST.Identifier({ name: 'n' })],
63 63
       body: new AST.Application({
64
-        functionName: new AST.Identifier({ name: "+" }),
65
-        args: [new AST.Identifier({ name: "n" }), new AST.Number({ value: 1 })]
66
-      })
67
-    })
68
-  ]);
69
-});
64
+        functionName: new AST.Identifier({ name: '+' }),
65
+        args: [new AST.Identifier({ name: 'n' }), new AST.Number({ value: 1 })],
66
+      }),
67
+    }),
68
+  ])
69
+})

Loading…
Cancel
Save