function Position() { this.advance = function(n) { this.absolute += n; this.col += n; } this.newline = function() { this.col = 0; this.line++; } this.copy_from = function(that) { this.absolute = that.absolute; this.col = that.col; this.line = that.line; } this.reset = function() { this.absolute = 0; this.line = 1; this.col = 0; } this.reset(); } function Token(type, text) { this.type = type; this.text = text; this.toString = function() { return "(" + this.type + ", \"" + this.text + "\")"; } } function match_token(string) { var i, m; for (i=1; i= this.length) return new Token("EOF", "EOF"); var match = match_token(this.text.substring(this.pos.absolute), ["COMMENT" , /^WTF[^\n]*/ ], ["SPACE" , /^[ \t]+/ ], ["IDENTIFIER", /^[A-Za-z_][A-Za-z0-9_]*/], ["NUMBER" , /^[0-9]+/ ], ["ARROW" , /^(\<-|-\>)/ ], ["OP" , /^[~\\:@]/ ], ["NEWLINE" , /^\n/ ], ["BRACKET" , /^[\[\]]/ ], ["UNKNOWN" , /^./ ]); if (match) { this.pos.advance(match.text.length); if (match.type == "NEWLINE") this.pos.newline(); else if (match.type == "UNKNOWN") this.error("Token '" + match.text + "' never heard of"); else if (match.type!="SPACE" && match.type!="COMMENT") return match; } else { throw "Ouch!"; } } } this.back = function() { this.pos.copy_from(this.lastpos); } this.enlist = function() { var ls = []; var m; while (m=this.next(), m.type!="EOF") ls.push(m.text); return ls; } this.error = function(msg) { throw "Error at line " + this.lastpos.line + ", column " + this.lastpos.col + ": " + msg; } this.reset = function() { this.lastpos.copy_from(pos); this.pos.reset(); } }