From 597bf15f6293fa672edf54f16156e70f7e23a784 Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Mon, 25 May 2015 18:40:56 -0400 Subject: [PATCH] Respect syntax error offset location --- lib/compiler.js | 2 +- lib/helpers.js | 24 +++++++++++++++++++----- lib/optimiser.js | 2 +- src/helpers.coffee | 20 ++++++++++++++++---- 4 files changed, 37 insertions(+), 11 deletions(-) diff --git a/lib/compiler.js b/lib/compiler.js index d48a9454..7ddd3d90 100644 --- a/lib/compiler.js +++ b/lib/compiler.js @@ -652,7 +652,7 @@ exports.Compiler = function () { Compiler.compile = function (this$) { return function () { var cache$2; - return (cache$2 = new this$).compile.apply(cache$2, [].slice.call(arguments)); + return (cache$2 = new this$()).compile.apply(cache$2, [].slice.call(arguments)); }; }(Compiler); defaultRules = [ diff --git a/lib/helpers.js b/lib/helpers.js index 4471b06c..94c17a79 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -49,16 +49,30 @@ this.humanReadable = humanReadable = function (str) { return str.replace(/\uEFEF/g, '(INDENT)').replace(/\uEFFE/g, '(DEDENT)').replace(/\uEFFF/g, '(TERM)'); }; this.formatParserError = function (input, e) { - var found, message, realColumn, unicode; - realColumn = cleanMarkers(('' + input.split('\n')[e.line - 1] + '\n').slice(0, e.column)).length; + var column, found, line, lines, message, offset, realColumn, unicode; + lines = input.split('\n'); + line = e.line - 1; + column = e.column; + offset = e.offset; + while (offset > 0) { + if (offset > lines[line].length) { + offset -= lines[line].length; + line += 1; + } else { + column += offset; + offset = 0; + } + } + realColumn = cleanMarkers(('' + lines[line] + '\n').slice(0, column)).length; + line += 1; if (!(null != e.found)) - return 'Syntax error on line ' + e.line + ', column ' + realColumn + ': unexpected end of input'; + return 'Syntax error on line ' + line + ', column ' + realColumn + ': unexpected end of input'; found = JSON.stringify(humanReadable(e.found)); found = found.replace(/^"|"$/g, '').replace(/'/g, "\\'").replace(/\\"/g, '"'); unicode = e.found.charCodeAt(0).toString(16).toUpperCase(); unicode = '\\u' + '0000'.slice(unicode.length) + unicode; - message = 'Syntax error on line ' + e.line + ', column ' + realColumn + ": unexpected '" + found + "' (" + unicode + ')'; - return '' + message + '\n' + pointToErrorLocation(input, e.line, realColumn); + message = 'Syntax error on line ' + line + ', column ' + realColumn + ": unexpected '" + found + "' (" + unicode + ')'; + return '' + message + '\n' + pointToErrorLocation(input, line, realColumn); }; this.pointToErrorLocation = pointToErrorLocation = function (source, line, column, numLinesOfContext) { var currentLineOffset, lines, numberedLines, padSize, postLines, preLines, startLine; diff --git a/lib/optimiser.js b/lib/optimiser.js index 874585fa..c25cd58e 100644 --- a/lib/optimiser.js +++ b/lib/optimiser.js @@ -387,7 +387,7 @@ exports.Optimiser = function () { Optimiser.optimise = function (this$) { return function () { var cache$2; - return (cache$2 = new this$).optimise.apply(cache$2, [].slice.call(arguments)); + return (cache$2 = new this$()).optimise.apply(cache$2, [].slice.call(arguments)); }; }(Optimiser); Optimiser.isTruthy = isTruthy; diff --git a/src/helpers.coffee b/src/helpers.coffee index 5498e9d4..26bdcc24 100644 --- a/src/helpers.coffee +++ b/src/helpers.coffee @@ -32,15 +32,27 @@ cleanMarkers = (str) -> str.replace /[\uEFEF\uEFFE\uEFFF]/g, '' ((str.replace /\uEFEF/g, '(INDENT)').replace /\uEFFE/g, '(DEDENT)').replace /\uEFFF/g, '(TERM)' @formatParserError = (input, e) -> - realColumn = (cleanMarkers "#{(input.split '\n')[e.line - 1]}\n"[...e.column]).length + lines = input.split('\n') + line = e.line - 1 # switch to zero-indexed + column = e.column + offset = e.offset + while offset > 0 + if offset > lines[line].length + offset -= lines[line].length + line += 1 + else + column += offset + offset = 0 + realColumn = (cleanMarkers "#{lines[line]}\n"[...column]).length + line += 1 # switch back to one-indexed unless e.found? - return "Syntax error on line #{e.line}, column #{realColumn}: unexpected end of input" + return "Syntax error on line #{line}, column #{realColumn}: unexpected end of input" found = JSON.stringify humanReadable e.found found = ((found.replace /^"|"$/g, '').replace /'/g, '\\\'').replace /\\"/g, '"' unicode = ((e.found.charCodeAt 0).toString 16).toUpperCase() unicode = "\\u#{"0000"[unicode.length..]}#{unicode}" - message = "Syntax error on line #{e.line}, column #{realColumn}: unexpected '#{found}' (#{unicode})" - "#{message}\n#{pointToErrorLocation input, e.line, realColumn}" + message = "Syntax error on line #{line}, column #{realColumn}: unexpected '#{found}' (#{unicode})" + "#{message}\n#{pointToErrorLocation input, line, realColumn}" @pointToErrorLocation = pointToErrorLocation = (source, line, column, numLinesOfContext = 3) -> lines = source.split '\n'