From ae250008976751b61f53fb98af9a688e22d0bc4d Mon Sep 17 00:00:00 2001 From: Felix Lee Date: Sun, 3 Sep 2017 12:09:46 -0700 Subject: [PATCH] use offset() instead of line()/column() for issue #39 --- index.js | 5 +++-- lib/compiler.js | 42 +++++++++++++++++++++++------------------- lib/parser.js | 5 ++--- src/toml.pegjs | 5 ++--- 4 files changed, 30 insertions(+), 27 deletions(-) diff --git a/index.js b/index.js index 6caf44a..f0c7c91 100644 --- a/index.js +++ b/index.js @@ -3,7 +3,8 @@ var compiler = require('./lib/compiler'); module.exports = { parse: function(input) { - var nodes = parser.parse(input.toString()); - return compiler.compile(nodes); + var normalized = String(input).replace(/\r\n/g, '\n'); + var nodes = parser.parse(normalized); + return compiler.compile(nodes, normalized); } }; diff --git a/lib/compiler.js b/lib/compiler.js index 10dc59a..0400f55 100644 --- a/lib/compiler.js +++ b/lib/compiler.js @@ -1,5 +1,5 @@ "use strict"; -function compile(nodes) { +function compile(nodes, sourceText) { var assignedPaths = []; var valueAssignments = []; var currentPath = ""; @@ -29,18 +29,26 @@ function compile(nodes) { return data; } - function genError(err, line, col) { + function getLocation(node) { + var before = sourceText.substr(0, node.offset); + var line = before.match(/\n/g).length + 1; + var column = before.match(/.*\n?$/)[0].length + 1; + return { offset: node.offset, line: line, column: column }; + } + + + function genError(node, err) { var ex = new Error(err); - ex.line = line; - ex.column = col; + var loc = getLocation(node); + ex.offset = loc.offset; + ex.line = loc.line; + ex.column = loc.column; throw ex; } function assign(node) { var key = node.key; var value = node.value; - var line = node.line; - var column = node.column; var fullPath; if (currentPath) { @@ -49,7 +57,7 @@ function compile(nodes) { fullPath = key; } if (typeof context[key] !== "undefined") { - genError("Cannot redefine existing key '" + fullPath + "'.", line, column); + genError(node, "Cannot redefine existing key '" + fullPath + "'."); } context[key] = reduceValueNode(value); @@ -92,22 +100,18 @@ function compile(nodes) { function setPath(node) { var path = node.value; var quotedPath = path.map(quoteDottedString).join("."); - var line = node.line; - var column = node.column; if (pathAssigned(quotedPath)) { - genError("Cannot redefine existing key '" + path + "'.", line, column); + genError(node, "Cannot redefine existing key '" + path + "'."); } assignedPaths.push(quotedPath); - context = deepRef(data, path, {}, line, column); + context = deepRef(data, path, {}, node); currentPath = path; } function addTableArray(node) { var path = node.value; var quotedPath = path.map(quoteDottedString).join("."); - var line = node.line; - var column = node.column; if (!pathAssigned(quotedPath)) { assignedPaths.push(quotedPath); @@ -116,7 +120,7 @@ function compile(nodes) { return p.indexOf(quotedPath) !== 0; }); assignedPaths.push(quotedPath); - context = deepRef(data, path, [], line, column); + context = deepRef(data, path, [], node); currentPath = quotedPath; if (context instanceof Array) { @@ -124,7 +128,7 @@ function compile(nodes) { context.push(newObj); context = newObj; } else { - genError("Cannot redefine existing key '" + path + "'.", line, column); + genError(node, "Cannot redefine existing key '" + path + "'."); } } @@ -132,7 +136,7 @@ function compile(nodes) { // `start.a.b`, and `start.a.b.c`, assigning `value` to `start.a.b.c`. // If `a` or `b` are arrays and have items in them, the last item in the // array is used as the context for the next sub-path. - function deepRef(start, keys, value, line, column) { + function deepRef(start, keys, value, node) { var traversed = []; var traversedPath = ""; var path = keys.join("."); @@ -150,7 +154,7 @@ function compile(nodes) { } } else if (i !== keys.length - 1 && valueAssignments.indexOf(traversedPath) > -1) { // already a non-object value at key, can't be used as part of a new path - genError("Cannot redefine existing key '" + traversedPath + "'.", line, column); + genError(node, "Cannot redefine existing key '" + traversedPath + "'."); } ctx = ctx[key]; @@ -171,8 +175,8 @@ function compile(nodes) { firstType = node.type; } else { if (node.type !== firstType) { - genError("Cannot add value of type " + node.type + " to array of type " + - firstType + ".", node.line, node.column); + genError(node, "Cannot add value of type " + node.type + " to array of type " + + firstType + "."); } } } diff --git a/lib/parser.js b/lib/parser.js index 69cbd6f..5913917 100644 --- a/lib/parser.js +++ b/lib/parser.js @@ -3768,10 +3768,9 @@ module.exports = (function() { nodes.push(node); } + // TODO(felix9): remove line, column args after grammar change lands function node(type, value, line, column, key) { - var obj = { type: type, value: value, line: line(), column: column() }; - if (key) obj.key = key; - return obj; + return { type: type, value: value, key: key, offset: offset() }; } function convertCodePoint(str, line, col) { diff --git a/src/toml.pegjs b/src/toml.pegjs index 7051707..4f81939 100644 --- a/src/toml.pegjs +++ b/src/toml.pegjs @@ -12,10 +12,9 @@ nodes.push(node); } + // TODO(felix9): remove line, column args after grammar change lands function node(type, value, line, column, key) { - var obj = { type: type, value: value, line: line(), column: column() }; - if (key) obj.key = key; - return obj; + return { type: type, value: value, key: key, offset: offset() }; } function convertCodePoint(str, line, col) {