Comparing version 0.5.1 to 0.5.2
100
moo.js
@@ -56,2 +56,34 @@ (function(root, factory) { | ||
function pad(s, length) { | ||
if (s.length > length) { | ||
return s | ||
} | ||
return Array(length - s.length + 1).join(" ") + s | ||
} | ||
function lastNLines(string, numLines) { | ||
var position = string.length | ||
var lineBreaks = 0; | ||
while (true) { | ||
var idx = string.lastIndexOf("\n", position - 1) | ||
if (idx === -1) { | ||
break; | ||
} else { | ||
lineBreaks++ | ||
} | ||
position = idx | ||
if (lineBreaks === numLines) { | ||
break; | ||
} | ||
if (position === 0) { | ||
break; | ||
} | ||
} | ||
var startPosition = | ||
lineBreaks < numLines ? | ||
0 : | ||
position + 1 | ||
return string.substring(startPosition).split("\n") | ||
} | ||
function objectToRules(object) { | ||
@@ -339,4 +371,8 @@ var keys = Object.getOwnPropertyNames(object) | ||
function keywordTransform(map) { | ||
var reverseMap = Object.create(null) | ||
var byLength = Object.create(null) | ||
// Use a JavaScript Map to map keywords to their corresponding token type | ||
// unless Map is unsupported, then fall back to using an Object: | ||
var isMap = typeof Map !== 'undefined' | ||
var reverseMap = isMap ? new Map : Object.create(null) | ||
var types = Object.getOwnPropertyNames(map) | ||
@@ -348,27 +384,15 @@ for (var i = 0; i < types.length; i++) { | ||
keywordList.forEach(function(keyword) { | ||
(byLength[keyword.length] = byLength[keyword.length] || []).push(keyword) | ||
if (typeof keyword !== 'string') { | ||
throw new Error("keyword must be string (in keyword '" + tokenType + "')") | ||
} | ||
reverseMap[keyword] = tokenType | ||
if (isMap) { | ||
reverseMap.set(keyword, tokenType) | ||
} else { | ||
reverseMap[keyword] = tokenType | ||
} | ||
}) | ||
} | ||
// fast string lookup | ||
// https://jsperf.com/string-lookups | ||
function str(x) { return JSON.stringify(x) } | ||
var source = '' | ||
source += 'switch (value.length) {\n' | ||
for (var length in byLength) { | ||
var keywords = byLength[length] | ||
source += 'case ' + length + ':\n' | ||
source += 'switch (value) {\n' | ||
keywords.forEach(function(keyword) { | ||
var tokenType = reverseMap[keyword] | ||
source += 'case ' + str(keyword) + ': return ' + str(tokenType) + '\n' | ||
}) | ||
source += '}\n' | ||
return function(k) { | ||
return isMap ? reverseMap.get(k) : reverseMap[k] | ||
} | ||
source += '}\n' | ||
return Function('value', source) // type | ||
} | ||
@@ -392,2 +416,3 @@ | ||
this.queuedToken = info ? info.queuedToken : null | ||
this.queuedText = info ? info.queuedText: ""; | ||
this.queuedThrow = info ? info.queuedThrow : null | ||
@@ -406,2 +431,3 @@ this.setState(info ? info.state : this.startState) | ||
queuedToken: this.queuedToken, | ||
queuedText: this.queuedText, | ||
queuedThrow: this.queuedThrow, | ||
@@ -538,3 +564,4 @@ } | ||
if (group.shouldThrow) { | ||
throw new Error(this.formatError(token, "invalid syntax")) | ||
var err = new Error(this.formatError(token, "invalid syntax")) | ||
throw err; | ||
} | ||
@@ -580,9 +607,24 @@ | ||
} | ||
var start = Math.max(0, token.offset - token.col + 1) | ||
var eol = token.lineBreaks ? token.text.indexOf('\n') : token.text.length | ||
var firstLine = this.buffer.substring(start, token.offset + eol) | ||
message += " at line " + token.line + " col " + token.col + ":\n\n" | ||
message += " " + firstLine + "\n" | ||
message += " " + Array(token.col).join(" ") + "^" | ||
return message | ||
var numLinesAround = 2 | ||
var firstDisplayedLine = Math.max(token.line - numLinesAround, 1) | ||
var lastDisplayedLine = token.line + numLinesAround | ||
var lastLineDigits = String(lastDisplayedLine).length | ||
var displayedLines = lastNLines( | ||
this.buffer, | ||
(this.line - token.line) + numLinesAround + 1 | ||
) | ||
.slice(0, 5) | ||
var errorLines = [] | ||
errorLines.push(message + " at line " + token.line + " col " + token.col + ":") | ||
errorLines.push("") | ||
for (var i = 0; i < displayedLines.length; i++) { | ||
var line = displayedLines[i] | ||
var lineNo = firstDisplayedLine + i | ||
errorLines.push(pad(String(lineNo), lastLineDigits) + " " + line); | ||
if (lineNo === token.line) { | ||
errorLines.push(pad("", lastLineDigits + token.col + 1) + "^") | ||
} | ||
} | ||
return errorLines.join("\n") | ||
} | ||
@@ -589,0 +631,0 @@ |
{ | ||
"name": "moo", | ||
"version": "0.5.1", | ||
"version": "0.5.2", | ||
"description": "Optimised tokenizer/lexer generator! π Much performance. Moo!", | ||
@@ -5,0 +5,0 @@ "main": "moo.js", |
@@ -243,8 +243,6 @@ ![](cow.png) | ||
You can use [itt](https://github.com/nathan/itt)'s iterator adapters to make constructing keyword objects easier: | ||
You can use `Object.fromEntries` to easily construct keyword objects: | ||
```js | ||
itt(['class', 'def', 'if']) | ||
.map(k => ['kw-' + k, k]) | ||
.toObject() | ||
Object.fromEntries(['class', 'def', 'if'].map(k => ['kw-' + k, k])) | ||
``` | ||
@@ -274,3 +272,3 @@ | ||
lbrace: {match: '{', push: 'main'}, | ||
rbrace: {match: '}', pop: true}, | ||
rbrace: {match: '}', pop: 1}, | ||
colon: ':', | ||
@@ -282,3 +280,3 @@ space: {match: /\s+/, lineBreaks: true}, | ||
escape: /\\./, | ||
strend: {match: '`', pop: true}, | ||
strend: {match: '`', pop: 1}, | ||
const: {match: /(?:[^$`]|\$(?!\{))+/, lineBreaks: true}, | ||
@@ -356,6 +354,6 @@ }, | ||
Use [itt](https://github.com/nathan/itt)'s iteration tools with Moo. | ||
Use [itt](https://www.npmjs.com/package/itt)'s iteration tools with Moo. | ||
```js | ||
for (let [here, next] = itt(lexer).lookahead()) { // pass a number if you need more tokens | ||
for (let [here, next] of itt(lexer).lookahead()) { // pass a number if you need more tokens | ||
// enjoy! | ||
@@ -362,0 +360,0 @@ } |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
32679
560
384