Browse Source

Initial commit

master
Dylan Baker 3 years ago
commit
190d19a7a1
6 changed files with 574 additions and 0 deletions
  1. 1
    0
      .gitignore
  2. 21
    0
      LICENSE
  3. 425
    0
      package-lock.json
  4. 18
    0
      package.json
  5. 69
    0
      src/lexer.js
  6. 40
    0
      test/lexer.js

+ 1
- 0
.gitignore View File

@@ -0,0 +1 @@
1
+node_modules

+ 21
- 0
LICENSE View File

@@ -0,0 +1,21 @@
1
+MIT License
2
+
3
+Copyright (c) 2018 Dylan Baker
4
+
5
+Permission is hereby granted, free of charge, to any person obtaining a copy
6
+of this software and associated documentation files (the "Software"), to deal
7
+in the Software without restriction, including without limitation the rights
8
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+copies of the Software, and to permit persons to whom the Software is
10
+furnished to do so, subject to the following conditions:
11
+
12
+The above copyright notice and this permission notice shall be included in all
13
+copies or substantial portions of the Software.
14
+
15
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+SOFTWARE.

+ 425
- 0
package-lock.json View File

@@ -0,0 +1,425 @@
1
+{
2
+  "name": "oslo",
3
+  "version": "0.0.1",
4
+  "lockfileVersion": 1,
5
+  "requires": true,
6
+  "dependencies": {
7
+    "balanced-match": {
8
+      "version": "1.0.0",
9
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
10
+      "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
11
+      "dev": true
12
+    },
13
+    "brace-expansion": {
14
+      "version": "1.1.11",
15
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
16
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
17
+      "dev": true,
18
+      "requires": {
19
+        "balanced-match": "1.0.0",
20
+        "concat-map": "0.0.1"
21
+      }
22
+    },
23
+    "concat-map": {
24
+      "version": "0.0.1",
25
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
26
+      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
27
+      "dev": true
28
+    },
29
+    "core-util-is": {
30
+      "version": "1.0.2",
31
+      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
32
+      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
33
+      "dev": true
34
+    },
35
+    "deep-equal": {
36
+      "version": "1.0.1",
37
+      "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
38
+      "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
39
+      "dev": true
40
+    },
41
+    "define-properties": {
42
+      "version": "1.1.2",
43
+      "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz",
44
+      "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=",
45
+      "dev": true,
46
+      "requires": {
47
+        "foreach": "2.0.5",
48
+        "object-keys": "1.0.11"
49
+      }
50
+    },
51
+    "defined": {
52
+      "version": "1.0.0",
53
+      "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
54
+      "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=",
55
+      "dev": true
56
+    },
57
+    "duplexer": {
58
+      "version": "0.1.1",
59
+      "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
60
+      "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
61
+      "dev": true
62
+    },
63
+    "es-abstract": {
64
+      "version": "1.11.0",
65
+      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.11.0.tgz",
66
+      "integrity": "sha512-ZnQrE/lXTTQ39ulXZ+J1DTFazV9qBy61x2bY071B+qGco8Z8q1QddsLdt/EF8Ai9hcWH72dWS0kFqXLxOxqslA==",
67
+      "dev": true,
68
+      "requires": {
69
+        "es-to-primitive": "1.1.1",
70
+        "function-bind": "1.1.1",
71
+        "has": "1.0.1",
72
+        "is-callable": "1.1.3",
73
+        "is-regex": "1.0.4"
74
+      }
75
+    },
76
+    "es-to-primitive": {
77
+      "version": "1.1.1",
78
+      "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz",
79
+      "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=",
80
+      "dev": true,
81
+      "requires": {
82
+        "is-callable": "1.1.3",
83
+        "is-date-object": "1.0.1",
84
+        "is-symbol": "1.0.1"
85
+      }
86
+    },
87
+    "faucet": {
88
+      "version": "0.0.1",
89
+      "resolved": "https://registry.npmjs.org/faucet/-/faucet-0.0.1.tgz",
90
+      "integrity": "sha1-WX3PHSGJosBiMhtZHo8VHtIDnZw=",
91
+      "dev": true,
92
+      "requires": {
93
+        "defined": "0.0.0",
94
+        "duplexer": "0.1.1",
95
+        "minimist": "0.0.5",
96
+        "sprintf": "0.1.5",
97
+        "tap-parser": "0.4.3",
98
+        "tape": "2.3.3",
99
+        "through2": "0.2.3"
100
+      },
101
+      "dependencies": {
102
+        "deep-equal": {
103
+          "version": "0.1.2",
104
+          "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.1.2.tgz",
105
+          "integrity": "sha1-skbCuApXCkfBG+HZvRBw7IeLh84=",
106
+          "dev": true
107
+        },
108
+        "defined": {
109
+          "version": "0.0.0",
110
+          "resolved": "https://registry.npmjs.org/defined/-/defined-0.0.0.tgz",
111
+          "integrity": "sha1-817qfXBekzuvE7LwOz+D2SFAOz4=",
112
+          "dev": true
113
+        },
114
+        "minimist": {
115
+          "version": "0.0.5",
116
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.5.tgz",
117
+          "integrity": "sha1-16oye87PUY+RBqxrjwA/o7zqhWY=",
118
+          "dev": true
119
+        },
120
+        "tape": {
121
+          "version": "2.3.3",
122
+          "resolved": "https://registry.npmjs.org/tape/-/tape-2.3.3.tgz",
123
+          "integrity": "sha1-Lnzgox3wn41oUWZKcYQuDKUFevc=",
124
+          "dev": true,
125
+          "requires": {
126
+            "deep-equal": "0.1.2",
127
+            "defined": "0.0.0",
128
+            "inherits": "2.0.3",
129
+            "jsonify": "0.0.0",
130
+            "resumer": "0.0.0",
131
+            "through": "2.3.8"
132
+          }
133
+        }
134
+      }
135
+    },
136
+    "for-each": {
137
+      "version": "0.3.2",
138
+      "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.2.tgz",
139
+      "integrity": "sha1-LEBFC5NI6X8oEyJZO6lnBLmr1NQ=",
140
+      "dev": true,
141
+      "requires": {
142
+        "is-function": "1.0.1"
143
+      }
144
+    },
145
+    "foreach": {
146
+      "version": "2.0.5",
147
+      "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
148
+      "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=",
149
+      "dev": true
150
+    },
151
+    "fs.realpath": {
152
+      "version": "1.0.0",
153
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
154
+      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
155
+      "dev": true
156
+    },
157
+    "function-bind": {
158
+      "version": "1.1.1",
159
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
160
+      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
161
+      "dev": true
162
+    },
163
+    "glob": {
164
+      "version": "7.1.2",
165
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
166
+      "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
167
+      "dev": true,
168
+      "requires": {
169
+        "fs.realpath": "1.0.0",
170
+        "inflight": "1.0.6",
171
+        "inherits": "2.0.3",
172
+        "minimatch": "3.0.4",
173
+        "once": "1.4.0",
174
+        "path-is-absolute": "1.0.1"
175
+      }
176
+    },
177
+    "has": {
178
+      "version": "1.0.1",
179
+      "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz",
180
+      "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=",
181
+      "dev": true,
182
+      "requires": {
183
+        "function-bind": "1.1.1"
184
+      }
185
+    },
186
+    "inflight": {
187
+      "version": "1.0.6",
188
+      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
189
+      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
190
+      "dev": true,
191
+      "requires": {
192
+        "once": "1.4.0",
193
+        "wrappy": "1.0.2"
194
+      }
195
+    },
196
+    "inherits": {
197
+      "version": "2.0.3",
198
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
199
+      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
200
+      "dev": true
201
+    },
202
+    "is-callable": {
203
+      "version": "1.1.3",
204
+      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz",
205
+      "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=",
206
+      "dev": true
207
+    },
208
+    "is-date-object": {
209
+      "version": "1.0.1",
210
+      "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
211
+      "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
212
+      "dev": true
213
+    },
214
+    "is-function": {
215
+      "version": "1.0.1",
216
+      "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz",
217
+      "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=",
218
+      "dev": true
219
+    },
220
+    "is-regex": {
221
+      "version": "1.0.4",
222
+      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
223
+      "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
224
+      "dev": true,
225
+      "requires": {
226
+        "has": "1.0.1"
227
+      }
228
+    },
229
+    "is-symbol": {
230
+      "version": "1.0.1",
231
+      "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz",
232
+      "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=",
233
+      "dev": true
234
+    },
235
+    "isarray": {
236
+      "version": "0.0.1",
237
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
238
+      "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
239
+      "dev": true
240
+    },
241
+    "jsonify": {
242
+      "version": "0.0.0",
243
+      "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
244
+      "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
245
+      "dev": true
246
+    },
247
+    "minimatch": {
248
+      "version": "3.0.4",
249
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
250
+      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
251
+      "dev": true,
252
+      "requires": {
253
+        "brace-expansion": "1.1.11"
254
+      }
255
+    },
256
+    "minimist": {
257
+      "version": "1.2.0",
258
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
259
+      "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
260
+      "dev": true
261
+    },
262
+    "object-inspect": {
263
+      "version": "1.5.0",
264
+      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.5.0.tgz",
265
+      "integrity": "sha512-UmOFbHbwvv+XHj7BerrhVq+knjceBdkvU5AriwLMvhv2qi+e7DJzxfBeFpILEjVzCp+xA+W/pIf06RGPWlZNfw==",
266
+      "dev": true
267
+    },
268
+    "object-keys": {
269
+      "version": "1.0.11",
270
+      "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz",
271
+      "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=",
272
+      "dev": true
273
+    },
274
+    "once": {
275
+      "version": "1.4.0",
276
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
277
+      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
278
+      "dev": true,
279
+      "requires": {
280
+        "wrappy": "1.0.2"
281
+      }
282
+    },
283
+    "path-is-absolute": {
284
+      "version": "1.0.1",
285
+      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
286
+      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
287
+      "dev": true
288
+    },
289
+    "path-parse": {
290
+      "version": "1.0.5",
291
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz",
292
+      "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=",
293
+      "dev": true
294
+    },
295
+    "prettier": {
296
+      "version": "1.12.1",
297
+      "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.12.1.tgz",
298
+      "integrity": "sha1-wa0g6APndJ+vkFpAnSNn4Gu+cyU=",
299
+      "dev": true
300
+    },
301
+    "readable-stream": {
302
+      "version": "1.1.14",
303
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
304
+      "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
305
+      "dev": true,
306
+      "requires": {
307
+        "core-util-is": "1.0.2",
308
+        "inherits": "2.0.3",
309
+        "isarray": "0.0.1",
310
+        "string_decoder": "0.10.31"
311
+      }
312
+    },
313
+    "resolve": {
314
+      "version": "1.5.0",
315
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz",
316
+      "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==",
317
+      "dev": true,
318
+      "requires": {
319
+        "path-parse": "1.0.5"
320
+      }
321
+    },
322
+    "resumer": {
323
+      "version": "0.0.0",
324
+      "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz",
325
+      "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=",
326
+      "dev": true,
327
+      "requires": {
328
+        "through": "2.3.8"
329
+      }
330
+    },
331
+    "sprintf": {
332
+      "version": "0.1.5",
333
+      "resolved": "https://registry.npmjs.org/sprintf/-/sprintf-0.1.5.tgz",
334
+      "integrity": "sha1-j4PjmpMXwaUCy324BQ5Rxnn27c8=",
335
+      "dev": true
336
+    },
337
+    "string.prototype.trim": {
338
+      "version": "1.1.2",
339
+      "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz",
340
+      "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=",
341
+      "dev": true,
342
+      "requires": {
343
+        "define-properties": "1.1.2",
344
+        "es-abstract": "1.11.0",
345
+        "function-bind": "1.1.1"
346
+      }
347
+    },
348
+    "string_decoder": {
349
+      "version": "0.10.31",
350
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
351
+      "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
352
+      "dev": true
353
+    },
354
+    "tap-parser": {
355
+      "version": "0.4.3",
356
+      "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-0.4.3.tgz",
357
+      "integrity": "sha1-pOrhkMENdsehEZIf84u+TVjwnuo=",
358
+      "dev": true,
359
+      "requires": {
360
+        "inherits": "2.0.3",
361
+        "readable-stream": "1.1.14"
362
+      }
363
+    },
364
+    "tape": {
365
+      "version": "4.9.0",
366
+      "resolved": "https://registry.npmjs.org/tape/-/tape-4.9.0.tgz",
367
+      "integrity": "sha512-j0jO9BiScfqtPBb9QmPLL0qvxXMz98xjkMb7x8lKipFlJZwNJkqkWPou+NU4V6T9RnVh1kuSthLE8gLrN8bBfw==",
368
+      "dev": true,
369
+      "requires": {
370
+        "deep-equal": "1.0.1",
371
+        "defined": "1.0.0",
372
+        "for-each": "0.3.2",
373
+        "function-bind": "1.1.1",
374
+        "glob": "7.1.2",
375
+        "has": "1.0.1",
376
+        "inherits": "2.0.3",
377
+        "minimist": "1.2.0",
378
+        "object-inspect": "1.5.0",
379
+        "resolve": "1.5.0",
380
+        "resumer": "0.0.0",
381
+        "string.prototype.trim": "1.1.2",
382
+        "through": "2.3.8"
383
+      }
384
+    },
385
+    "through": {
386
+      "version": "2.3.8",
387
+      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
388
+      "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
389
+      "dev": true
390
+    },
391
+    "through2": {
392
+      "version": "0.2.3",
393
+      "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz",
394
+      "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=",
395
+      "dev": true,
396
+      "requires": {
397
+        "readable-stream": "1.1.14",
398
+        "xtend": "2.1.2"
399
+      }
400
+    },
401
+    "wrappy": {
402
+      "version": "1.0.2",
403
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
404
+      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
405
+      "dev": true
406
+    },
407
+    "xtend": {
408
+      "version": "2.1.2",
409
+      "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz",
410
+      "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=",
411
+      "dev": true,
412
+      "requires": {
413
+        "object-keys": "0.4.0"
414
+      },
415
+      "dependencies": {
416
+        "object-keys": {
417
+          "version": "0.4.0",
418
+          "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz",
419
+          "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=",
420
+          "dev": true
421
+        }
422
+      }
423
+    }
424
+  }
425
+}

+ 18
- 0
package.json View File

@@ -0,0 +1,18 @@
1
+{
2
+  "name": "oslo",
3
+  "version": "0.0.1",
4
+  "description": "",
5
+  "main": "index.js",
6
+  "scripts": {
7
+    "test": "faucet test/*.js",
8
+    "pretty": "prettier --single-quote --no-semi --trailing-comma all --write ./**/*.js"
9
+  },
10
+  "keywords": [],
11
+  "author": "",
12
+  "license": "MIT",
13
+  "devDependencies": {
14
+    "faucet": "0.0.1",
15
+    "prettier": "^1.12.1",
16
+    "tape": "^4.9.0"
17
+  }
18
+}

+ 69
- 0
src/lexer.js View File

@@ -0,0 +1,69 @@
1
+const tokenTypes = {
2
+  OPAREN: '(',
3
+  CPAREN: ')',
4
+  KEYWORD: 'keyword',
5
+  QUOTE: '"',
6
+  LITERAL: 'literal',
7
+  ATTRIBUTE: 'attribute',
8
+  EOF: 'eof',
9
+}
10
+
11
+const scan = source => {
12
+  pos = 0
13
+  line = 1
14
+  tokens = []
15
+
16
+  while (pos < source.length) {
17
+    if (source[pos].match(/\(/)) {
18
+      tokens.push({
19
+        type: tokenTypes.OPAREN,
20
+        line: line,
21
+      })
22
+      pos++
23
+    } else if (source[pos].match(/\)/)) {
24
+      tokens.push({
25
+        type: tokenTypes.CPAREN,
26
+        line: line,
27
+      })
28
+      pos++
29
+    } else if (source[pos].match(/['"]/)) {
30
+      tokens.push({
31
+        type: tokenTypes.QUOTE,
32
+        line: line,
33
+      })
34
+      pos++
35
+    } else if (source[pos].match(/:/)) {
36
+      let value = /:([^()'"\s]+)/.exec(source)[1].trim()
37
+      tokens.push({
38
+        type: tokenTypes.ATTRIBUTE,
39
+        line: line,
40
+        value: value,
41
+      })
42
+      pos += value.length + 1 // the +1 is to account for the colon
43
+    } else if (source[pos].match(/\n/)) {
44
+      line++
45
+      pos++
46
+    } else if (source[pos].match(/\s/)) {
47
+      pos++
48
+    } else {
49
+      let value = /[^()"':]+/.exec(source.slice(pos))[0]
50
+      tokens.push({
51
+        type: tokenTypes.LITERAL,
52
+        line: line,
53
+        value: value.trim(),
54
+      })
55
+      pos += value.length
56
+    }
57
+  }
58
+
59
+  tokens.push({
60
+    type: tokenTypes.EOF,
61
+    line: line,
62
+  })
63
+  return tokens
64
+}
65
+
66
+module.exports = {
67
+  scan: scan,
68
+  tokenTypes: tokenTypes,
69
+}

+ 40
- 0
test/lexer.js View File

@@ -0,0 +1,40 @@
1
+const test = require('tape')
2
+const lexer = require('../src/lexer')
3
+
4
+const tt = lexer.tokenTypes
5
+
6
+test('lexes simple template correctly', t => {
7
+  t.plan(4)
8
+  let tokens = lexer.scan(
9
+    '(div :class "foobar" (p "Lorem ipsum dolor sit amet"))',
10
+  )
11
+  t.deepEqual(tokens.map(token => token.type), [
12
+    tt.OPAREN,
13
+    tt.LITERAL,
14
+    tt.ATTRIBUTE,
15
+    tt.QUOTE,
16
+    tt.LITERAL,
17
+    tt.QUOTE,
18
+    tt.OPAREN,
19
+    tt.LITERAL,
20
+    tt.QUOTE,
21
+    tt.LITERAL,
22
+    tt.QUOTE,
23
+    tt.CPAREN,
24
+    tt.CPAREN,
25
+    tt.EOF,
26
+  ])
27
+  t.equal(tokens[1].value, 'div')
28
+  t.equal(tokens[2].value, 'class')
29
+  t.equal(tokens[9].value, 'Lorem ipsum dolor sit amet')
30
+})
31
+
32
+test('keeps track of line numbers', t => {
33
+  t.plan(2)
34
+  let tokens = lexer.scan(`(
35
+    (div :class "foobar"
36
+      (p :class "bazquux"))
37
+  `)
38
+  t.equal(tokens[2].line, 2)
39
+  t.equal(tokens[7].line, 3)
40
+})

Loading…
Cancel
Save