133 lines
2.7 KiB
JavaScript
133 lines
2.7 KiB
JavaScript
|
if (typeof JSDOC == "undefined") JSDOC = {};
|
||
|
|
||
|
/**
|
||
|
@constructor
|
||
|
*/
|
||
|
JSDOC.TokenStream = function(tokens) {
|
||
|
this.tokens = (tokens || []);
|
||
|
this.rewind();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
@constructor
|
||
|
@private
|
||
|
*/
|
||
|
function VoidToken(/**String*/type) {
|
||
|
this.toString = function() {return "<VOID type=\""+type+"\">"};
|
||
|
this.is = function(){return false;}
|
||
|
}
|
||
|
|
||
|
JSDOC.TokenStream.prototype.rewind = function() {
|
||
|
this.cursor = -1;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
@type JSDOC.Token
|
||
|
*/
|
||
|
JSDOC.TokenStream.prototype.look = function(/**Number*/n, /**Boolean*/considerWhitespace) {
|
||
|
if (typeof n == "undefined") n = 0;
|
||
|
|
||
|
if (considerWhitespace == true) {
|
||
|
if (this.cursor+n < 0 || this.cursor+n > this.tokens.length) return {};
|
||
|
return this.tokens[this.cursor+n];
|
||
|
}
|
||
|
else {
|
||
|
var count = 0;
|
||
|
var i = this.cursor;
|
||
|
|
||
|
while (true) {
|
||
|
if (i < 0) return new JSDOC.Token("", "VOID", "START_OF_STREAM");
|
||
|
else if (i > this.tokens.length) return new JSDOC.Token("", "VOID", "END_OF_STREAM");
|
||
|
|
||
|
if (i != this.cursor && (this.tokens[i] === undefined || this.tokens[i].is("WHIT"))) {
|
||
|
if (n < 0) i--; else i++;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (count == Math.abs(n)) {
|
||
|
return this.tokens[i];
|
||
|
}
|
||
|
count++;
|
||
|
(n < 0)? i-- : i++;
|
||
|
}
|
||
|
|
||
|
return new JSDOC.Token("", "VOID", "STREAM_ERROR"); // because null isn't an object and caller always expects an object
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
@type JSDOC.Token|JSDOC.Token[]
|
||
|
*/
|
||
|
JSDOC.TokenStream.prototype.next = function(/**Number*/howMany) {
|
||
|
if (typeof howMany == "undefined") howMany = 1;
|
||
|
if (howMany < 1) return null;
|
||
|
var got = [];
|
||
|
|
||
|
for (var i = 1; i <= howMany; i++) {
|
||
|
if (this.cursor+i >= this.tokens.length) {
|
||
|
return null;
|
||
|
}
|
||
|
got.push(this.tokens[this.cursor+i]);
|
||
|
}
|
||
|
this.cursor += howMany;
|
||
|
|
||
|
if (howMany == 1) {
|
||
|
return got[0];
|
||
|
}
|
||
|
else return got;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
@type JSDOC.Token[]
|
||
|
*/
|
||
|
JSDOC.TokenStream.prototype.balance = function(/**String*/start, /**String*/stop) {
|
||
|
if (!stop) stop = JSDOC.Lang.matching(start);
|
||
|
|
||
|
var depth = 0;
|
||
|
var got = [];
|
||
|
var started = false;
|
||
|
|
||
|
while ((token = this.look())) {
|
||
|
if (token.is(start)) {
|
||
|
depth++;
|
||
|
started = true;
|
||
|
}
|
||
|
|
||
|
if (started) {
|
||
|
got.push(token);
|
||
|
}
|
||
|
|
||
|
if (token.is(stop)) {
|
||
|
depth--;
|
||
|
if (depth == 0) return got;
|
||
|
}
|
||
|
if (!this.next()) break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
JSDOC.TokenStream.prototype.getMatchingToken = function(/**String*/start, /**String*/stop) {
|
||
|
var depth = 0;
|
||
|
var cursor = this.cursor;
|
||
|
|
||
|
if (!start) {
|
||
|
start = JSDOC.Lang.matching(stop);
|
||
|
depth = 1;
|
||
|
}
|
||
|
if (!stop) stop = JSDOC.Lang.matching(start);
|
||
|
|
||
|
while ((token = this.tokens[cursor])) {
|
||
|
if (token.is(start)) {
|
||
|
depth++;
|
||
|
}
|
||
|
|
||
|
if (token.is(stop) && cursor) {
|
||
|
depth--;
|
||
|
if (depth == 0) return this.tokens[cursor];
|
||
|
}
|
||
|
cursor++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
JSDOC.TokenStream.prototype.insertAhead = function(/**JSDOC.Token*/token) {
|
||
|
this.tokens.splice(this.cursor+1, 0, token);
|
||
|
}
|