Skip to content

Commit

Permalink
Export getLineAndColumnMessage via ohm.util.
Browse files Browse the repository at this point in the history
  • Loading branch information
pdubroy committed Jun 1, 2015
1 parent 1a67a4a commit d376cf3
Show file tree
Hide file tree
Showing 13 changed files with 476 additions and 362 deletions.
199 changes: 141 additions & 58 deletions dist/ohm.js

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions dist/ohm.min.js

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions src/MatchResult.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
var inherits = require('inherits');

var common = require('./common');
var util = require('./util');

// --------------------------------------------------------------------
// Private stuff
// --------------------------------------------------------------------

// Create a short error message for an error that occurred during matching.
function getShortMatchErrorMessage(pos, source, detail) {
var errorInfo = common.getLineAndColumn(source, pos);
var errorInfo = util.getLineAndColumn(source, pos);
return 'Line ' + errorInfo.lineNum + ', col ' + errorInfo.colNum + ': ' + detail;
}

Expand Down Expand Up @@ -52,7 +53,7 @@ function MatchFailure(state) {
}

var detail = 'Expected ' + this.getExpectedText();
return common.getLineAndColumnMessage(source, this.getPos()) + detail;
return util.getLineAndColumnMessage(source, this.getPos()) + detail;
});
common.defineLazyProperty(this, 'shortMessage', function() {
if (typeof this.state.inputStream.source !== 'string') {
Expand Down
120 changes: 7 additions & 113 deletions src/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,6 @@ var extend = require('util-extend');

// Helpers

function pad(str, len, optChar) {
var ch = optChar || ' ';
if (str.length < len) {
return repeatStr(ch, len - str.length) + str;
}
return str;
}

function repeatStr(str, n) {
return new Array(n + 1).join(str);
}
Expand Down Expand Up @@ -100,110 +92,12 @@ exports.isSyntactic = function(ruleName) {
return ('A' <= firstChar && firstChar <= 'Z');
};

// Return an object with the line and column information for the given
// offset in `str`.
exports.getLineAndColumn = function(str, offset) {
var lineNum = 1;
var colNum = 1;

var currOffset = 0;
var lineStartOffset = 0;

var nextLine = null;
var prevLine = null;
var prevLineStartOffset = -1;

while (currOffset < offset) {
var c = str.charAt(currOffset++);
if (c === '\n') {
lineNum++;
colNum = 1;
prevLineStartOffset = lineStartOffset;
lineStartOffset = currOffset;
} else if (c !== '\r') {
colNum++;
}
}

// Find the end of the target line.
var lineEndOffset = str.indexOf('\n', lineStartOffset);
if (lineEndOffset === -1) {
lineEndOffset = str.length;
} else {
// Get the next line.
var nextLineEndOffset = str.indexOf('\n', lineEndOffset + 1);
nextLine = nextLineEndOffset === -1 ? str.slice(lineEndOffset)
: str.slice(lineEndOffset, nextLineEndOffset);
// Strip leading and trailing EOL char(s).
nextLine = nextLine.replace(/^\r?\n/, '').replace(/\r$/, '');
}

// Get the previous line.
if (prevLineStartOffset >= 0) {
prevLine = str.slice(prevLineStartOffset, lineStartOffset)
.replace(/\r?\n$/, ''); // Strip trailing EOL char(s).
}

// Get the target line, stripping a trailing carriage return if necessary.
var line = str.slice(lineStartOffset, lineEndOffset).replace(/\r$/, '');

return {
lineNum: lineNum,
colNum: colNum,
line: line,
prevLine: prevLine,
nextLine: nextLine
};
};

// Given an array of numbers `arr`, return an array of the numbers as strings,
// right-justified and padded to the same length.
function padNumbersToEqualLength(arr) {
var maxLen = 0;
var strings = arr.map(function(n) {
var str = n.toString();
maxLen = Math.max(maxLen, str.length);
return str;
});
return strings.map(function(s) { return pad(s, maxLen); });
}

// Return a nicely-formatted string describing the line and column for the
// given offset in `str`.
exports.getLineAndColumnMessage = function(str, offset) {
var lineAndCol = exports.getLineAndColumn(str, offset);
var sb = new exports.StringBuffer();
sb.append('Line ' + lineAndCol.lineNum + ', col ' + lineAndCol.colNum + ':\n');

// An array of the previous, current, and next line numbers as strings of equal length.
var lineNumbers = padNumbersToEqualLength([
lineAndCol.prevLine == null ? 0 : lineAndCol.lineNum - 1,
lineAndCol.lineNum,
lineAndCol.nextLine == null ? 0 : lineAndCol.lineNum + 1
]);

// Helper for appending formatting input lines to the buffer.
function appendLine(num, content, prefix) {
sb.append(prefix + lineNumbers[num] + ' | ' + content + '\n');
}

// Include the previous line for context if possible.
if (lineAndCol.prevLine != null) {
appendLine(0, lineAndCol.prevLine, ' ');
}
// Line that the error occurred on.
appendLine(1, lineAndCol.line, '> ');

// Line indicating the column on which the error occurred.
var gutterWidth = 2 + lineNumbers[1].length + 3;
sb.append(repeatStr(' ', gutterWidth - 1 + lineAndCol.colNum));
sb.append('^\n');

// Include the next line for context if possible.
if (lineAndCol.nextLine != null) {
appendLine(2, lineAndCol.nextLine, ' ');
exports.padLeft = function(str, len, optChar) {
var ch = optChar || ' ';
if (str.length < len) {
return repeatStr(ch, len - str.length) + str;
}
return sb.contents();
return str;
};

// StringBuffer
Expand All @@ -229,9 +123,9 @@ exports.escapeChar = function(c, optDelim) {
} else if (charCode < 128) {
return escapeStringFor[charCode];
} else if (128 <= charCode && charCode < 256) {
return '\\x' + pad(charCode.toString(16), 2, '0');
return '\\x' + exports.padLeft(charCode.toString(16), 2, '0');
} else {
return '\\u' + pad(charCode.toString(16), 4, '0');
return '\\u' + exports.padLeft(charCode.toString(16), 4, '0');
}
};

Expand Down
6 changes: 4 additions & 2 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ var Semantics = require('./Semantics');
var UnicodeCategories = require('../third_party/unicode').UnicodeCategories;
var common = require('./common');
var errors = require('./errors');
var util = require('./util');

// --------------------------------------------------------------------
// Private stuff
Expand Down Expand Up @@ -312,7 +313,7 @@ function grammar(source, optNamespace) {
var secondGrammar = ns[grammarNames[1]];
var interval = secondGrammar.definitionInterval;
throw new Error(
common.getLineAndColumnMessage(interval.inputStream.source, interval.startIdx) +
util.getLineAndColumnMessage(interval.inputStream.source, interval.startIdx) +
'Found more than one grammar definition -- use ohm.grammars() instead.');
}
return ns[grammarNames[0]]; // Return the one and only grammar.
Expand Down Expand Up @@ -385,7 +386,8 @@ module.exports = {
grammars: grammars,
grammarFromScriptElement: grammarFromScriptElement,
grammarsFromScriptElements: grammarsFromScriptElements,
makeRecipe: makeRecipe
makeRecipe: makeRecipe,
util: util
};

// Stuff that's only here for bootstrapping, testing, etc.
Expand Down
120 changes: 120 additions & 0 deletions src/util.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
'use strict';

// --------------------------------------------------------------------
// Imports
// --------------------------------------------------------------------

var common = require('./common');

// --------------------------------------------------------------------
// Private stuff
// --------------------------------------------------------------------

// Given an array of numbers `arr`, return an array of the numbers as strings,
// right-justified and padded to the same length.
function padNumbersToEqualLength(arr) {
var maxLen = 0;
var strings = arr.map(function(n) {
var str = n.toString();
maxLen = Math.max(maxLen, str.length);
return str;
});
return strings.map(function(s) { return common.padLeft(s, maxLen); });
}

// --------------------------------------------------------------------
// Exports
// --------------------------------------------------------------------

// Return an object with the line and column information for the given
// offset in `str`.
exports.getLineAndColumn = function(str, offset) {
var lineNum = 1;
var colNum = 1;

var currOffset = 0;
var lineStartOffset = 0;

var nextLine = null;
var prevLine = null;
var prevLineStartOffset = -1;

while (currOffset < offset) {
var c = str.charAt(currOffset++);
if (c === '\n') {
lineNum++;
colNum = 1;
prevLineStartOffset = lineStartOffset;
lineStartOffset = currOffset;
} else if (c !== '\r') {
colNum++;
}
}

// Find the end of the target line.
var lineEndOffset = str.indexOf('\n', lineStartOffset);
if (lineEndOffset === -1) {
lineEndOffset = str.length;
} else {
// Get the next line.
var nextLineEndOffset = str.indexOf('\n', lineEndOffset + 1);
nextLine = nextLineEndOffset === -1 ? str.slice(lineEndOffset)
: str.slice(lineEndOffset, nextLineEndOffset);
// Strip leading and trailing EOL char(s).
nextLine = nextLine.replace(/^\r?\n/, '').replace(/\r$/, '');
}

// Get the previous line.
if (prevLineStartOffset >= 0) {
prevLine = str.slice(prevLineStartOffset, lineStartOffset)
.replace(/\r?\n$/, ''); // Strip trailing EOL char(s).
}

// Get the target line, stripping a trailing carriage return if necessary.
var line = str.slice(lineStartOffset, lineEndOffset).replace(/\r$/, '');

return {
lineNum: lineNum,
colNum: colNum,
line: line,
prevLine: prevLine,
nextLine: nextLine
};
};

// Return a nicely-formatted string describing the line and column for the
// given offset in `str`.
exports.getLineAndColumnMessage = function(str, offset) {
var lineAndCol = exports.getLineAndColumn(str, offset);
var sb = new common.StringBuffer();
sb.append('Line ' + lineAndCol.lineNum + ', col ' + lineAndCol.colNum + ':\n');

// An array of the previous, current, and next line numbers as strings of equal length.
var lineNumbers = padNumbersToEqualLength([
lineAndCol.prevLine == null ? 0 : lineAndCol.lineNum - 1,
lineAndCol.lineNum,
lineAndCol.nextLine == null ? 0 : lineAndCol.lineNum + 1
]);

// Helper for appending formatting input lines to the buffer.
function appendLine(num, content, prefix) {
sb.append(prefix + lineNumbers[num] + ' | ' + content + '\n');
}

// Include the previous line for context if possible.
if (lineAndCol.prevLine != null) {
appendLine(0, lineAndCol.prevLine, ' ');
}
// Line that the error occurred on.
appendLine(1, lineAndCol.line, '> ');

// Line indicating the column on which the error occurred.
var gutterWidth = 2 + lineNumbers[1].length + 3;
sb.append(common.padLeft('^', gutterWidth + lineAndCol.colNum) + '\n');

// Include the next line for context if possible.
if (lineAndCol.nextLine != null) {
appendLine(2, lineAndCol.nextLine, ' ');
}
return sb.contents();
};
Loading

0 comments on commit d376cf3

Please sign in to comment.