Skip to main content
Module

x/ohm_js/src/common.js

A library and language for building parsers, interpreters, compilers, etc.
Go to Latest
File
'use strict';
// --------------------------------------------------------------------// Private Stuff// --------------------------------------------------------------------
// Helpers
const escapeStringFor = {};for (let c = 0; c < 128; c++) { escapeStringFor[c] = String.fromCharCode(c);}escapeStringFor["'".charCodeAt(0)] = "\\'";escapeStringFor['"'.charCodeAt(0)] = '\\"';escapeStringFor['\\'.charCodeAt(0)] = '\\\\';escapeStringFor['\b'.charCodeAt(0)] = '\\b';escapeStringFor['\f'.charCodeAt(0)] = '\\f';escapeStringFor['\n'.charCodeAt(0)] = '\\n';escapeStringFor['\r'.charCodeAt(0)] = '\\r';escapeStringFor['\t'.charCodeAt(0)] = '\\t';escapeStringFor['\u000b'.charCodeAt(0)] = '\\v';
// --------------------------------------------------------------------// Exports// --------------------------------------------------------------------
exports.abstract = function(optMethodName) { const methodName = optMethodName || ''; return function() { throw new Error( 'this method ' + methodName + ' is abstract! ' + '(it has no implementation in class ' + this.constructor.name + ')' ); };};
exports.assert = function(cond, message) { if (!cond) { throw new Error(message || 'Assertion failed'); }};
// Define a lazily-computed, non-enumerable property named `propName`// on the object `obj`. `getterFn` will be called to compute the value the// first time the property is accessed.exports.defineLazyProperty = function(obj, propName, getterFn) { let memo; Object.defineProperty(obj, propName, { get() { if (!memo) { memo = getterFn.call(this); } return memo; }, });};
exports.clone = function(obj) { if (obj) { return Object.assign({}, obj); } return obj;};
exports.repeatFn = function(fn, n) { const arr = []; while (n-- > 0) { arr.push(fn()); } return arr;};
exports.repeatStr = function(str, n) { return new Array(n + 1).join(str);};
exports.repeat = function(x, n) { return exports.repeatFn(() => x, n);};
exports.getDuplicates = function(array) { const duplicates = []; for (let idx = 0; idx < array.length; idx++) { const x = array[idx]; if (array.lastIndexOf(x) !== idx && duplicates.indexOf(x) < 0) { duplicates.push(x); } } return duplicates;};
exports.copyWithoutDuplicates = function(array) { const noDuplicates = []; array.forEach(entry => { if (noDuplicates.indexOf(entry) < 0) { noDuplicates.push(entry); } }); return noDuplicates;};
exports.isSyntactic = function(ruleName) { const firstChar = ruleName[0]; return firstChar === firstChar.toUpperCase();};
exports.isLexical = function(ruleName) { return !exports.isSyntactic(ruleName);};
exports.padLeft = function(str, len, optChar) { const ch = optChar || ' '; if (str.length < len) { return exports.repeatStr(ch, len - str.length) + str; } return str;};
// StringBuffer
exports.StringBuffer = function() { this.strings = [];};
exports.StringBuffer.prototype.append = function(str) { this.strings.push(str);};
exports.StringBuffer.prototype.contents = function() { return this.strings.join('');};
const escapeUnicode = str => String.fromCodePoint(parseInt(str, 16));
exports.unescapeCodePoint = function(s) { if (s.charAt(0) === '\\') { switch (s.charAt(1)) { case 'b': return '\b'; case 'f': return '\f'; case 'n': return '\n'; case 'r': return '\r'; case 't': return '\t'; case 'v': return '\v'; case 'x': return escapeUnicode(s.slice(2, 4)); case 'u': return s.charAt(2) === '{' ? escapeUnicode(s.slice(3, -1)) : escapeUnicode(s.slice(2, 6)); default: return s.charAt(1); } } else { return s; }};
// Helper for producing a description of an unknown object in a safe way.// Especially useful for error messages where an unexpected type of object was encountered.exports.unexpectedObjToString = function(obj) { if (obj == null) { return String(obj); } const baseToString = Object.prototype.toString.call(obj); try { let typeName; if (obj.constructor && obj.constructor.name) { typeName = obj.constructor.name; } else if (baseToString.indexOf('[object ') === 0) { typeName = baseToString.slice(8, -1); // Extract e.g. "Array" from "[object Array]". } else { typeName = typeof obj; } return typeName + ': ' + JSON.stringify(String(obj)); } catch (e) { return baseToString; }};