},{}],24:[function(require,module,exports){
module.exports = StringReader;
* Convenient way to read through strings.
* @namespace parserlib.util
* @param {String} text The text to read.
function StringReader(text) {
* The input text with line endings normalized.
this._input = text.replace(/(\r\n?|\n)/g, "\n");
* The row for the character to be read next.
* The column for the character to be read next.
* The index of the character in the input to be read next.
StringReader.prototype = {
constructor: StringReader,
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
* Returns the column of the character to be read next.
* @return {int} The column of the character to be read next.
* Returns the row of the character to be read next.
* @return {int} The row of the character to be read next.
* Determines if you're at the end of the input.
* @return {Boolean} True if there's no more input, false otherwise.
return this._cursor === this._input.length;
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
* Reads the next character without advancing the cursor.
* @param {int} count How many characters to look ahead (default is 1).
* @return {String} The next character or null if there is no next character.
count = typeof count === "undefined" ? 1 : count;
// if we're not at the end of the input...
if (this._cursor < this._input.length) {
// get character and increment cursor and column
c = this._input.charAt(this._cursor + count - 1);
* Reads the next character from the input and adjusts the row and column
* @return {String} The next character or null if there is no next character.
// if we're not at the end of the input...
if (this._cursor < this._input.length) {
// if the last character was a newline, increment row count
// and reset column count
if (this._input.charAt(this._cursor) === "\n") {
// get character and increment cursor and column
c = this._input.charAt(this._cursor++);
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
* Saves the current location so it can be returned to later.
this._cursor = this._bookmark.cursor;
this._line = this._bookmark.line;
this._col = this._bookmark.col;
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
* Reads up to and including the given string. Throws an error if that
* @param {String} pattern The string to read.
* @return {String} The string when it is found.
* @throws Error when the string pattern is not found.
readTo: function(pattern) {
* First, buffer must be the same length as the pattern.
* Then, buffer must end with the pattern or else reach the
while (buffer.length < pattern.length || buffer.lastIndexOf(pattern) !== buffer.length - pattern.length) {
throw new Error("Expected \"" + pattern + "\" at line " + this._line + ", col " + this._col + ".");
* Reads characters while each character causes the given
* filter function to return true. The function is passed
* in each character and either returns true to continue
* reading or false to stop.
* @param {Function} filter The function to read on each character.
* @return {String} The string made up of all characters that passed the
readWhile: function(filter) {
while (c !== null && filter(c)) {
* Reads characters that match either text or a regular expression and
* returns those characters. If a match is found, the row and column
* are adjusted; if no match is found, the reader's state is unchanged.
* reading or false to stop.
* @param {String|RegExp} matcher If a string, then the literal string
* value is searched for. If a regular expression, then any string
* matching the pattern is search for.
* @return {String} The string made up of all characters that matched or
* null if there was no match.
readMatch: function(matcher) {
var source = this._input.substring(this._cursor),
// if it's a string, just do a straight match
if (typeof matcher === "string") {
if (source.slice(0, matcher.length) === matcher) {
value = this.readCount(matcher.length);
} else if (matcher instanceof RegExp) {
if (matcher.test(source)) {
value = this.readCount(RegExp.lastMatch.length);
* Reads a given number of characters. If the end of the input is reached,
* it reads only the remaining characters and does not throw an error.
* @param {int} count The number of characters to read.
* @return {String} The string made up the read characters.
readCount: function(count) {
},{}],25:[function(require,module,exports){
module.exports = SyntaxError;
* Type to use when a syntax error occurs.
* @namespace parserlib.util
* @param {String} message The error message.
* @param {int} line The line at which the error occurred.
* @param {int} col The column at which the error occurred.
function SyntaxError(message, line, col) {
this.name = this.constructor.name;
* The column at which the error occurred.
* The line at which the error occurred.
* The text representation of the unit.
SyntaxError.prototype = Object.create(Error.prototype); // jshint ignore:line
SyntaxError.prototype.constructor = SyntaxError; // jshint ignore:line
},{}],26:[function(require,module,exports){
module.exports = SyntaxUnit;
* Base type to represent a single syntactic unit.
* @namespace parserlib.util
* @param {String} text The text of the unit.
* @param {int} line The line of text on which the unit resides.
* @param {int} col The column of text on which the unit resides.
function SyntaxUnit(text, line, col, type) {
* The column of text on which the unit resides.
* The line of text on which the unit resides.
* The text representation of the unit.
* The type of syntax unit.
* Create a new syntax unit based solely on the given token.
* Convenience method for creating a new syntax unit when
* it represents a single token instead of multiple.
* @param {Object} token The token object to represent.
* @return {parserlib.util.SyntaxUnit} The object representing the token.
SyntaxUnit.fromToken = function(token) {
return new SyntaxUnit(token.value, token.startLine, token.startCol);
* Returns the text representation of the unit.
* @return {String} The text representation of the unit.
* Returns the text representation of the unit.
* @return {String} The text representation of the unit.
},{}],27:[function(require,module,exports){
module.exports = TokenStreamBase;
var StringReader = require("./StringReader");
var SyntaxError = require("./SyntaxError");
* Generic TokenStream providing base functionality.
* @namespace parserlib.util
* @param {String|StringReader} input The text to tokenize or a reader from
* which to read the input.
function TokenStreamBase(input, tokenData) {
* The string reader for easy access to the text.
this._reader = new StringReader(input ? input.toString() : "");
* Token object for the last consumed token.
* The array of token information.
this._tokenData = tokenData;
* Lookahead token buffer.
* Lookahead token buffer index.
* Accepts an array of token information and outputs
* an array of token data containing key-value mappings
* and matching functions that the TokenStream needs.
* @param {Array} tokens An array of token descriptors.
* @return {Array} An array of processed token data.
* @method createTokenData
TokenStreamBase.createTokenData = function(tokens) {
typeMap = Object.create(null),
tokenData = tokens.concat([]),
len = tokenData.length+1;
tokenData.unshift({ name:"EOF" });
nameMap.push(tokenData[i].name);
tokenData[tokenData[i].name] = i;
typeMap[tokenData[i].text] = i;
tokenData.name = function(tt) {
tokenData.type = function(c) {