diffusion
Version:
Diffusion JavaScript client
101 lines (85 loc) • 2.17 kB
JavaScript
/*eslint valid-jsdoc: "off"*/
/**
* Maintain recursive parsing context on a stack.
*/
function Context() {
var ROOT = { length : -1, type : 'root', read : 0 };
var stack = [];
var tail = ROOT;
/**
* @returns {Object} the type of the current context
*/
this.type = function() {
return tail.type;
};
/**
* @returns {Number} how many tokens have been read in this context
*/
this.read = function() {
return tail.read;
};
/**
* @returns {Number} how many tokens are expected by this current context
*/
this.expected = function() {
return tail.length;
};
/**
* Add a new context
*/
this.push = function(type, length) {
length = length === undefined ? -1 : length;
tail = {
length : length,
type : type,
read : 0
};
stack.push(tail);
};
/**
* Pop the current context
*
* @returns the previous tail on the context stack
*/
this.pop = function() {
var prev = stack.pop();
if (stack.length) {
tail = stack[stack.length - 1];
} else {
tail = ROOT;
}
return prev;
};
/**
* Progress through the current context's expected value count
*/
this.next = function() {
if (this.hasRemaining()) {
tail.read++;
} else {
throw new Error('Exceeded expected collection limit');
}
};
/**
* Ends this current context.
*/
this.break = function() {
if (this.acceptsBreakMarker()) {
tail.length = 0;
tail.read = 0;
}
};
/**
* @returns {Number} the expected number of remaining values from the current context.
*/
this.hasRemaining = function() {
return tail.length === -1 ? true : tail.length > tail.read;
};
/**
* @returns {Boolean} whether the current context accepts break marker tokens
*/
this.acceptsBreakMarker = function() {
return tail !== ROOT && tail.length === -1;
};
}
module.exports = Context;