- Filters will highlight matching items with the specified colour
-
- Note: If multiple filters match an item, it will be highlighted with the average colour
-
- New: You can now filter based on FloatDB ranks and item price!
-
- Examples:
-
-
float < 0.3
-
-
Matches items with floats less than 0.3
-
-
float >= 0.112 and float < 0.2
-
-
Matches items with floats greater than or equal to 0.112 and less than 0.2
-
-
float < 0.02 and price < 12.30
-
-
Matches items with floats less than 0.02 and a price of 12.30 or less in your logged-in account currency
-
Note: Price only works when you're logged in to ensure the proper currency
-
-
phase == "Ruby" or phase == "1"
-
-
Matches items with a doppler phase 1 or Ruby
-
Equivalent to phase in ("Ruby", "1")
-
-
float == 0.2 or (seed > 500 and float < 0.15)
-
-
Matches items with floats of 0.2 or paint seeds greater than 500 and floats less than 0.15
-
-
low_rank <= 500
-
-
Matches items with floats ranked in the top 500 lowest for this skin on FloatDB
-
-
match(float, "7355608") >= 1
-
-
Matches items with floats that contain at least one match of the CS bomb code
-
Example Match: 0.234327355608454
-
-
percentile(90)
-
-
Matches items with a float better than 90% of items of this type
-
-
percentileRange(0, 10)
-
-
Matches items with a float within the percentile range 0-10%
-
This matches the worst 10% of floats of items of this type
-
-
-
- Variables
-
-
float
-
-
The float value of the item
-
-
seed
-
-
The paint seed of the item
-
-
low_rank
-
-
If the item is in the top 1000 lowest float for this skin and category (normal, stattrak, souvenir), this is the FloatDB rank
-
-
high_rank
-
-
If the item is in the top 1000 highest float for this skin and category (normal, stattrak, souvenir), this is the FloatDB rank
-
-
price
-
-
Price of the item in your currency in decimal format (ex. 18.43), includes fees
-
Note: Price only works when you're logged in to ensure the proper currency
-
-
phase
-
-
Phase of the item if it's a doppler, empty otherwise
-
Possible values are "1", "2", "3", "4", "Ruby", "Sapphire", "Black Pearl", "Emerald"
-
-
minfloat
-
-
The minimum float the skin can have (regardless of wear)
-
-
maxfloat
-
-
The maximum float the skin can have (regardless of wear)
-
-
-
- Functions:
-
-
match(x, regex)
-
-
Performs a regex match on 'x' and returns the amount of matches
-
-
percentile(rank)
-
-
Returns true if the skin's float is in the given percentile, lower floats are considered "better"
-
This takes into account the range of the wear and specific per-skin range
-
Note: This assumes that floats are distributed evenly
-
-
percentileRange(minRank, maxRank)
-
-
Returns true if the skin's float is in the given percentile range
-
This takes into account the range of the wear and specific per-skin range
-
Note: This assumes that floats are distributed evenly
-
-
abs(x)
-
-
Absolute value
-
-
ceil(x)
-
-
Round floating point up
-
-
floor(x)
-
-
Round floating point down
-
-
log(x)
-
-
Natural logarithm
-
-
max(a, b, c...)
-
-
Max value (variable length of args)
-
-
min(a, b, c...)
-
-
Min value (variable length of args)
-
-
random()
-
-
Random floating point from 0.0 to 1.0
-
-
round(x)
-
-
Round floating point
-
-
sqrt(x)
-
-
Square root
-
-
- `;
-
- filterdiv.appendChild(helpdiv);
- }
- }
-
- async addFilterUI(parent) {
- let filterdiv = document.createElement('div');
- filterdiv.id = 'floatFilter';
- parent.appendChild(filterdiv);
-
- // Add separator
- let hr = document.createElement('hr');
- filterdiv.appendChild(hr);
-
- // Adds filters div
- let filtersdiv = document.createElement('div');
- filtersdiv.id = 'floatFilters';
- filterdiv.appendChild(filtersdiv);
-
- // Adds colour picker
- let colourDiv = document.createElement('input');
- colourDiv.id = 'floatFilterColour';
- colourDiv.type = 'color';
- colourDiv.value = '#354908';
- colourDiv.style.float = 'left';
- colourDiv.style.marginTop = '2px';
- filterdiv.appendChild(colourDiv);
-
- // Add new filter input box
- let input = document.createElement('input');
- input.id = 'float_expression_filter';
- input.classList.add('filter_search_box');
- input.placeholder = 'Add Highlight Filter';
- input.style.width = '350px';
- input.style.marginLeft = '10px';
- input.addEventListener('keyup', e => this.filterKeyPress(e));
- filterdiv.appendChild(input);
-
- // Add filter help link
- let helpText = document.createElement('a');
- helpText.innerText = 'ⓘ';
- helpText.style.fontSize = '18px';
- helpText.title = 'Filter Help';
- helpText.style.marginLeft = '5px';
- helpText.href = 'javascript:void(0)';
- helpText.addEventListener('click', e => this.onHelpClick(e));
- filterdiv.appendChild(helpText);
-
- // Add compile status indicator
- let status = document.createElement('div');
- status.id = 'compileStatus';
- filterdiv.appendChild(status);
-
- // Add new filter btn
- let addFilterBtn = createButton('Add Filter', 'green');
- addFilterBtn.addEventListener('click', e => this.addFilter());
- addFilterBtn.id = 'addFloatFilter';
- addFilterBtn.style.display = 'none';
- addFilterBtn.style.marginLeft = '10px';
-
- filterdiv.appendChild(addFilterBtn);
-
- // Compile error div
- let compileError = document.createElement('div');
- compileError.id = 'compileError';
- filterdiv.appendChild(compileError);
-
- const globalFilters = await this.getGlobalFilters();
- const localFilters = await this.getItemFilters();
-
- const allFilters = globalFilters.concat(localFilters);
-
- for (let filter of allFilters) {
- let newFilter = new Filter(filter.expression, filter.colour, !!filter.isGlobal, this);
- this.filters.push(newFilter);
- newFilter.addToUI();
- }
-
- this.filtersLoaded = true;
- for (const resolve of this.waitForFilters) {
- resolve();
- }
- }
-
- filterKeyPress() {
- if (this.expressionTimer) clearTimeout(this.expressionTimer);
-
- this.expressionTimer = setTimeout(() => {
- let input = document.querySelector('#float_expression_filter');
- let compileError = document.querySelector('#compileError');
- let status = document.querySelector('#compileStatus');
- let addFilterBtn = document.querySelector('#addFloatFilter');
-
- let expression = input.value;
-
- // try to compile the expression
- try {
- this.tryCompile(expression);
- status.setAttribute('error', 'false');
- status.innerText = '✓';
- compileError.innerText = '';
- addFilterBtn.style.display = '';
- } catch (e) {
- if (expression === '') {
- status.innerText = '';
- compileError.innerText = '';
- } else {
- status.setAttribute('error', 'true');
- compileError.innerText = e.message;
- }
- addFilterBtn.style.display = 'none';
- }
- }, 250);
- }
-
- getSaveKey() {
- let itemName = document.querySelector('.market_listing_nav a:nth-child(2)');
-
- if (itemName) return itemName.innerText + '_expressions';
- }
-
- getItemFilters() {
- return new Promise((resolve, reject) => {
- let key = this.getSaveKey();
-
- if (!key) cb([]);
-
- let syncFilters = {};
- syncFilters[key] = [];
-
- let storageType = chrome.storage.sync;
- if (!storageType) storageType = chrome.storage.local;
-
- storageType.get(syncFilters, items => {
- resolve(items[key]);
- });
- });
- }
-
- getGlobalFilters() {
- return new Promise((resolve, reject) => {
- let syncFilters = {};
- syncFilters['global'] = [];
-
- let storageType = chrome.storage.sync;
- if (!storageType) storageType = chrome.storage.local;
-
- storageType.get(syncFilters, items => {
- resolve(items['global']);
- });
- });
- }
-
- /**
- * Ensures we don't hit MAX_WRITE_OPERATIONS_PER_MINUTE
- */
- saveFilters() {
- clearTimeout(this.saveTimeout);
-
- this.saveTimeout = setTimeout(() => this._saveFilters(), 500);
- }
-
- _saveFilters() {
- let key = this.getSaveKey();
-
- if (!key) return;
-
- let syncFilters = {};
-
- const pureFilters = this.filters.map(f => ({
- expression: f.expression,
- colour: f.colour,
- isGlobal: f.isGlobal
- }));
- const localFilters = pureFilters.filter(f => !f.isGlobal);
- const globalFilters = pureFilters.filter(f => f.isGlobal);
-
- syncFilters['global'] = globalFilters;
- syncFilters[key] = localFilters;
-
- let storageType = chrome.storage.sync;
- if (!storageType) storageType = chrome.storage.local;
-
- if (localFilters.length === 0) {
- storageType.remove(key);
- delete syncFilters[key];
- }
-
- storageType.set(syncFilters, () => {
- if (chrome.runtime.lastError) {
- alert(
- 'Error occurred while saving, you may have to remove some filters and try again\n' +
- chrome.runtime.lastError.toString()
- );
- }
- });
-
- // update UI
- removeAllItemsHtml();
- }
-}
diff --git a/lib/filtrex.js b/lib/filtrex.js
deleted file mode 100644
index d9660db7..00000000
--- a/lib/filtrex.js
+++ /dev/null
@@ -1,3556 +0,0 @@
-/**
- * Filtrex provides compileExpression() to compile user expressions to JavaScript.
- *
- * See https://github.com/joewalnes/filtrex for tutorial, reference and examples.
- * MIT License.
- *
- * Includes Jison by Zachary Carter. See http://jison.org/
- *
- * -Joe Walnes
- */
-function compileExpression(expression, validVars) {
- var functions = {
- abs: Math.abs,
- ceil: Math.ceil,
- floor: Math.floor,
- log: Math.log,
- max: Math.max,
- min: Math.min,
- random: Math.random,
- round: Math.round,
- sqrt: Math.sqrt,
- };
- if (!compileExpression.parser) {
- // Building the original parser is the heaviest part. Do it
- // once and cache the result in our own function.
- compileExpression.parser = filtrexParser();
- }
- var tree = compileExpression.parser.parse(expression);
-
- var js = [];
- js.push('return ');
- function toJs(node) {
- if (Array.isArray(node)) {
- node.forEach(toJs);
- } else {
- js.push(node);
- }
- }
- tree.forEach(toJs);
- js.push(';');
-
- js = js.join('');
-
- // check if each var is proper in the js
- if (validVars) {
- let reg = /data\[\"(.+?)\"\]/g;
- let match = reg.exec(js);
-
- while (match !== null) {
- let dataVar = match[1];
-
- if (validVars.indexOf(dataVar) === -1) {
- throw new Error(`'${dataVar}' is an improper variable name`);
- }
-
- match = reg.exec(js);
- }
- }
-
- function unknown(funcName) {
- throw 'Unknown function: ' + funcName + '()';
- }
-
- function prop(obj, name) {
- return Object.prototype.hasOwnProperty.call(obj||{}, name) ? obj[name] : undefined;
- }
-
- var func = new Function('functions', 'data', 'unknown', 'prop', js);
-
- return function(data, extraFunctions) {
- // Modification to not require us to compile a new expression every time
- if (extraFunctions) {
- for (var name in extraFunctions) {
- if (extraFunctions.hasOwnProperty(name)) {
- functions[name] = extraFunctions[name];
- }
- }
- }
-
- return func(functions, data, unknown, prop);
- };
-}
-
-function filtrexParser() {
-
- // Language parser powered by Jison ,
- // which is a pure JavaScript implementation of
- // Bison .
-
- var Jison = require('jison'),
- bnf = require('jison/bnf');
-
- function code(args, skipParentheses) {
- var argsJs = args.map(function(a) {
- return typeof(a) == 'number' ? ('$' + a) : JSON.stringify(a);
- }).join(',');
-
- return skipParentheses
- ? '$$ = [' + argsJs + '];'
- : '$$ = ["(", ' + argsJs + ', ")"];';
- }
-
- var grammar = {
- // Lexical tokens
- lex: {
- rules: [
- ['\\*', 'return "*";'],
- ['\\/', 'return "/";'],
- ['-' , 'return "-";'],
- ['\\+', 'return "+";'],
- ['\\^', 'return "^";'],
- ['\\%', 'return "%";'],
- ['\\(', 'return "(";'],
- ['\\)', 'return ")";'],
- ['\\,', 'return ",";'],
- ['==', 'return "==";'],
- ['\\!=', 'return "!=";'],
- ['\\~=', 'return "~=";'],
- ['>=', 'return ">=";'],
- ['<=', 'return "<=";'],
- ['<', 'return "<";'],
- ['>', 'return ">";'],
- ['\\?', 'return "?";'],
- ['\\:', 'return ":";'],
- ['and[^\\w]', 'return "and";'],
- ['or[^\\w]' , 'return "or";'],
- ['not[^\\w]', 'return "not";'],
- ['in[^\\w]', 'return "in";'],
-
- ['\\s+', ''], // skip whitespace
- ['[0-9]+(?:\\.[0-9]+)?\\b', 'return "NUMBER";'], // 212.321
-
- ['[a-zA-Z][\\.a-zA-Z0-9_]*',
- `yytext = JSON.stringify(yytext);
- return "SYMBOL";`
- ], // some.Symbol22
-
- [`'(?:[^\'])*'`,
- `yytext = JSON.stringify(
- yytext.substr(1, yyleng-2)
- );
- return "SYMBOL";`
- ], // 'some-symbol'
-
- ['"(?:[^"])*"',
- `yytext = JSON.stringify(
- yytext.substr(1, yyleng-2)
- );
- return "STRING";`
- ], // "foo"
-
- // End
- ['$', 'return "EOF";'],
- ]
- },
- // Operator precedence - lowest precedence first.
- // See http://www.gnu.org/software/bison/manual/html_node/Precedence.html
- // for a good explanation of how it works in Bison (and hence, Jison).
- // Different languages have different rules, but this seems a good starting
- // point: http://en.wikipedia.org/wiki/Order_of_operations#Programming_languages
- operators: [
- ['left', '?', ':'],
- ['left', 'or'],
- ['left', 'and'],
- ['left', 'in'],
- ['left', '==', '!=', '~='],
- ['left', '<', '<=', '>', '>='],
- ['left', '+', '-'],
- ['left', '*', '/', '%'],
- ['left', '^'],
- ['left', 'not'],
- ['left', 'UMINUS'],
- ],
- // Grammar
- bnf: {
- expressions: [ // Entry point
- ['e EOF', 'return $1;']
- ],
- e: [
- ['e + e' , code([1, '+', 3])],
- ['e - e' , code([1, '-', 3])],
- ['e * e' , code([1, '*', 3])],
- ['e / e' , code([1, '/', 3])],
- ['e % e' , code([1, '%', 3])],
- ['e ^ e' , code(['Math.pow(', 1, ',', 3, ')'])],
- ['- e' , code(['-', 2]), {prec: 'UMINUS'}],
- ['e and e', code(['Number(', 1, '&&', 3, ')'])],
- ['e or e' , code(['Number(', 1, '||', 3, ')'])],
- ['not e' , code(['Number(!', 2, ')'])],
- ['e == e' , code(['Number(', 1, '==', 3, ')'])],
- ['e != e' , code(['Number(', 1, '!=', 3, ')'])],
- ['e ~= e' , code(['RegExp(', 3, ').test(', 1, ')'])],
- ['e < e' , code(['Number(', 1, '<' , 3, ')'])],
- ['e <= e' , code(['Number(', 1, '<=', 3, ')'])],
- ['e > e' , code(['Number(', 1, '> ', 3, ')'])],
- ['e >= e' , code(['Number(', 1, '>=', 3, ')'])],
- ['e ? e : e', code([1, '?', 3, ':', 5])],
- ['( e )' , code([2])],
- ['NUMBER' , code([1])],
- ['STRING' , code([1])],
- ['SYMBOL' , code(['prop(data, ', 1, ')'])],
- ['SYMBOL ( )', code(['(functions.hasOwnProperty(', 1, ') ? functions[', 1, ']() : unknown(', 1, '))'])],
- ['SYMBOL ( argsList )', code(['(functions.hasOwnProperty(', 1, ') ? functions[', 1, '](', 3, ') : unknown(', 1, '))'])],
- ['e in ( inSet )', code(['(function(o) { return ', 4, '; })(', 1, ')'])],
- ['e not in ( inSet )', code(['!(function(o) { return ', 5, '; })(', 1, ')'])],
- ],
- argsList: [
- ['e', code([1], true)],
- ['argsList , e', code([1, ',', 3], true)],
- ],
- inSet: [
- ['e', code(['o ==', 1], true)],
- ['inSet , e', code([1, '|| o ==', 3], true)],
- ],
- }
- };
- return new Jison.Parser(grammar);
-}
-
-// ---------------------------------------------------
-// Jison will be appended after this point by Makefile
-// ---------------------------------------------------
-var require = (function() {
-var require = (function () {
- var modules = {};
- var factories = {};
- var r = function(id) {
- if (!modules[id]) {
- //console.log(id);
- modules[id] = {};
- factories[id](r, modules[id], { id : id });
- }
- return modules[id];
- };
- r.def = function(id, params) {
- //console.log('def', id);
- factories[id] = params.factory;
- };
- return r;
-})()
-require.def("jison",{factory:function(require,exports,module){
-// Jison, an LR(0), SLR(1), LARL(1), LR(1) Parser Generator
-// Zachary Carter
-// MIT X Licensed
-
-var typal = require("jison/util/typal").typal,
- Set = require("jison/util/set").Set,
- RegExpLexer = require("jison/lexer").RegExpLexer;
-
-var Jison = exports.Jison = exports;
-
-// detect prints
-Jison.print = function() { }
-/*
-if (typeof console !== 'undefined' && console.log) {
- Jison.print = console.log;
- Jison.print = function print () {};
-} else if (typeof puts !== 'undefined') {
- Jison.print = function print () { puts([].join.call(arguments, ' ')); };
-} else if (typeof print !== 'undefined') {
- Jison.print = print;
-} else {
- Jison.print = function print () {};
-}
-*/
-Jison.Parser = (function () {
-
-// iterator utility
-function each (obj, func) {
- if (obj.forEach) {
- obj.forEach(func);
- } else {
- var p;
- for (p in obj) {
- if (obj.hasOwnProperty(p)) {
- func.call(obj, obj[p], p, obj);
- }
- }
- }
-}
-
-var Nonterminal = typal.construct({
- constructor: function Nonterminal (symbol) {
- this.symbol = symbol;
- this.productions = new Set();
- this.first = [];
- this.follows = [];
- this.nullable = false;
- },
- toString: function Nonterminal_toString () {
- var str = this.symbol+"\n";
- str += (this.nullable ? 'nullable' : 'not nullable');
- str += "\nFirsts: "+this.first.join(', ');
- str += "\nFollows: "+this.first.join(', ');
- str += "\nProductions:\n "+this.productions.join('\n ');
-
- return str;
- }
-});
-
-var Production = typal.construct({
- constructor: function Production (symbol, handle, id) {
- this.symbol = symbol;
- this.handle = handle;
- this.nullable = false;
- this.id = id;
- this.first = [];
- this.precedence = 0;
- },
- toString: function Production_toString () {
- return this.symbol+" -> "+this.handle.join(' ');
- }
-});
-
-var generator = typal.beget();
-
-generator.constructor = function Jison_Generator (grammar, opt) {
- if (typeof grammar === 'string') {
- grammar = require("jison/bnf").parse(grammar);
- }
-
- var options = typal.mix.call({}, grammar.options, opt);
- this.terms = {};
- this.operators = {};
- this.productions = [];
- this.conflicts = 0;
- this.resolutions = [];
- this.options = options;
- this.yy = {}; // accessed as yy free variable in the parser/lexer actions
-
- // source included in semantic action execution scope
- if (grammar.actionInclude) {
- if (typeof grammar.actionInclude === 'function') {
- grammar.actionInclude = String(grammar.actionInclude).replace(/^\s*function \(\) \{/, '').replace(/\}\s*$/, '');
- }
- this.actionInclude = grammar.actionInclude;
- }
- this.moduleInclude = grammar.moduleInclude||'';
-
- this.DEBUG = options.debug || false;
- if (this.DEBUG) this.mix(generatorDebug); // mixin debug methods
-
- this.processGrammar(grammar);
-
- if (grammar.lex) {
- this.lexer = new RegExpLexer(grammar.lex, null, this.terminals_);
- }
-};
-
-generator.processGrammar = function processGrammarDef (grammar) {
- var bnf = grammar.bnf,
- tokens = grammar.tokens,
- nonterminals = this.nonterminals = {},
- productions = this.productions,
- self = this;
-
- if (!grammar.bnf && grammar.ebnf) {
- bnf = grammar.bnf = require("jison/ebnf").transform(grammar.ebnf);
- }
-
- if (tokens) {
- if (typeof tokens === 'string') {
- tokens = tokens.trim().split(' ');
- } else {
- tokens = tokens.slice(0);
- }
- }
-
- var symbols = this.symbols = [];
-
- // calculate precedence of operators
- var operators = this.operators = processOperators(grammar.operators);
-
- // build productions from cfg
- this.buildProductions(grammar.bnf, productions, nonterminals, symbols, operators);
-
- if (tokens && this.terminals.length !== tokens.length) {
- self.trace("Warning: declared tokens differ from tokens found in rules.");
- self.trace(this.terminals);
- self.trace(tokens);
- }
-
- // augment the grammar
- this.augmentGrammar(grammar);
-};
-
-generator.augmentGrammar = function augmentGrammar (grammar) {
- // use specified start symbol, or default to first user defined production
- this.startSymbol = grammar.start || grammar.startSymbol || this.productions[0].symbol;
- if (!this.nonterminals[this.startSymbol]) {
- throw new Error("Grammar error: startSymbol must be a non-terminal found in your grammar.");
- }
- this.EOF = "$end";
-
- // augment the grammar
- var acceptProduction = new Production('$accept', [this.startSymbol, '$end'], 0);
- this.productions.unshift(acceptProduction);
-
- // prepend parser tokens
- this.symbols.unshift("$accept",this.EOF);
- this.symbols_.$accept = 0;
- this.symbols_[this.EOF] = 1;
- this.terminals.unshift(this.EOF);
-
- this.nonterminals.$accept = new Nonterminal("$accept");
- this.nonterminals.$accept.productions.push(acceptProduction);
-
- // add follow $ to start symbol
- this.nonterminals[this.startSymbol].follows.push(this.EOF);
-};
-
-// set precedence and associativity of operators
-function processOperators (ops) {
- if (!ops) return {};
- var operators = {};
- for (var i=0,k,prec;prec=ops[i]; i++) {
- for (k=1;k < prec.length;k++) {
- operators[prec[k]] = {precedence: i+1, assoc: prec[0]};
- }
- }
- return operators;
-}
-
-
-generator.buildProductions = function buildProductions(bnf, productions, nonterminals, symbols, operators) {
- var actions = [
- this.actionInclude || '',
- 'var $0 = $$.length - 1;',
- 'switch (yystate) {'
- ];
- var prods, symbol;
- var productions_ = [0];
- var symbolId = 1;
- var symbols_ = {};
-
- var her = false; // has error recovery
-
- function addSymbol (s) {
- if (s && !symbols_[s]) {
- symbols_[s] = ++symbolId;
- symbols.push(s);
- }
- }
-
- // add error symbol; will be third symbol, or "2" ($accept, $end, error)
- addSymbol("error");
-
- for (symbol in bnf) {
- if (!bnf.hasOwnProperty(symbol)) continue;
-
- addSymbol(symbol);
- nonterminals[symbol] = new Nonterminal(symbol);
-
- if (typeof bnf[symbol] === 'string') {
- prods = bnf[symbol].split(/\s*\|\s*/g);
- } else {
- prods = bnf[symbol].slice(0);
- }
-
- prods.forEach(buildProduction);
- }
-
- var sym, terms = [], terms_ = {};
- each(symbols_, function (id, sym) {
- if (!nonterminals[sym]) {
- terms.push(sym);
- terms_[id] = sym;
- }
- });
-
- this.hasErrorRecovery = her;
-
- this.terminals = terms;
- this.terminals_ = terms_;
- this.symbols_ = symbols_;
-
- this.productions_ = productions_;
- actions.push('}');
- this.performAction = Function("yytext,yyleng,yylineno,yy,yystate,$$,_$", actions.join("\n"));
-
- function buildProduction (handle) {
- var r, rhs, i;
- if (handle.constructor === Array) {
- rhs = (typeof handle[0] === 'string') ?
- handle[0].trim().split(' ') :
- handle[0].slice(0);
-
- for (i=0; i=0; i--) {
- if (!(r.handle[i] in nonterminals) && r.handle[i] in operators) {
- r.precedence = operators[r.handle[i]].precedence;
- }
- }
- }
-
- productions.push(r);
- productions_.push([symbols_[r.symbol], r.handle[0] === '' ? 0 : r.handle.length]);
- nonterminals[symbol].productions.push(r);
- }
-};
-
-
-
-generator.createParser = function createParser () {
- throw new Error('Calling abstract method.');
-};
-
-// noop. implemented in debug mixin
-generator.trace = function trace () { };
-
-generator.warn = function warn () {
- var args = Array.prototype.slice.call(arguments,0);
- console.warn('Jison Warning', args);
-// Jison.print.call(null,args.join(""));
-};
-
-generator.error = function error (msg) {
- throw new Error(msg);
-};
-
-// Generator debug mixin
-
-var generatorDebug = {
- trace: function trace () {
- Jison.print.apply(null, arguments);
- },
- beforeprocessGrammar: function () {
- this.trace("Processing grammar.");
- },
- afteraugmentGrammar: function () {
- var trace = this.trace;
- each(this.symbols, function (sym, i) {
- trace(sym+"("+i+")");
- });
- }
-};
-
-
-
-/*
- * Mixin for common behaviors of lookahead parsers
- * */
-var lookaheadMixin = {};
-
-lookaheadMixin.computeLookaheads = function computeLookaheads () {
- if (this.DEBUG) this.mix(lookaheadDebug); // mixin debug methods
-
- this.computeLookaheads = function () {};
- this.nullableSets();
- this.firstSets();
- this.followSets();
-};
-
-// calculate follow sets typald on first and nullable
-lookaheadMixin.followSets = function followSets () {
- var productions = this.productions,
- nonterminals = this.nonterminals,
- self = this,
- cont = true;
-
- // loop until no further changes have been made
- while(cont) {
- cont = false;
-
- productions.forEach(function Follow_prod_forEach (production, k) {
- //self.trace(production.symbol,nonterminals[production.symbol].follows);
- // q is used in Simple LALR algorithm determine follows in context
- var q;
- var ctx = !!self.go_;
-
- var set = [],oldcount;
- for (var i=0,t;t=production.handle[i];++i) {
- if (!nonterminals[t]) continue;
-
- // for Simple LALR algorithm, self.go_ checks if
- if (ctx)
- q = self.go_(production.symbol, production.handle.slice(0, i));
- var bool = !ctx || q === parseInt(self.nterms_[t], 10);
-
- if (i === production.handle.length+1 && bool) {
- set = nonterminals[production.symbol].follows;
- } else {
- var part = production.handle.slice(i+1);
-
- set = self.first(part);
- if (self.nullable(part) && bool) {
- set.push.apply(set, nonterminals[production.symbol].follows);
- }
- }
- oldcount = nonterminals[t].follows.length;
- Set.union(nonterminals[t].follows, set);
- if (oldcount !== nonterminals[t].follows.length) {
- cont = true;
- }
- }
- });
- }
-};
-
-// return the FIRST set of a symbol or series of symbols
-lookaheadMixin.first = function first (symbol) {
- // epsilon
- if (symbol === '') {
- return [];
- // RHS
- } else if (symbol instanceof Array) {
- var firsts = [];
- for (var i=0,t;t=symbol[i];++i) {
- if (!this.nonterminals[t]) {
- if (firsts.indexOf(t) === -1)
- firsts.push(t);
- } else {
- Set.union(firsts, this.nonterminals[t].first);
- }
- if (!this.nullable(t))
- break;
- }
- return firsts;
- // terminal
- } else if (!this.nonterminals[symbol]) {
- return [symbol];
- // nonterminal
- } else {
- return this.nonterminals[symbol].first;
- }
-};
-
-// fixed-point calculation of FIRST sets
-lookaheadMixin.firstSets = function firstSets () {
- var productions = this.productions,
- nonterminals = this.nonterminals,
- self = this,
- cont = true,
- symbol,firsts;
-
- // loop until no further changes have been made
- while(cont) {
- cont = false;
-
- productions.forEach(function FirstSets_forEach (production, k) {
- var firsts = self.first(production.handle);
- if (firsts.length !== production.first.length) {
- production.first = firsts;
- cont=true;
- }
- });
-
- for (symbol in nonterminals) {
- firsts = [];
- nonterminals[symbol].productions.forEach(function (production) {
- Set.union(firsts, production.first);
- });
- if (firsts.length !== nonterminals[symbol].first.length) {
- nonterminals[symbol].first = firsts;
- cont=true;
- }
- }
- }
-};
-
-// fixed-point calculation of NULLABLE
-lookaheadMixin.nullableSets = function nullableSets () {
- var firsts = this.firsts = {},
- nonterminals = this.nonterminals,
- self = this,
- cont = true;
-
- // loop until no further changes have been made
- while(cont) {
- cont = false;
-
- // check if each production is nullable
- this.productions.forEach(function (production, k) {
- if (!production.nullable) {
- for (var i=0,n=0,t;t=production.handle[i];++i) {
- if (self.nullable(t)) n++;
- }
- if (n===i) { // production is nullable if all tokens are nullable
- production.nullable = cont = true;
- }
- }
- });
-
- //check if each symbol is nullable
- for (var symbol in nonterminals) {
- if (!this.nullable(symbol)) {
- for (var i=0,production;production=nonterminals[symbol].productions.item(i);i++) {
- if (production.nullable)
- nonterminals[symbol].nullable = cont = true;
- }
- }
- }
- }
-};
-
-// check if a token or series of tokens is nullable
-lookaheadMixin.nullable = function nullable (symbol) {
- // epsilon
- if (symbol === '') {
- return true;
- // RHS
- } else if (symbol instanceof Array) {
- for (var i=0,t;t=symbol[i];++i) {
- if (!this.nullable(t))
- return false;
- }
- return true;
- // terminal
- } else if (!this.nonterminals[symbol]) {
- return false;
- // nonterminal
- } else {
- return this.nonterminals[symbol].nullable;
- }
-};
-
-
-// lookahead debug mixin
-var lookaheadDebug = {
- beforenullableSets: function () {
- this.trace("Computing Nullable sets.");
- },
- beforefirstSets: function () {
- this.trace("Computing First sets.");
- },
- beforefollowSets: function () {
- this.trace("Computing Follow sets.");
- },
- afterfollowSets: function () {
- var trace = this.trace;
- each(this.nonterminals, function (nt, t) {
- trace(nt, '\n');
- });
- }
-};
-
-/*
- * Mixin for common LR parser behavior
- * */
-var lrGeneratorMixin = {};
-
-lrGeneratorMixin.buildTable = function buildTable () {
- if (this.DEBUG) this.mix(lrGeneratorDebug); // mixin debug methods
-
- this.states = this.canonicalCollection();
- this.table = this.parseTable(this.states);
- this.defaultActions = findDefaults(this.table);
-};
-
-lrGeneratorMixin.Item = typal.construct({
- constructor: function Item(production, dot, f, predecessor) {
- this.production = production;
- this.dotPosition = dot || 0;
- this.follows = f || [];
- this.predecessor = predecessor;
- this.id = parseInt(production.id+'a'+this.dotPosition, 36);
- this.markedSymbol = this.production.handle[this.dotPosition];
- },
- remainingHandle: function () {
- return this.production.handle.slice(this.dotPosition+1);
- },
- eq: function (e) {
- return e.id === this.id;
- },
- handleToString: function () {
- var handle = this.production.handle.slice(0);
- handle[this.dotPosition] = '.'+(handle[this.dotPosition]||'');
- return handle.join(' ');
- },
- toString: function () {
- var temp = this.production.handle.slice(0);
- temp[this.dotPosition] = '.'+(temp[this.dotPosition]||'');
- return this.production.symbol+" -> "+temp.join(' ') +
- (this.follows.length === 0 ? "" : " #lookaheads= "+this.follows.join(' '));
- }
-});
-
-lrGeneratorMixin.ItemSet = Set.prototype.construct({
- afterconstructor: function () {
- this.reductions = [];
- this.goes = {};
- this.edges = {};
- this.shifts = false;
- this.inadequate = false;
- this.hash_ = {};
- for (var i=this._items.length-1;i >=0;i--) {
- this.hash_[this._items[i].id] = true; //i;
- }
- },
- concat: function concat (set) {
- var a = set._items || set;
- for (var i=a.length-1;i >=0;i--) {
- this.hash_[a[i].id] = true; //i;
- }
- this._items.push.apply(this._items, a);
- return this;
- },
- push: function (item) {
- this.hash_[item.id] = true;
- return this._items.push(item);
- },
- contains: function (item) {
- return this.hash_[item.id];
- },
- valueOf: function toValue () {
- var v = this._items.map(function (a) {return a.id;}).sort().join('|');
- this.valueOf = function toValue_inner() {return v;};
- return v;
- }
-});
-
-lrGeneratorMixin.closureOperation = function closureOperation (itemSet /*, closureSet*/) {
- var closureSet = new this.ItemSet();
- var self = this;
-
- var set = itemSet,
- itemQueue, syms = {};
-
- do {
- itemQueue = new Set();
- closureSet.concat(set);
- set.forEach(function CO_set_forEach (item) {
- var symbol = item.markedSymbol;
-
- // if token is a non-terminal, recursively add closures
- if (symbol && self.nonterminals[symbol]) {
- if(!syms[symbol]) {
- self.nonterminals[symbol].productions.forEach(function CO_nt_forEach (production) {
- var newItem = new self.Item(production, 0);
- if(!closureSet.contains(newItem))
- itemQueue.push(newItem);
- });
- syms[symbol] = true;
- }
- } else if (!symbol) {
- // reduction
- closureSet.reductions.push(item);
- closureSet.inadequate = closureSet.reductions.length > 1 || closureSet.shifts;
- } else {
- // shift
- closureSet.shifts = true;
- closureSet.inadequate = closureSet.reductions.length > 0;
- }
- });
-
- set = itemQueue;
-
- } while (!itemQueue.isEmpty());
-
- return closureSet;
-};
-
-lrGeneratorMixin.gotoOperation = function gotoOperation (itemSet, symbol) {
- var gotoSet = new this.ItemSet(),
- self = this;
-
- itemSet.forEach(function goto_forEach(item, n) {
- if (item.markedSymbol === symbol) {
- gotoSet.push(new self.Item(item.production, item.dotPosition+1, item.follows, n));
- }
- });
-
- return gotoSet.isEmpty() ? gotoSet : this.closureOperation(gotoSet);
-};
-
-/* Create unique set of item sets
- * */
-lrGeneratorMixin.canonicalCollection = function canonicalCollection () {
- var item1 = new this.Item(this.productions[0], 0, [this.EOF]);
- var firstState = this.closureOperation(new this.ItemSet(item1)),
- states = new Set(firstState),
- marked = 0,
- self = this,
- itemSet;
-
- states.has = {};
- states.has[firstState] = 0;
-
- while (marked !== states.size()) {
- itemSet = states.item(marked); marked++;
- itemSet.forEach(function CC_itemSet_forEach (item) {
- if (item.markedSymbol && item.markedSymbol !== self.EOF)
- self.canonicalCollectionInsert(item.markedSymbol, itemSet, states, marked-1);
- });
- }
-
- return states;
-};
-
-// Pushes a unique state into the que. Some parsing algorithms may perform additional operations
-lrGeneratorMixin.canonicalCollectionInsert = function canonicalCollectionInsert (symbol, itemSet, states, stateNum) {
- var g = this.gotoOperation(itemSet, symbol);
- if (!g.predecessors)
- g.predecessors = {};
- // add g to que if not empty or duplicate
- if (!g.isEmpty()) {
- var gv = g.valueOf(),
- i = states.has[gv];
- if (i === -1 || typeof i === 'undefined') {
- states.has[gv] = states.size();
- itemSet.edges[symbol] = states.size(); // store goto transition for table
- states.push(g);
- g.predecessors[symbol] = [stateNum];
- } else {
- itemSet.edges[symbol] = i; // store goto transition for table
- states.item(i).predecessors[symbol].push(stateNum);
- }
- }
-};
-
-var NONASSOC = 0;
-lrGeneratorMixin.parseTable = function parseTable (itemSets) {
- var NONASSOC = 0;
- var states = [],
- nonterminals = this.nonterminals,
- operators = this.operators,
- conflictedStates = {}, // array of [state, token] tuples
- self = this,
- s = 1, // shift
- r = 2, // reduce
- a = 3; // accept
-
- // for each item set
- itemSets.forEach(function (itemSet, k) {
- var state = states[k] = {};
- var action, stackSymbol;
-
- // set shift and goto actions
- for (stackSymbol in itemSet.edges) {
- itemSet.forEach(function (item, j) {
- // find shift and goto actions
- if (item.markedSymbol == stackSymbol) {
- var gotoState = itemSet.edges[stackSymbol];
- if (nonterminals[stackSymbol]) {
- // store state to go to after a reduce
- //self.trace(k, stackSymbol, 'g'+gotoState);
- state[self.symbols_[stackSymbol]] = gotoState;
- } else {
- //self.trace(k, stackSymbol, 's'+gotoState);
- state[self.symbols_[stackSymbol]] = [s,gotoState];
- }
- }
- });
- }
-
- // set accept action
- itemSet.forEach(function (item, j) {
- if (item.markedSymbol == self.EOF) {
- // accept
- state[self.symbols_[self.EOF]] = [a];
- //self.trace(k, self.EOF, state[self.EOF]);
- }
- });
-
- var allterms = self.lookAheads ? false : self.terminals;
-
- // set reductions and resolve potential conflicts
- itemSet.reductions.forEach(function (item, j) {
- // if parser uses lookahead, only enumerate those terminals
- var terminals = allterms || self.lookAheads(itemSet, item);
-
- terminals.forEach(function (stackSymbol) {
- action = state[self.symbols_[stackSymbol]];
- var op = operators[stackSymbol];
-
- // Reading a terminal and current position is at the end of a production, try to reduce
- if (action || action && action.length) {
- var sol = resolveConflict(item.production, op, [r,item.production.id], action[0] instanceof Array ? action[0] : action);
- self.resolutions.push([k,stackSymbol,sol]);
- if (sol.bydefault) {
- self.conflicts++;
- if (!self.DEBUG) {
- self.warn('Conflict in grammar: multiple actions possible when lookahead token is ',stackSymbol,' in state ',k, "\n- ", printAction(sol.r, self), "\n- ", printAction(sol.s, self));
- conflictedStates[k] = true;
- }
- if (self.options.noDefaultResolve) {
- if (!(action[0] instanceof Array))
- action = [action];
- action.push(sol.r);
- }
- } else {
- action = sol.action;
- }
- } else {
- action = [r,item.production.id];
- }
- if (action && action.length) {
- state[self.symbols_[stackSymbol]] = action;
- } else if (action === NONASSOC) {
- state[self.symbols_[stackSymbol]] = undefined;
- }
- });
- });
-
- });
-
- if (!self.DEBUG && self.conflicts > 0) {
- self.warn("\nStates with conflicts:");
- each(conflictedStates, function (val, state) {
- self.warn('State '+state);
- self.warn(' ',itemSets.item(state).join("\n "));
- });
- }
-
- return states;
-};
-
-// find states with only one action, a reduction
-function findDefaults (states) {
- var defaults = {};
- states.forEach(function (state, k) {
- var i = 0;
- for (var act in state) {
- if ({}.hasOwnProperty.call(state, act)) i++;
- }
-
- if (i === 1 && state[act][0] === 2) {
- // only one action in state and it's a reduction
- defaults[k] = state[act];
- }
- });
-
- return defaults;
-}
-
-// resolves shift-reduce and reduce-reduce conflicts
-function resolveConflict (production, op, reduce, shift) {
- var sln = {production: production, operator: op, r: reduce, s: shift},
- s = 1, // shift
- r = 2, // reduce
- a = 3; // accept
-
- if (shift[0] === r) {
- sln.msg = "Resolve R/R conflict (use first production declared in grammar.)";
- sln.action = shift[1] < reduce[1] ? shift : reduce;
- if (shift[1] !== reduce[1]) sln.bydefault = true;
- return sln;
- }
-
- if (production.precedence === 0 || !op) {
- sln.msg = "Resolve S/R conflict (shift by default.)";
- sln.bydefault = true;
- sln.action = shift;
- } else if (production.precedence < op.precedence ) {
- sln.msg = "Resolve S/R conflict (shift for higher precedent operator.)";
- sln.action = shift;
- } else if (production.precedence === op.precedence) {
- if (op.assoc === "right" ) {
- sln.msg = "Resolve S/R conflict (shift for right associative operator.)";
- sln.action = shift;
- } else if (op.assoc === "left" ) {
- sln.msg = "Resolve S/R conflict (reduce for left associative operator.)";
- sln.action = reduce;
- } else if (op.assoc === "nonassoc" ) {
- sln.msg = "Resolve S/R conflict (no action for non-associative operator.)";
- sln.action = NONASSOC;
- }
- } else {
- sln.msg = "Resolve conflict (reduce for higher precedent production.)";
- sln.action = reduce;
- }
-
- return sln;
-}
-
-lrGeneratorMixin.generate = function parser_generate (opt) {
- opt = typal.mix.call({}, this.options, opt);
- var code = "";
-
- // check for illegal identifier
- if (!opt.moduleName || !opt.moduleName.match(/^[A-Za-z_$][A-Za-z0-9_$]*$/)) {
- opt.moduleName = "parser";
- }
- switch (opt.moduleType) {
- case "js":
- code = this.generateModule(opt);
- break;
- case "amd":
- code = this.generateAMDModule(opt);
- break;
- default:
- code = this.generateCommonJSModule(opt);
- }
-
- return code;
-};
-
-lrGeneratorMixin.generateAMDModule = function generateAMDModule(opt){
- opt = typal.mix.call({}, this.options, opt);
- var out = 'define([], function(){'
- + '\nvar parser = '+ this.generateModule_(opt)
- + (this.lexer && this.lexer.generateModule ?
- '\n' + this.lexer.generateModule() +
- '\nparser.lexer = lexer;' : '')
- + '\nreturn parser;'
- + '\n});'
- return out;
-};
-
-lrGeneratorMixin.generateCommonJSModule = function generateCommonJSModule (opt) {
- opt = typal.mix.call({}, this.options, opt);
- var moduleName = opt.moduleName || "parser";
- var out = this.generateModule(opt)
- + "\nif (typeof require !== 'undefined' && typeof exports !== 'undefined') {"
- + "\nexports.parser = "+moduleName+";"
- + "\nexports.Parser = "+moduleName+".Parser;"
- + "\nexports.parse = function () { return "+moduleName+".parse.apply("+moduleName+", arguments); }"
- + "\nexports.main = "+ String(opt.moduleMain || commonjsMain)
- + "\nif (typeof module !== 'undefined' && require.main === module) {\n"
- + " exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require(\"system\").args);\n}"
- + "\n}"
-
- return out;
-};
-
-lrGeneratorMixin.generateModule = function generateModule (opt) {
- opt = typal.mix.call({}, this.options, opt);
- var moduleName = opt.moduleName || "parser";
- var out = "/* Jison generated parser */\n";
- out += (moduleName.match(/\./) ? moduleName : "var "+moduleName)+" = (function(){";
- out += "\nvar parser = "+this.generateModule_();
- out += "\n"+this.moduleInclude;
- if (this.lexer && this.lexer.generateModule) {
- out += this.lexer.generateModule();
- out += "\nparser.lexer = lexer;";
- }
- out += "\nfunction Parser () { this.yy = {}; }"
- + "Parser.prototype = parser;"
- + "parser.Parser = Parser;"
- + "\nreturn new Parser;\n})();";
-
- return out;
-};
-
-// returns parse function without error recovery code
-function removeErrorRecovery (fn) {
- var parseFn = String(fn);
- try {
- var JSONSelect = require("JSONSelect");
- var Reflect = require("reflect");
- var ast = Reflect.parse(parseFn);
-
- var labeled = JSONSelect.match(':has(:root > .label > .name:val("_handle_error"))', ast);
- labeled[0].body.consequent.body = [labeled[0].body.consequent.body[0], labeled[0].body.consequent.body[1]];
-
- return Reflect.stringify(ast).replace(/_handle_error:\s?/,"").replace(/\\\\n/g,"\\n");
- } catch (e) {
- return parseFn;
- }
-}
-
-lrGeneratorMixin.generateModule_ = function generateModule_ () {
- var parseFn = (this.hasErrorRecovery ? String : removeErrorRecovery)(parser.parse);
-
- var out = "{";
- out += [
- "trace: " + String(this.trace || parser.trace),
- "yy: {}",
- "symbols_: " + JSON.stringify(this.symbols_),
- "terminals_: " + JSON.stringify(this.terminals_).replace(/"([0-9]+)":/g,"$1:"),
- "productions_: " + JSON.stringify(this.productions_),
- "performAction: " + String(this.performAction),
- "table: " + JSON.stringify(this.table).replace(/"([0-9]+)":/g,"$1:"),
- "defaultActions: " + JSON.stringify(this.defaultActions).replace(/"([0-9]+)":/g,"$1:"),
- "parseError: " + String(this.parseError || (this.hasErrorRecovery ? traceParseError : parser.parseError)),
- "parse: " + parseFn
- ].join(",\n");
- out += "};";
-
- return out;
-};
-
-// default main method for generated commonjs modules
-function commonjsMain (args) {
- if (!args[1])
- throw new Error('Usage: '+args[0]+' FILE');
- var source, cwd;
- if (typeof process !== 'undefined') {
- source = require("fs").readFileSync(require("path").resolve(args[1]), "utf8");
- } else {
- source = require("file").path(require("file").cwd()).join(args[1]).read({charset: "utf-8"});
- }
- return exports.parser.parse(source);
-}
-
-// debug mixin for LR parser generators
-
-function printAction (a, gen) {
- var s = a[0] == 1 ? 'shift token (then go to state '+a[1]+')' :
- a[0] == 2 ? 'reduce by rule: '+gen.productions[a[1]] :
- 'accept' ;
-
- return s;
-}
-
-var lrGeneratorDebug = {
- beforeparseTable: function () {
- this.trace("Building parse table.");
- },
- afterparseTable: function () {
- var self = this;
- if (this.conflicts > 0) {
- this.resolutions.forEach(function (r, i) {
- if (r[2].bydefault) {
- self.warn('Conflict at state: ',r[0], ', token: ',r[1], "\n ", printAction(r[2].r, self), "\n ", printAction(r[2].s, self));
- }
- });
- this.trace("\n"+this.conflicts+" Conflict(s) found in grammar.");
- }
- this.trace("Done.");
- },
- aftercanonicalCollection: function (states) {
- var trace = this.trace;
- trace("\nItem sets\n------");
-
- states.forEach(function (state, i) {
- trace("\nitem set",i,"\n"+state.join("\n"), '\ntransitions -> ', JSON.stringify(state.edges));
- });
- }
-};
-
-var parser = typal.beget();
-
-lrGeneratorMixin.createParser = function createParser () {
- var p = parser.beget();
- p.yy = {};
-
- p.init({
- table: this.table,
- defaultActions: this.defaultActions,
- productions_: this.productions_,
- symbols_: this.symbols_,
- terminals_: this.terminals_,
- performAction: this.performAction
- });
-
- // don't throw if grammar recovers from errors
- if (this.hasErrorRecovery) {
- p.parseError = traceParseError;
- p.recover = true;
- }
-
- // for debugging
- p.productions = this.productions;
-
- // backwards compatability
- p.generate = this.generate;
- p.lexer = this.lexer;
- p.generateModule = this.generateModule;
- p.generateCommonJSModule = this.generateCommonJSModule;
- p.generateModule_ = this.generateModule_;
-
- var gen = this;
-
- p.Parser = function () {
- return gen.createParser();
- };
-
- return p;
-};
-
-parser.trace = generator.trace;
-parser.warn = generator.warn;
-parser.error = generator.error;
-
-function traceParseError (err, hash) {
- this.trace(err);
-}
-
-parser.parseError = lrGeneratorMixin.parseError = function parseError (str, hash) {
- throw new Error(str);
-};
-
-parser.parse = function parse (input) {
- var self = this,
- stack = [0],
- vstack = [null], // semantic value stack
- lstack = [], // location stack
- table = this.table,
- yytext = '',
- yylineno = 0,
- yyleng = 0,
- recovering = 0,
- TERROR = 2,
- EOF = 1;
-
- //this.reductionCount = this.shiftCount = 0;
-
- this.lexer.setInput(input);
- this.lexer.yy = this.yy;
- this.yy.lexer = this.lexer;
- this.yy.parser = this;
- if (typeof this.lexer.yylloc == 'undefined')
- this.lexer.yylloc = {};
- var yyloc = this.lexer.yylloc;
- lstack.push(yyloc);
-
- var ranges = this.lexer.options && this.lexer.options.ranges;
-
- if (typeof this.yy.parseError === 'function')
- this.parseError = this.yy.parseError;
-
- function popStack (n) {
- stack.length = stack.length - 2*n;
- vstack.length = vstack.length - n;
- lstack.length = lstack.length - n;
- }
-
- function lex() {
- var token;
- token = self.lexer.lex() || 1; // $end = 1
- // if token isn't its numeric value, convert
- if (typeof token !== 'number') {
- token = self.symbols_[token] || token;
- }
- return token;
- }
-
- var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected;
- while (true) {
- // retreive state number from top of stack
- state = stack[stack.length-1];
-
- // use default actions if available
- if (this.defaultActions[state]) {
- action = this.defaultActions[state];
- } else {
- if (symbol === null || typeof symbol == 'undefined') {
- symbol = lex();
- }
- // read action for current state and first input
- action = table[state] && table[state][symbol];
- }
-
- // handle parse error
- _handle_error:
- if (typeof action === 'undefined' || !action.length || !action[0]) {
-
- var errStr = '';
- if (!recovering) {
- // Report error
- expected = [];
- for (p in table[state]) if (this.terminals_[p] && p > 2) {
- expected.push("'"+this.terminals_[p]+"'");
- }
- if (this.lexer.showPosition) {
- errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + (this.terminals_[symbol] || symbol)+ "'";
- } else {
- errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " +
- (symbol == 1 /*EOF*/ ? "end of input" :
- ("'"+(this.terminals_[symbol] || symbol)+"'"));
- }
- this.parseError(errStr,
- {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});
- }
-
- // just recovered from another error
- if (recovering == 3) {
- if (symbol == EOF) {
- throw new Error(errStr || 'Parsing halted.');
- }
-
- // discard current lookahead and grab another
- yyleng = this.lexer.yyleng;
- yytext = this.lexer.yytext;
- yylineno = this.lexer.yylineno;
- yyloc = this.lexer.yylloc;
- symbol = lex();
- }
-
- // try to recover from error
- while (1) {
- // check for error recovery rule in this state
- if ((TERROR.toString()) in table[state]) {
- break;
- }
- if (state === 0) {
- throw new Error(errStr || 'Parsing halted.');
- }
- popStack(1);
- state = stack[stack.length-1];
- }
-
- preErrorSymbol = symbol == 2 ? null : symbol; // save the lookahead token
- symbol = TERROR; // insert generic error symbol as new lookahead
- state = stack[stack.length-1];
- action = table[state] && table[state][TERROR];
- recovering = 3; // allow 3 real symbols to be shifted before reporting a new error
- }
-
- // this shouldn't happen, unless resolve defaults are off
- if (action[0] instanceof Array && action.length > 1) {
- throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol);
- }
-
- switch (action[0]) {
-
- case 1: // shift
- //this.shiftCount++;
-
- stack.push(symbol);
- vstack.push(this.lexer.yytext);
- lstack.push(this.lexer.yylloc);
- stack.push(action[1]); // push state
- symbol = null;
- if (!preErrorSymbol) { // normal execution/no error
- yyleng = this.lexer.yyleng;
- yytext = this.lexer.yytext;
- yylineno = this.lexer.yylineno;
- yyloc = this.lexer.yylloc;
- if (recovering > 0)
- recovering--;
- } else { // error just occurred, resume old lookahead f/ before error
- symbol = preErrorSymbol;
- preErrorSymbol = null;
- }
- break;
-
- case 2: // reduce
- //this.reductionCount++;
-
- len = this.productions_[action[1]][1];
-
- // perform semantic action
- yyval.$ = vstack[vstack.length-len]; // default to $$ = $1
- // default location, uses first token for firsts, last for lasts
- yyval._$ = {
- first_line: lstack[lstack.length-(len||1)].first_line,
- last_line: lstack[lstack.length-1].last_line,
- first_column: lstack[lstack.length-(len||1)].first_column,
- last_column: lstack[lstack.length-1].last_column
- };
- if (ranges) {
- yyval._$.range = [lstack[lstack.length-(len||1)].range[0], lstack[lstack.length-1].range[1]];
- }
- r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
-
- if (typeof r !== 'undefined') {
- return r;
- }
-
- // pop off stack
- if (len) {
- stack = stack.slice(0,-1*len*2);
- vstack = vstack.slice(0, -1*len);
- lstack = lstack.slice(0, -1*len);
- }
-
- stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce)
- vstack.push(yyval.$);
- lstack.push(yyval._$);
- // goto new state = table[STATE][NONTERMINAL]
- newState = table[stack[stack.length-2]][stack[stack.length-1]];
- stack.push(newState);
- break;
-
- case 3: // accept
- return true;
- }
-
- }
-
- return true;
-};
-
-parser.init = function parser_init (dict) {
- this.table = dict.table;
- this.defaultActions = dict.defaultActions;
- this.performAction = dict.performAction;
- this.productions_ = dict.productions_;
- this.symbols_ = dict.symbols_;
- this.terminals_ = dict.terminals_;
-};
-
-/*
- * LR(0) Parser
- * */
-
-var lr0 = generator.beget(lookaheadMixin, lrGeneratorMixin, {
- type: "LR(0)",
- afterconstructor: function lr0_afterconstructor () {
- this.buildTable();
- }
-});
-
-var LR0Generator = exports.LR0Generator = lr0.construct();
-
-/*
- * Simple LALR(1)
- * */
-
-var lalr = generator.beget(lookaheadMixin, lrGeneratorMixin, {
- type: "LALR(1)",
-
- afterconstructor: function (grammar, options) {
- if (this.DEBUG) this.mix(lrGeneratorDebug, lalrGeneratorDebug); // mixin debug methods
-
- options = options || {};
- this.states = this.canonicalCollection();
- this.terms_ = {};
-
- var newg = this.newg = typal.beget(lookaheadMixin,{
- oldg: this,
- trace: this.trace,
- nterms_: {},
- DEBUG: false,
- go_: function (r, B) {
- r = r.split(":")[0]; // grab state #
- B = B.map(function (b) { return b.slice(b.indexOf(":")+1); });
- return this.oldg.go(r, B);
- }
- });
- newg.nonterminals = {};
- newg.productions = [];
-
- this.inadequateStates = [];
-
- // if true, only lookaheads in inadequate states are computed (faster, larger table)
- // if false, lookaheads for all reductions will be computed (slower, smaller table)
- this.onDemandLookahead = options.onDemandLookahead || false;
-
- this.buildNewGrammar();
- newg.computeLookaheads();
- this.unionLookaheads();
-
- this.table = this.parseTable(this.states);
- this.defaultActions = findDefaults(this.table);
- },
-
- lookAheads: function LALR_lookaheads (state, item) {
- return (!!this.onDemandLookahead && !state.inadequate) ? this.terminals : item.follows;
- },
- go: function LALR_go (p, w) {
- var q = parseInt(p, 10);
- for (var i=0;i
-
-var RegExpLexer = (function () {
-
-// expand macros and convert matchers to RegExp's
-function prepareRules(rules, macros, actions, tokens, startConditions, caseless) {
- var m,i,k,action,conditions,
- newRules = [];
-
- if (macros) {
- macros = prepareMacros(macros);
- }
-
- function tokenNumberReplacement (str, token) {
- return "return "+(tokens[token] || "'"+token+"'");
- }
-
- actions.push('switch($avoiding_name_collisions) {');
-
- for (i=0;i < rules.length; i++) {
- if (Object.prototype.toString.apply(rules[i][0]) !== '[object Array]') {
- // implicit add to all inclusive start conditions
- for (k in startConditions) {
- if (startConditions[k].inclusive) {
- startConditions[k].rules.push(i);
- }
- }
- } else if (rules[i][0][0] === '*') {
- // Add to ALL start conditions
- for (k in startConditions) {
- startConditions[k].rules.push(i);
- }
- rules[i].shift();
- } else {
- // Add to explicit start conditions
- conditions = rules[i].shift();
- for (k=0;k 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
- },
- // displays upcoming input, i.e. for error messages
- upcomingInput: function () {
- var next = this.match;
- if (next.length < 20) {
- next += this._input.substr(0, 20-next.length);
- }
- return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, "");
- },
- // displays upcoming input, i.e. for error messages
- showPosition: function () {
- var pre = this.pastInput();
- var c = new Array(pre.length + 1).join("-");
- return pre + this.upcomingInput() + "\n" + c+"^";
- },
-
- // return next match in input
- next: function () {
- if (this.done) {
- return this.EOF;
- }
- if (!this._input) this.done = true;
-
- var token,
- match,
- tempMatch,
- index,
- col,
- lines;
- if (!this._more) {
- this.yytext = '';
- this.match = '';
- }
- var rules = this._currentRules();
- for (var i=0;i < rules.length; i++) {
- tempMatch = this._input.match(this.rules[rules[i]]);
- if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
- match = tempMatch;
- index = i;
- if (!this.options.flex) break;
- }
- }
- if (match) {
- lines = match[0].match(/(?:\r\n?|\n).*/g);
- if (lines) this.yylineno += lines.length;
- this.yylloc = {first_line: this.yylloc.last_line,
- last_line: this.yylineno+1,
- first_column: this.yylloc.last_column,
- last_column: lines ? lines[lines.length-1].length-lines[lines.length-1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length};
- this.yytext += match[0];
- this.match += match[0];
- this.matches = match;
- this.yyleng = this.yytext.length;
- if (this.options.ranges) {
- this.yylloc.range = [this.offset, this.offset += this.yyleng];
- }
- this._more = false;
- this._input = this._input.slice(match[0].length);
- this.matched += match[0];
- token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]);
- if (this.done && this._input) this.done = false;
- if (token) return token;
- else return;
- }
- if (this._input === "") {
- return this.EOF;
- } else {
- return this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(),
- {text: "", token: null, line: this.yylineno});
- }
- },
-
- // return next match that has a token
- lex: function lex () {
- var r = this.next();
- if (typeof r !== 'undefined') {
- return r;
- } else {
- return this.lex();
- }
- },
- begin: function begin (condition) {
- this.conditionStack.push(condition);
- },
- popState: function popState () {
- return this.conditionStack.pop();
- },
- _currentRules: function _currentRules () {
- return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules;
- },
- topState: function () {
- return this.conditionStack[this.conditionStack.length-2];
- },
- pushState: function begin (condition) {
- this.begin(condition);
- },
-
- generate: function generate(opt) {
- var code = "";
- if (opt.commonjs)
- code = this.generateCommonJSModule(opt);
- else
- code = this.generateModule(opt);
-
- return code;
- },
- generateModule: function generateModule(opt) {
- opt = opt || {};
- var out = "/* Jison generated lexer */",
- moduleName = opt.moduleName || "lexer";
- out += "\nvar "+moduleName+" = (function(){\nvar lexer = ({";
- var p = [];
- for (var k in RegExpLexer.prototype)
- if (RegExpLexer.prototype.hasOwnProperty(k) && k.indexOf("generate") === -1)
- p.push(k + ":" + (RegExpLexer.prototype[k].toString() || '""'));
- out += p.join(",\n");
- out += "})";
- if (this.options) {
- out += ";\nlexer.options = "+JSON.stringify(this.options);
- }
- out += ";\nlexer.performAction = "+String(this.performAction);
- out += ";\nlexer.rules = [" + this.rules + "]";
- out += ";\nlexer.conditions = " + JSON.stringify(this.conditions);
- if (this.moduleInclude) out += ";\n"+this.moduleInclude;
- out += ";\nreturn lexer;})()";
- return out;
- },
- generateCommonJSModule: function generateCommonJSModule(opt) {
- opt = opt || {};
- var out = "/* Jison generated lexer as commonjs module */",
- moduleName = opt.moduleName || "lexer";
- out += this.generateModule(opt);
- out += "\nexports.lexer = "+moduleName;
- out += ";\nexports.lex = function () { return "+moduleName+".lex.apply(lexer, arguments); };";
- return out;
- }
-};
-
-return RegExpLexer;
-
-})();
-
-if (typeof exports !== 'undefined')
- exports.RegExpLexer = RegExpLexer;
-
-
-//*/
-},requires:["jison/jisonlex"]});
-
-require.def("jison/bnf",{factory:function(require,exports,module){
-var bnf = require("jison/util/bnf-parser").parser,
- jisonlex = require("jison/jisonlex");
-
-exports.parse = function parse () { return bnf.parse.apply(bnf, arguments); };
-
-// adds a declaration to the grammar
-bnf.yy.addDeclaration = function (grammar, decl) {
- if (decl.start) {
- grammar.start = decl.start;
- }
- else if (decl.lex) {
- grammar.lex = parseLex(decl.lex);
- }
- else if (decl.operator) {
- if (!grammar.operators) {
- grammar.operators = [];
- }
- grammar.operators.push(decl.operator);
- }
- else if (decl.include) {
- if (!grammar.moduleInclude)
- grammar.moduleInclude = '';
- grammar.moduleInclude += decl.include;
- }
-
-};
-
-// helps tokenize comments
-bnf.yy.lexComment = function (lexer) {
- var ch = lexer.input();
- if (ch === '/') {
- lexer.yytext = lexer.yytext.replace(/\*(.|\s)\/\*/, '*$1');
- return;
- } else {
- lexer.unput('/*');
- lexer.more();
- }
-};
-
-// parse an embedded lex section
-var parseLex = function (text) {
- return jisonlex.parse(text.replace(/(?:^%lex)|(?:\/lex$)/g, ''));
-};
-
-
-//*/
-},requires:["jison/util/bnf-parser","jison/jisonlex"]});
-
-require.def("jison/jisonlex",{factory:function(require,exports,module){
-var jisonlex = require("jison/util/lex-parser").parser;
-
-var parse_ = jisonlex.parse;
-jisonlex.parse = exports.parse = function parse () {
- jisonlex.yy.ruleSection = false;
- return parse_.apply(jisonlex, arguments);
-};
-
-function encodeRE (s) { return s.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1').replace(/\\\\u([a-fA-F0-9]{4})/g,'\\u$1'); }
-
-jisonlex.yy = {
- prepareString: function (s) {
- // unescape slashes
- s = s.replace(/\\\\/g, "\\");
- s = encodeRE(s);
- return s;
- }
-};
-
-//*/
-},requires:["jison/util/lex-parser"]});
-
-require.def("jison/util/set",{factory:function(require,exports,module){
-// Set class to wrap arrays
-
-var typal = require("jison/util/typal").typal;
-
-var setMixin = {
- constructor: function Set_constructor (set, raw) {
- this._items = [];
- if (set && set.constructor === Array)
- this._items = raw ? set: set.slice(0);
- else if(arguments.length)
- this._items = [].slice.call(arguments,0);
- },
- concat: function concat (setB) {
- this._items.push.apply(this._items, setB._items || setB);
- return this;
- },
- eq: function eq (set) {
- return this._items.length === set._items.length && this.subset(set);
- },
- indexOf: function indexOf (item) {
- if(item && item.eq) {
- for(var k=0; k=0;--k) {
- ar[a[k]] = true;
- }
- for (var i=b.length-1;i >= 0;--i) {
- if (!ar[b[i]]) {
- a.push(b[i]);
- }
- }
- return a;
- }
-});
-
-if (typeof exports !== 'undefined')
- exports.Set = Set;
-
-
-//*/
-},requires:["jison/util/typal"]});
-
-require.def("jison/util/typal",{factory:function(require,exports,module){
-/*
- * Introduces a typal object to make classical/prototypal patterns easier
- * Plus some AOP sugar
- *
- * By Zachary Carter
- * MIT Licensed
- * */
-
-var typal = (function () {
-
-var create = Object.create || function (o) { function F(){} F.prototype = o; return new F(); };
-var position = /^(before|after)/;
-
-// basic method layering
-// always returns original method's return value
-function layerMethod(k, fun) {
- var pos = k.match(position)[0],
- key = k.replace(position, ''),
- prop = this[key];
-
- if (pos === 'after') {
- this[key] = function () {
- var ret = prop.apply(this, arguments);
- var args = [].slice.call(arguments);
- args.splice(0, 0, ret);
- fun.apply(this, args);
- return ret;
- };
- } else if (pos === 'before') {
- this[key] = function () {
- fun.apply(this, arguments);
- var ret = prop.apply(this, arguments);
- return ret;
- };
- }
-}
-
-// mixes each argument's own properties into calling object,
-// overwriting them or layering them. i.e. an object method 'meth' is
-// layered by mixin methods 'beforemeth' or 'aftermeth'
-function typal_mix() {
- var self = this;
- for(var i=0,o,k; i 2) {
- expected.push("'" + this.terminals_[p] + "'");
- }
- if (this.lexer.showPosition) {
- errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'";
- } else {
- errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1?"end of input":"'" + (this.terminals_[symbol] || symbol) + "'");
- }
- this.parseError(errStr, {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});
- }
- }
- if (action[0] instanceof Array && action.length > 1) {
- throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol);
- }
- switch (action[0]) {
- case 1:
- stack.push(symbol);
- vstack.push(this.lexer.yytext);
- lstack.push(this.lexer.yylloc);
- stack.push(action[1]);
- symbol = null;
- if (!preErrorSymbol) {
- yyleng = this.lexer.yyleng;
- yytext = this.lexer.yytext;
- yylineno = this.lexer.yylineno;
- yyloc = this.lexer.yylloc;
- if (recovering > 0)
- recovering--;
- } else {
- symbol = preErrorSymbol;
- preErrorSymbol = null;
- }
- break;
- case 2:
- len = this.productions_[action[1]][1];
- yyval.$ = vstack[vstack.length - len];
- yyval._$ = {first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column};
- if (ranges) {
- yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
- }
- r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
- if (typeof r !== "undefined") {
- return r;
- }
- if (len) {
- stack = stack.slice(0, -1 * len * 2);
- vstack = vstack.slice(0, -1 * len);
- lstack = lstack.slice(0, -1 * len);
- }
- stack.push(this.productions_[action[1]][0]);
- vstack.push(yyval.$);
- lstack.push(yyval._$);
- newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
- stack.push(newState);
- break;
- case 3:
- return true;
- }
- }
- return true;
-}
-};
-
-var ebnf = false;
-
-
-/* Jison generated lexer */
-var lexer = (function(){
-var lexer = ({EOF:1,
-parseError:function parseError(str, hash) {
- if (this.yy.parser) {
- this.yy.parser.parseError(str, hash);
- } else {
- throw new Error(str);
- }
- },
-setInput:function (input) {
- this._input = input;
- this._more = this._less = this.done = false;
- this.yylineno = this.yyleng = 0;
- this.yytext = this.matched = this.match = '';
- this.conditionStack = ['INITIAL'];
- this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0};
- if (this.options.ranges) this.yylloc.range = [0,0];
- this.offset = 0;
- return this;
- },
-input:function () {
- var ch = this._input[0];
- this.yytext += ch;
- this.yyleng++;
- this.offset++;
- this.match += ch;
- this.matched += ch;
- var lines = ch.match(/(?:\r\n?|\n).*/g);
- if (lines) {
- this.yylineno++;
- this.yylloc.last_line++;
- } else {
- this.yylloc.last_column++;
- }
- if (this.options.ranges) this.yylloc.range[1]++;
-
- this._input = this._input.slice(1);
- return ch;
- },
-unput:function (ch) {
- var len = ch.length;
- var lines = ch.split(/(?:\r\n?|\n)/g);
-
- this._input = ch + this._input;
- this.yytext = this.yytext.substr(0, this.yytext.length-len-1);
- //this.yyleng -= len;
- this.offset -= len;
- var oldLines = this.match.split(/(?:\r\n?|\n)/g);
- this.match = this.match.substr(0, this.match.length-1);
- this.matched = this.matched.substr(0, this.matched.length-1);
-
- if (lines.length-1) this.yylineno -= lines.length-1;
- var r = this.yylloc.range;
-
- this.yylloc = {first_line: this.yylloc.first_line,
- last_line: this.yylineno+1,
- first_column: this.yylloc.first_column,
- last_column: lines ?
- (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length:
- this.yylloc.first_column - len
- };
-
- if (this.options.ranges) {
- this.yylloc.range = [r[0], r[0] + this.yyleng - len];
- }
- return this;
- },
-more:function () {
- this._more = true;
- return this;
- },
-less:function (n) {
- this.unput(this.match.slice(n));
- },
-pastInput:function () {
- var past = this.matched.substr(0, this.matched.length - this.match.length);
- return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
- },
-upcomingInput:function () {
- var next = this.match;
- if (next.length < 20) {
- next += this._input.substr(0, 20-next.length);
- }
- return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, "");
- },
-showPosition:function () {
- var pre = this.pastInput();
- var c = new Array(pre.length + 1).join("-");
- return pre + this.upcomingInput() + "\n" + c+"^";
- },
-next:function () {
- if (this.done) {
- return this.EOF;
- }
- if (!this._input) this.done = true;
-
- var token,
- match,
- tempMatch,
- index,
- col,
- lines;
- if (!this._more) {
- this.yytext = '';
- this.match = '';
- }
- var rules = this._currentRules();
- for (var i=0;i < rules.length; i++) {
- tempMatch = this._input.match(this.rules[rules[i]]);
- if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
- match = tempMatch;
- index = i;
- if (!this.options.flex) break;
- }
- }
- if (match) {
- lines = match[0].match(/(?:\r\n?|\n).*/g);
- if (lines) this.yylineno += lines.length;
- this.yylloc = {first_line: this.yylloc.last_line,
- last_line: this.yylineno+1,
- first_column: this.yylloc.last_column,
- last_column: lines ? lines[lines.length-1].length-lines[lines.length-1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length};
- this.yytext += match[0];
- this.match += match[0];
- this.matches = match;
- this.yyleng = this.yytext.length;
- if (this.options.ranges) {
- this.yylloc.range = [this.offset, this.offset += this.yyleng];
- }
- this._more = false;
- this._input = this._input.slice(match[0].length);
- this.matched += match[0];
- token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]);
- if (this.done && this._input) this.done = false;
- if (token) return token;
- else return;
- }
- if (this._input === "") {
- return this.EOF;
- } else {
- return this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(),
- {text: "", token: null, line: this.yylineno});
- }
- },
-lex:function lex() {
- var r = this.next();
- if (typeof r !== 'undefined') {
- return r;
- } else {
- return this.lex();
- }
- },
-begin:function begin(condition) {
- this.conditionStack.push(condition);
- },
-popState:function popState() {
- return this.conditionStack.pop();
- },
-_currentRules:function _currentRules() {
- return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules;
- },
-topState:function () {
- return this.conditionStack[this.conditionStack.length-2];
- },
-pushState:function begin(condition) {
- this.begin(condition);
- }});
-lexer.options = {};
-lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
-
-var YYSTATE=YY_START
-switch($avoiding_name_collisions) {
-case 0:this.begin('code');return 5;
-break;
-case 1:return 38
-break;
-case 2:return 39
-break;
-case 3:return 40
-break;
-case 4:return 41
-break;
-case 5:return 42
-break;
-case 6:/* skip whitespace */
-break;
-case 7:/* skip comment */
-break;
-case 8:return yy.lexComment(this);
-break;
-case 9:return 36;
-break;
-case 10:yy_.yytext = yy_.yytext.substr(1, yy_.yyleng-2); return 37;
-break;
-case 11:yy_.yytext = yy_.yytext.substr(1, yy_.yyleng-2); return 37;
-break;
-case 12:return 24;
-break;
-case 13:return 26;
-break;
-case 14:return 27;
-break;
-case 15:this.begin(ebnf ? 'ebnf' : 'bnf');return 5;
-break;
-case 16:if (!yy.options) yy.options = {}; ebnf = yy.options.ebnf = true;
-break;
-case 17:return 43;
-break;
-case 18:return 11;
-break;
-case 19:return 18;
-break;
-case 20:return 19;
-break;
-case 21:return 20;
-break;
-case 22:return 13;
-break;
-case 23:/* ignore unrecognized decl */
-break;
-case 24:/* ignore type */
-break;
-case 25:yy_.yytext = yy_.yytext.substr(2, yy_.yyleng-4); return 15;
-break;
-case 26:yy_.yytext = yy_.yytext.substr(2, yy_.yytext.length-4);return 15;
-break;
-case 27:yy.depth=0; this.begin('action'); return 44;
-break;
-case 28:yy_.yytext = yy_.yytext.substr(2, yy_.yyleng-2); return 47;
-break;
-case 29:/* ignore bad characters */
-break;
-case 30:return 8;
-break;
-case 31:return 48;
-break;
-case 32:yy.depth++; return 44;
-break;
-case 33:yy.depth==0? this.begin(ebnf ? 'ebnf' : 'bnf') : yy.depth--; return 46;
-break;
-case 34:return 9;
-break;
-}
-};
-lexer.rules = [/^(?:%%)/,/^(?:\()/,/^(?:\))/,/^(?:\*)/,/^(?:\?)/,/^(?:\+)/,/^(?:\s+)/,/^(?:\/\/.*)/,/^(?:\/\*[^*]*\*)/,/^(?:[a-zA-Z][a-zA-Z0-9_-]*)/,/^(?:"[^"]+")/,/^(?:'[^']+')/,/^(?::)/,/^(?:;)/,/^(?:\|)/,/^(?:%%)/,/^(?:%ebnf\b)/,/^(?:%prec\b)/,/^(?:%start\b)/,/^(?:%left\b)/,/^(?:%right\b)/,/^(?:%nonassoc\b)/,/^(?:%lex[\w\W]*?\/lex\b)/,/^(?:%[a-zA-Z]+[^\n]*)/,/^(?:<[a-zA-Z]*>)/,/^(?:\{\{[\w\W]*?\}\})/,/^(?:%\{(.|\n)*?%\})/,/^(?:\{)/,/^(?:->.*)/,/^(?:.)/,/^(?:$)/,/^(?:[^{}]+)/,/^(?:\{)/,/^(?:\})/,/^(?:(.|\n)+)/];
-lexer.conditions = {"bnf":{"rules":[0,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30],"inclusive":true},"ebnf":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30],"inclusive":true},"action":{"rules":[30,31,32,33],"inclusive":false},"code":{"rules":[30,34],"inclusive":false},"INITIAL":{"rules":[6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30],"inclusive":true}};
-
-;
-return lexer;})()
-parser.lexer = lexer;
-function Parser () { this.yy = {}; }Parser.prototype = parser;parser.Parser = Parser;
-return new Parser;
-})();
-if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
-exports.parser = bnf;
-exports.Parser = bnf.Parser;
-exports.parse = function () { return bnf.parse.apply(bnf, arguments); }
-exports.main = function commonjsMain(args) {
- if (!args[1])
- throw new Error('Usage: '+args[0]+' FILE');
- var source, cwd;
- if (typeof process !== 'undefined') {
- source = require("fs").readFileSync(require("path").resolve(args[1]), "utf8");
- } else {
- source = require("file").path(require("file").cwd()).join(args[1]).read({charset: "utf-8"});
- }
- return exports.parser.parse(source);
-}
-if (typeof module !== 'undefined' && require.main === module) {
- exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require("system").args);
-}
-}
-//*/
-},requires:["fs","path","file","file","system"]});
-
-require.def("jison/util/lex-parser",{factory:function(require,exports,module){
-/* Jison generated parser */
-var jisonlex = (function(){
-var parser = {trace: function trace() { },
-yy: {},
-symbols_: {"error":2,"lex":3,"definitions":4,"%%":5,"rules":6,"epilogue":7,"EOF":8,"CODE":9,"definition":10,"ACTION":11,"NAME":12,"regex":13,"START_INC":14,"names_inclusive":15,"START_EXC":16,"names_exclusive":17,"START_COND":18,"rule":19,"start_conditions":20,"action":21,"{":22,"action_body":23,"}":24,"ACTION_BODY":25,"<":26,"name_list":27,">":28,"*":29,",":30,"regex_list":31,"|":32,"regex_concat":33,"regex_base":34,"(":35,")":36,"SPECIAL_GROUP":37,"+":38,"?":39,"/":40,"/!":41,"name_expansion":42,"range_regex":43,"any_group_regex":44,".":45,"^":46,"$":47,"string":48,"escape_char":49,"NAME_BRACE":50,"ANY_GROUP_REGEX":51,"ESCAPE_CHAR":52,"RANGE_REGEX":53,"STRING_LIT":54,"CHARACTER_LIT":55,"$accept":0,"$end":1},
-terminals_: {2:"error",5:"%%",8:"EOF",9:"CODE",11:"ACTION",12:"NAME",14:"START_INC",16:"START_EXC",18:"START_COND",22:"{",24:"}",25:"ACTION_BODY",26:"<",28:">",29:"*",30:",",32:"|",35:"(",36:")",37:"SPECIAL_GROUP",38:"+",39:"?",40:"/",41:"/!",45:".",46:"^",47:"$",50:"NAME_BRACE",51:"ANY_GROUP_REGEX",52:"ESCAPE_CHAR",53:"RANGE_REGEX",54:"STRING_LIT",55:"CHARACTER_LIT"},
-productions_: [0,[3,4],[7,1],[7,2],[7,3],[4,2],[4,2],[4,0],[10,2],[10,2],[10,2],[15,1],[15,2],[17,1],[17,2],[6,2],[6,1],[19,3],[21,3],[21,1],[23,0],[23,1],[23,5],[23,4],[20,3],[20,3],[20,0],[27,1],[27,3],[13,1],[31,3],[31,2],[31,1],[31,0],[33,2],[33,1],[34,3],[34,3],[34,2],[34,2],[34,2],[34,2],[34,2],[34,1],[34,2],[34,1],[34,1],[34,1],[34,1],[34,1],[34,1],[42,1],[44,1],[49,1],[43,1],[48,1],[48,1]],
-performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
-
-var $0 = $$.length - 1;
-switch (yystate) {
-case 1: this.$ = {rules: $$[$0-1]};
- if ($$[$0-3][0]) this.$.macros = $$[$0-3][0];
- if ($$[$0-3][1]) this.$.startConditions = $$[$0-3][1];
- if ($$[$0]) this.$.moduleInclude = $$[$0];
- if (yy.options) this.$.options = yy.options;
- if (yy.actionInclude) this.$.actionInclude = yy.actionInclude;
- delete yy.options;
- delete yy.actionInclude;
- return this.$;
-break;
-case 2: this.$ = null;
-break;
-case 3: this.$ = null;
-break;
-case 4: this.$ = $$[$0-1];
-break;
-case 5:
- this.$ = $$[$0];
- if ('length' in $$[$0-1]) {
- this.$[0] = this.$[0] || {};
- this.$[0][$$[$0-1][0]] = $$[$0-1][1];
- } else {
- this.$[1] = this.$[1] || {};
- for (var name in $$[$0-1]) {
- this.$[1][name] = $$[$0-1][name];
- }
- }
-
-break;
-case 6: yy.actionInclude += $$[$0-1]; this.$ = $$[$0];
-break;
-case 7: yy.actionInclude = ''; this.$ = [null,null];
-break;
-case 8: this.$ = [$$[$0-1], $$[$0]];
-break;
-case 9: this.$ = $$[$0];
-break;
-case 10: this.$ = $$[$0];
-break;
-case 11: this.$ = {}; this.$[$$[$0]] = 0;
-break;
-case 12: this.$ = $$[$0-1]; this.$[$$[$0]] = 0;
-break;
-case 13: this.$ = {}; this.$[$$[$0]] = 1;
-break;
-case 14: this.$ = $$[$0-1]; this.$[$$[$0]] = 1;
-break;
-case 15: this.$ = $$[$0-1]; this.$.push($$[$0]);
-break;
-case 16: this.$ = [$$[$0]];
-break;
-case 17: this.$ = $$[$0-2] ? [$$[$0-2], $$[$0-1], $$[$0]] : [$$[$0-1],$$[$0]];
-break;
-case 18:this.$ = $$[$0-1];
-break;
-case 19:this.$ = $$[$0];
-break;
-case 20:this.$ = '';
-break;
-case 21:this.$ = yytext;
-break;
-case 22:this.$ = $$[$0-4]+$$[$0-3]+$$[$0-2]+$$[$0-1]+$$[$0];
-break;
-case 23:this.$ = $$[$0-3]+$$[$0-2]+$$[$0-1]+$$[$0];
-break;
-case 24: this.$ = $$[$0-1];
-break;
-case 25: this.$ = ['*'];
-break;
-case 27: this.$ = [$$[$0]];
-break;
-case 28: this.$ = $$[$0-2]; this.$.push($$[$0]);
-break;
-case 29: this.$ = $$[$0];
- if (!(yy.options && yy.options.flex) && this.$.match(/[\w\d]$/) && !this.$.match(/\\(b|c[A-Z]|x[0-9A-F]{2}|u[a-fA-F0-9]{4}|[0-7]{1,3})$/))
- this.$ += "\\b";
-
-break;
-case 30: this.$ = $$[$0-2]+'|'+$$[$0];
-break;
-case 31: this.$ = $$[$0-1]+'|';
-break;
-case 33: this.$ = ''
-break;
-case 34: this.$ = $$[$0-1]+$$[$0];
-break;
-case 36: this.$ = '('+$$[$0-1]+')';
-break;
-case 37: this.$ = $$[$0-2]+$$[$0-1]+')';
-break;
-case 38: this.$ = $$[$0-1]+'+';
-break;
-case 39: this.$ = $$[$0-1]+'*';
-break;
-case 40: this.$ = $$[$0-1]+'?';
-break;
-case 41: this.$ = '(?='+$$[$0]+')';
-break;
-case 42: this.$ = '(?!'+$$[$0]+')';
-break;
-case 44: this.$ = $$[$0-1]+$$[$0];
-break;
-case 46: this.$ = '.';
-break;
-case 47: this.$ = '^';
-break;
-case 48: this.$ = '$';
-break;
-case 52: this.$ = yytext;
-break;
-case 53: this.$ = yytext;
-break;
-case 54: this.$ = yytext;
-break;
-case 55: this.$ = yy.prepareString(yytext.substr(1, yytext.length-2));
-break;
-}
-},
-table: [{3:1,4:2,5:[2,7],10:3,11:[1,4],12:[1,5],14:[1,6],16:[1,7]},{1:[3]},{5:[1,8]},{4:9,5:[2,7],10:3,11:[1,4],12:[1,5],14:[1,6],16:[1,7]},{4:10,5:[2,7],10:3,11:[1,4],12:[1,5],14:[1,6],16:[1,7]},{5:[2,33],11:[2,33],12:[2,33],13:11,14:[2,33],16:[2,33],31:12,32:[2,33],33:13,34:14,35:[1,15],37:[1,16],40:[1,17],41:[1,18],42:19,44:20,45:[1,21],46:[1,22],47:[1,23],48:24,49:25,50:[1,26],51:[1,27],52:[1,30],54:[1,28],55:[1,29]},{15:31,18:[1,32]},{17:33,18:[1,34]},{6:35,11:[2,26],19:36,20:37,22:[2,26],26:[1,38],32:[2,26],35:[2,26],37:[2,26],40:[2,26],41:[2,26],45:[2,26],46:[2,26],47:[2,26],50:[2,26],51:[2,26],52:[2,26],54:[2,26],55:[2,26]},{5:[2,5]},{5:[2,6]},{5:[2,8],11:[2,8],12:[2,8],14:[2,8],16:[2,8]},{5:[2,29],11:[2,29],12:[2,29],14:[2,29],16:[2,29],22:[2,29],32:[1,39]},{5:[2,32],11:[2,32],12:[2,32],14:[2,32],16:[2,32],22:[2,32],32:[2,32],34:40,35:[1,15],36:[2,32],37:[1,16],40:[1,17],41:[1,18],42:19,44:20,45:[1,21],46:[1,22],47:[1,23],48:24,49:25,50:[1,26],51:[1,27],52:[1,30],54:[1,28],55:[1,29]},{5:[2,35],11:[2,35],12:[2,35],14:[2,35],16:[2,35],22:[2,35],29:[1,42],32:[2,35],35:[2,35],36:[2,35],37:[2,35],38:[1,41],39:[1,43],40:[2,35],41:[2,35],43:44,45:[2,35],46:[2,35],47:[2,35],50:[2,35],51:[2,35],52:[2,35],53:[1,45],54:[2,35],55:[2,35]},{31:46,32:[2,33],33:13,34:14,35:[1,15],36:[2,33],37:[1,16],40:[1,17],41:[1,18],42:19,44:20,45:[1,21],46:[1,22],47:[1,23],48:24,49:25,50:[1,26],51:[1,27],52:[1,30],54:[1,28],55:[1,29]},{31:47,32:[2,33],33:13,34:14,35:[1,15],36:[2,33],37:[1,16],40:[1,17],41:[1,18],42:19,44:20,45:[1,21],46:[1,22],47:[1,23],48:24,49:25,50:[1,26],51:[1,27],52:[1,30],54:[1,28],55:[1,29]},{34:48,35:[1,15],37:[1,16],40:[1,17],41:[1,18],42:19,44:20,45:[1,21],46:[1,22],47:[1,23],48:24,49:25,50:[1,26],51:[1,27],52:[1,30],54:[1,28],55:[1,29]},{34:49,35:[1,15],37:[1,16],40:[1,17],41:[1,18],42:19,44:20,45:[1,21],46:[1,22],47:[1,23],48:24,49:25,50:[1,26],51:[1,27],52:[1,30],54:[1,28],55:[1,29]},{5:[2,43],11:[2,43],12:[2,43],14:[2,43],16:[2,43],22:[2,43],29:[2,43],32:[2,43],35:[2,43],36:[2,43],37:[2,43],38:[2,43],39:[2,43],40:[2,43],41:[2,43],45:[2,43],46:[2,43],47:[2,43],50:[2,43],51:[2,43],52:[2,43],53:[2,43],54:[2,43],55:[2,43]},{5:[2,45],11:[2,45],12:[2,45],14:[2,45],16:[2,45],22:[2,45],29:[2,45],32:[2,45],35:[2,45],36:[2,45],37:[2,45],38:[2,45],39:[2,45],40:[2,45],41:[2,45],45:[2,45],46:[2,45],47:[2,45],50:[2,45],51:[2,45],52:[2,45],53:[2,45],54:[2,45],55:[2,45]},{5:[2,46],11:[2,46],12:[2,46],14:[2,46],16:[2,46],22:[2,46],29:[2,46],32:[2,46],35:[2,46],36:[2,46],37:[2,46],38:[2,46],39:[2,46],40:[2,46],41:[2,46],45:[2,46],46:[2,46],47:[2,46],50:[2,46],51:[2,46],52:[2,46],53:[2,46],54:[2,46],55:[2,46]},{5:[2,47],11:[2,47],12:[2,47],14:[2,47],16:[2,47],22:[2,47],29:[2,47],32:[2,47],35:[2,47],36:[2,47],37:[2,47],38:[2,47],39:[2,47],40:[2,47],41:[2,47],45:[2,47],46:[2,47],47:[2,47],50:[2,47],51:[2,47],52:[2,47],53:[2,47],54:[2,47],55:[2,47]},{5:[2,48],11:[2,48],12:[2,48],14:[2,48],16:[2,48],22:[2,48],29:[2,48],32:[2,48],35:[2,48],36:[2,48],37:[2,48],38:[2,48],39:[2,48],40:[2,48],41:[2,48],45:[2,48],46:[2,48],47:[2,48],50:[2,48],51:[2,48],52:[2,48],53:[2,48],54:[2,48],55:[2,48]},{5:[2,49],11:[2,49],12:[2,49],14:[2,49],16:[2,49],22:[2,49],29:[2,49],32:[2,49],35:[2,49],36:[2,49],37:[2,49],38:[2,49],39:[2,49],40:[2,49],41:[2,49],45:[2,49],46:[2,49],47:[2,49],50:[2,49],51:[2,49],52:[2,49],53:[2,49],54:[2,49],55:[2,49]},{5:[2,50],11:[2,50],12:[2,50],14:[2,50],16:[2,50],22:[2,50],29:[2,50],32:[2,50],35:[2,50],36:[2,50],37:[2,50],38:[2,50],39:[2,50],40:[2,50],41:[2,50],45:[2,50],46:[2,50],47:[2,50],50:[2,50],51:[2,50],52:[2,50],53:[2,50],54:[2,50],55:[2,50]},{5:[2,51],11:[2,51],12:[2,51],14:[2,51],16:[2,51],22:[2,51],29:[2,51],32:[2,51],35:[2,51],36:[2,51],37:[2,51],38:[2,51],39:[2,51],40:[2,51],41:[2,51],45:[2,51],46:[2,51],47:[2,51],50:[2,51],51:[2,51],52:[2,51],53:[2,51],54:[2,51],55:[2,51]},{5:[2,52],11:[2,52],12:[2,52],14:[2,52],16:[2,52],22:[2,52],29:[2,52],32:[2,52],35:[2,52],36:[2,52],37:[2,52],38:[2,52],39:[2,52],40:[2,52],41:[2,52],45:[2,52],46:[2,52],47:[2,52],50:[2,52],51:[2,52],52:[2,52],53:[2,52],54:[2,52],55:[2,52]},{5:[2,55],11:[2,55],12:[2,55],14:[2,55],16:[2,55],22:[2,55],29:[2,55],32:[2,55],35:[2,55],36:[2,55],37:[2,55],38:[2,55],39:[2,55],40:[2,55],41:[2,55],45:[2,55],46:[2,55],47:[2,55],50:[2,55],51:[2,55],52:[2,55],53:[2,55],54:[2,55],55:[2,55]},{5:[2,56],11:[2,56],12:[2,56],14:[2,56],16:[2,56],22:[2,56],29:[2,56],32:[2,56],35:[2,56],36:[2,56],37:[2,56],38:[2,56],39:[2,56],40:[2,56],41:[2,56],45:[2,56],46:[2,56],47:[2,56],50:[2,56],51:[2,56],52:[2,56],53:[2,56],54:[2,56],55:[2,56]},{5:[2,53],11:[2,53],12:[2,53],14:[2,53],16:[2,53],22:[2,53],29:[2,53],32:[2,53],35:[2,53],36:[2,53],37:[2,53],38:[2,53],39:[2,53],40:[2,53],41:[2,53],45:[2,53],46:[2,53],47:[2,53],50:[2,53],51:[2,53],52:[2,53],53:[2,53],54:[2,53],55:[2,53]},{5:[2,9],11:[2,9],12:[2,9],14:[2,9],16:[2,9],18:[1,50]},{5:[2,11],11:[2,11],12:[2,11],14:[2,11],16:[2,11],18:[2,11]},{5:[2,10],11:[2,10],12:[2,10],14:[2,10],16:[2,10],18:[1,51]},{5:[2,13],11:[2,13],12:[2,13],14:[2,13],16:[2,13],18:[2,13]},{5:[1,55],7:52,8:[1,54],11:[2,26],19:53,20:37,22:[2,26],26:[1,38],32:[2,26],35:[2,26],37:[2,26],40:[2,26],41:[2,26],45:[2,26],46:[2,26],47:[2,26],50:[2,26],51:[2,26],52:[2,26],54:[2,26],55:[2,26]},{5:[2,16],8:[2,16],11:[2,16],22:[2,16],26:[2,16],32:[2,16],35:[2,16],37:[2,16],40:[2,16],41:[2,16],45:[2,16],46:[2,16],47:[2,16],50:[2,16],51:[2,16],52:[2,16],54:[2,16],55:[2,16]},{11:[2,33],13:56,22:[2,33],31:12,32:[2,33],33:13,34:14,35:[1,15],37:[1,16],40:[1,17],41:[1,18],42:19,44:20,45:[1,21],46:[1,22],47:[1,23],48:24,49:25,50:[1,26],51:[1,27],52:[1,30],54:[1,28],55:[1,29]},{12:[1,59],27:57,29:[1,58]},{5:[2,31],11:[2,31],12:[2,31],14:[2,31],16:[2,31],22:[2,31],32:[2,31],33:60,34:14,35:[1,15],36:[2,31],37:[1,16],40:[1,17],41:[1,18],42:19,44:20,45:[1,21],46:[1,22],47:[1,23],48:24,49:25,50:[1,26],51:[1,27],52:[1,30],54:[1,28],55:[1,29]},{5:[2,34],11:[2,34],12:[2,34],14:[2,34],16:[2,34],22:[2,34],29:[1,42],32:[2,34],35:[2,34],36:[2,34],37:[2,34],38:[1,41],39:[1,43],40:[2,34],41:[2,34],43:44,45:[2,34],46:[2,34],47:[2,34],50:[2,34],51:[2,34],52:[2,34],53:[1,45],54:[2,34],55:[2,34]},{5:[2,38],11:[2,38],12:[2,38],14:[2,38],16:[2,38],22:[2,38],29:[2,38],32:[2,38],35:[2,38],36:[2,38],37:[2,38],38:[2,38],39:[2,38],40:[2,38],41:[2,38],45:[2,38],46:[2,38],47:[2,38],50:[2,38],51:[2,38],52:[2,38],53:[2,38],54:[2,38],55:[2,38]},{5:[2,39],11:[2,39],12:[2,39],14:[2,39],16:[2,39],22:[2,39],29:[2,39],32:[2,39],35:[2,39],36:[2,39],37:[2,39],38:[2,39],39:[2,39],40:[2,39],41:[2,39],45:[2,39],46:[2,39],47:[2,39],50:[2,39],51:[2,39],52:[2,39],53:[2,39],54:[2,39],55:[2,39]},{5:[2,40],11:[2,40],12:[2,40],14:[2,40],16:[2,40],22:[2,40],29:[2,40],32:[2,40],35:[2,40],36:[2,40],37:[2,40],38:[2,40],39:[2,40],40:[2,40],41:[2,40],45:[2,40],46:[2,40],47:[2,40],50:[2,40],51:[2,40],52:[2,40],53:[2,40],54:[2,40],55:[2,40]},{5:[2,44],11:[2,44],12:[2,44],14:[2,44],16:[2,44],22:[2,44],29:[2,44],32:[2,44],35:[2,44],36:[2,44],37:[2,44],38:[2,44],39:[2,44],40:[2,44],41:[2,44],45:[2,44],46:[2,44],47:[2,44],50:[2,44],51:[2,44],52:[2,44],53:[2,44],54:[2,44],55:[2,44]},{5:[2,54],11:[2,54],12:[2,54],14:[2,54],16:[2,54],22:[2,54],29:[2,54],32:[2,54],35:[2,54],36:[2,54],37:[2,54],38:[2,54],39:[2,54],40:[2,54],41:[2,54],45:[2,54],46:[2,54],47:[2,54],50:[2,54],51:[2,54],52:[2,54],53:[2,54],54:[2,54],55:[2,54]},{32:[1,39],36:[1,61]},{32:[1,39],36:[1,62]},{5:[2,41],11:[2,41],12:[2,41],14:[2,41],16:[2,41],22:[2,41],29:[1,42],32:[2,41],35:[2,41],36:[2,41],37:[2,41],38:[1,41],39:[1,43],40:[2,41],41:[2,41],43:44,45:[2,41],46:[2,41],47:[2,41],50:[2,41],51:[2,41],52:[2,41],53:[1,45],54:[2,41],55:[2,41]},{5:[2,42],11:[2,42],12:[2,42],14:[2,42],16:[2,42],22:[2,42],29:[1,42],32:[2,42],35:[2,42],36:[2,42],37:[2,42],38:[1,41],39:[1,43],40:[2,42],41:[2,42],43:44,45:[2,42],46:[2,42],47:[2,42],50:[2,42],51:[2,42],52:[2,42],53:[1,45],54:[2,42],55:[2,42]},{5:[2,12],11:[2,12],12:[2,12],14:[2,12],16:[2,12],18:[2,12]},{5:[2,14],11:[2,14],12:[2,14],14:[2,14],16:[2,14],18:[2,14]},{1:[2,1]},{5:[2,15],8:[2,15],11:[2,15],22:[2,15],26:[2,15],32:[2,15],35:[2,15],37:[2,15],40:[2,15],41:[2,15],45:[2,15],46:[2,15],47:[2,15],50:[2,15],51:[2,15],52:[2,15],54:[2,15],55:[2,15]},{1:[2,2]},{8:[1,63],9:[1,64]},{11:[1,67],21:65,22:[1,66]},{28:[1,68],30:[1,69]},{28:[1,70]},{28:[2,27],30:[2,27]},{5:[2,30],11:[2,30],12:[2,30],14:[2,30],16:[2,30],22:[2,30],32:[2,30],34:40,35:[1,15],36:[2,30],37:[1,16],40:[1,17],41:[1,18],42:19,44:20,45:[1,21],46:[1,22],47:[1,23],48:24,49:25,50:[1,26],51:[1,27],52:[1,30],54:[1,28],55:[1,29]},{5:[2,36],11:[2,36],12:[2,36],14:[2,36],16:[2,36],22:[2,36],29:[2,36],32:[2,36],35:[2,36],36:[2,36],37:[2,36],38:[2,36],39:[2,36],40:[2,36],41:[2,36],45:[2,36],46:[2,36],47:[2,36],50:[2,36],51:[2,36],52:[2,36],53:[2,36],54:[2,36],55:[2,36]},{5:[2,37],11:[2,37],12:[2,37],14:[2,37],16:[2,37],22:[2,37],29:[2,37],32:[2,37],35:[2,37],36:[2,37],37:[2,37],38:[2,37],39:[2,37],40:[2,37],41:[2,37],45:[2,37],46:[2,37],47:[2,37],50:[2,37],51:[2,37],52:[2,37],53:[2,37],54:[2,37],55:[2,37]},{1:[2,3]},{8:[1,71]},{5:[2,17],8:[2,17],11:[2,17],22:[2,17],26:[2,17],32:[2,17],35:[2,17],37:[2,17],40:[2,17],41:[2,17],45:[2,17],46:[2,17],47:[2,17],50:[2,17],51:[2,17],52:[2,17],54:[2,17],55:[2,17]},{22:[2,20],23:72,24:[2,20],25:[1,73]},{5:[2,19],8:[2,19],11:[2,19],22:[2,19],26:[2,19],32:[2,19],35:[2,19],37:[2,19],40:[2,19],41:[2,19],45:[2,19],46:[2,19],47:[2,19],50:[2,19],51:[2,19],52:[2,19],54:[2,19],55:[2,19]},{11:[2,24],22:[2,24],32:[2,24],35:[2,24],37:[2,24],40:[2,24],41:[2,24],45:[2,24],46:[2,24],47:[2,24],50:[2,24],51:[2,24],52:[2,24],54:[2,24],55:[2,24]},{12:[1,74]},{11:[2,25],22:[2,25],32:[2,25],35:[2,25],37:[2,25],40:[2,25],41:[2,25],45:[2,25],46:[2,25],47:[2,25],50:[2,25],51:[2,25],52:[2,25],54:[2,25],55:[2,25]},{1:[2,4]},{22:[1,76],24:[1,75]},{22:[2,21],24:[2,21]},{28:[2,28],30:[2,28]},{5:[2,18],8:[2,18],11:[2,18],22:[2,18],26:[2,18],32:[2,18],35:[2,18],37:[2,18],40:[2,18],41:[2,18],45:[2,18],46:[2,18],47:[2,18],50:[2,18],51:[2,18],52:[2,18],54:[2,18],55:[2,18]},{22:[2,20],23:77,24:[2,20],25:[1,73]},{22:[1,76],24:[1,78]},{22:[2,23],24:[2,23],25:[1,79]},{22:[2,22],24:[2,22]}],
-defaultActions: {9:[2,5],10:[2,6],52:[2,1],54:[2,2],63:[2,3],71:[2,4]},
-parseError: function parseError(str, hash) {
- throw new Error(str);
-},
-parse: function parse(input) {
- var self = this, stack = [0], vstack = [null], lstack = [], table = this.table, yytext = "", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
- this.lexer.setInput(input);
- this.lexer.yy = this.yy;
- this.yy.lexer = this.lexer;
- this.yy.parser = this;
- if (typeof this.lexer.yylloc == "undefined")
- this.lexer.yylloc = {};
- var yyloc = this.lexer.yylloc;
- lstack.push(yyloc);
- var ranges = this.lexer.options && this.lexer.options.ranges;
- if (typeof this.yy.parseError === "function")
- this.parseError = this.yy.parseError;
- function popStack(n) {
- stack.length = stack.length - 2 * n;
- vstack.length = vstack.length - n;
- lstack.length = lstack.length - n;
- }
- function lex() {
- var token;
- token = self.lexer.lex() || 1;
- if (typeof token !== "number") {
- token = self.symbols_[token] || token;
- }
- return token;
- }
- var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
- while (true) {
- state = stack[stack.length - 1];
- if (this.defaultActions[state]) {
- action = this.defaultActions[state];
- } else {
- if (symbol === null || typeof symbol == "undefined") {
- symbol = lex();
- }
- action = table[state] && table[state][symbol];
- }
- if (typeof action === "undefined" || !action.length || !action[0]) {
- var errStr = "";
- if (!recovering) {
- expected = [];
- for (p in table[state])
- if (this.terminals_[p] && p > 2) {
- expected.push("'" + this.terminals_[p] + "'");
- }
- if (this.lexer.showPosition) {
- errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'";
- } else {
- errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1?"end of input":"'" + (this.terminals_[symbol] || symbol) + "'");
- }
- this.parseError(errStr, {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});
- }
- }
- if (action[0] instanceof Array && action.length > 1) {
- throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol);
- }
- switch (action[0]) {
- case 1:
- stack.push(symbol);
- vstack.push(this.lexer.yytext);
- lstack.push(this.lexer.yylloc);
- stack.push(action[1]);
- symbol = null;
- if (!preErrorSymbol) {
- yyleng = this.lexer.yyleng;
- yytext = this.lexer.yytext;
- yylineno = this.lexer.yylineno;
- yyloc = this.lexer.yylloc;
- if (recovering > 0)
- recovering--;
- } else {
- symbol = preErrorSymbol;
- preErrorSymbol = null;
- }
- break;
- case 2:
- len = this.productions_[action[1]][1];
- yyval.$ = vstack[vstack.length - len];
- yyval._$ = {first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column};
- if (ranges) {
- yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
- }
- r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
- if (typeof r !== "undefined") {
- return r;
- }
- if (len) {
- stack = stack.slice(0, -1 * len * 2);
- vstack = vstack.slice(0, -1 * len);
- lstack = lstack.slice(0, -1 * len);
- }
- stack.push(this.productions_[action[1]][0]);
- vstack.push(yyval.$);
- lstack.push(yyval._$);
- newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
- stack.push(newState);
- break;
- case 3:
- return true;
- }
- }
- return true;
-}
-};
-/* Jison generated lexer */
-var lexer = (function(){
-var lexer = ({EOF:1,
-parseError:function parseError(str, hash) {
- if (this.yy.parser) {
- this.yy.parser.parseError(str, hash);
- } else {
- throw new Error(str);
- }
- },
-setInput:function (input) {
- this._input = input;
- this._more = this._less = this.done = false;
- this.yylineno = this.yyleng = 0;
- this.yytext = this.matched = this.match = '';
- this.conditionStack = ['INITIAL'];
- this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0};
- if (this.options.ranges) this.yylloc.range = [0,0];
- this.offset = 0;
- return this;
- },
-input:function () {
- var ch = this._input[0];
- this.yytext += ch;
- this.yyleng++;
- this.offset++;
- this.match += ch;
- this.matched += ch;
- var lines = ch.match(/(?:\r\n?|\n).*/g);
- if (lines) {
- this.yylineno++;
- this.yylloc.last_line++;
- } else {
- this.yylloc.last_column++;
- }
- if (this.options.ranges) this.yylloc.range[1]++;
-
- this._input = this._input.slice(1);
- return ch;
- },
-unput:function (ch) {
- var len = ch.length;
- var lines = ch.split(/(?:\r\n?|\n)/g);
-
- this._input = ch + this._input;
- this.yytext = this.yytext.substr(0, this.yytext.length-len-1);
- //this.yyleng -= len;
- this.offset -= len;
- var oldLines = this.match.split(/(?:\r\n?|\n)/g);
- this.match = this.match.substr(0, this.match.length-1);
- this.matched = this.matched.substr(0, this.matched.length-1);
-
- if (lines.length-1) this.yylineno -= lines.length-1;
- var r = this.yylloc.range;
-
- this.yylloc = {first_line: this.yylloc.first_line,
- last_line: this.yylineno+1,
- first_column: this.yylloc.first_column,
- last_column: lines ?
- (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length:
- this.yylloc.first_column - len
- };
-
- if (this.options.ranges) {
- this.yylloc.range = [r[0], r[0] + this.yyleng - len];
- }
- return this;
- },
-more:function () {
- this._more = true;
- return this;
- },
-less:function (n) {
- this.unput(this.match.slice(n));
- },
-pastInput:function () {
- var past = this.matched.substr(0, this.matched.length - this.match.length);
- return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
- },
-upcomingInput:function () {
- var next = this.match;
- if (next.length < 20) {
- next += this._input.substr(0, 20-next.length);
- }
- return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, "");
- },
-showPosition:function () {
- var pre = this.pastInput();
- var c = new Array(pre.length + 1).join("-");
- return pre + this.upcomingInput() + "\n" + c+"^";
- },
-next:function () {
- if (this.done) {
- return this.EOF;
- }
- if (!this._input) this.done = true;
-
- var token,
- match,
- tempMatch,
- index,
- col,
- lines;
- if (!this._more) {
- this.yytext = '';
- this.match = '';
- }
- var rules = this._currentRules();
- for (var i=0;i < rules.length; i++) {
- tempMatch = this._input.match(this.rules[rules[i]]);
- if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
- match = tempMatch;
- index = i;
- if (!this.options.flex) break;
- }
- }
- if (match) {
- lines = match[0].match(/(?:\r\n?|\n).*/g);
- if (lines) this.yylineno += lines.length;
- this.yylloc = {first_line: this.yylloc.last_line,
- last_line: this.yylineno+1,
- first_column: this.yylloc.last_column,
- last_column: lines ? lines[lines.length-1].length-lines[lines.length-1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length};
- this.yytext += match[0];
- this.match += match[0];
- this.matches = match;
- this.yyleng = this.yytext.length;
- if (this.options.ranges) {
- this.yylloc.range = [this.offset, this.offset += this.yyleng];
- }
- this._more = false;
- this._input = this._input.slice(match[0].length);
- this.matched += match[0];
- token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]);
- if (this.done && this._input) this.done = false;
- if (token) return token;
- else return;
- }
- if (this._input === "") {
- return this.EOF;
- } else {
- return this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(),
- {text: "", token: null, line: this.yylineno});
- }
- },
-lex:function lex() {
- var r = this.next();
- if (typeof r !== 'undefined') {
- return r;
- } else {
- return this.lex();
- }
- },
-begin:function begin(condition) {
- this.conditionStack.push(condition);
- },
-popState:function popState() {
- return this.conditionStack.pop();
- },
-_currentRules:function _currentRules() {
- return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules;
- },
-topState:function () {
- return this.conditionStack[this.conditionStack.length-2];
- },
-pushState:function begin(condition) {
- this.begin(condition);
- }});
-lexer.options = {};
-lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
-
-var YYSTATE=YY_START
-switch($avoiding_name_collisions) {
-case 0:return 25
-break;
-case 1:yy.depth++; return 22
-break;
-case 2:yy.depth == 0 ? this.begin('trail') : yy.depth--; return 24
-break;
-case 3:return 12
-break;
-case 4:this.popState(); return 28
-break;
-case 5:return 30
-break;
-case 6:return 29
-break;
-case 7:/* */
-break;
-case 8:this.begin('indented')
-break;
-case 9:this.begin('code'); return 5
-break;
-case 10:return 55
-break;
-case 11:yy.options[yy_.yytext] = true
-break;
-case 12:this.begin('INITIAL')
-break;
-case 13:this.begin('INITIAL')
-break;
-case 14:/* empty */
-break;
-case 15:return 18
-break;
-case 16:this.begin('INITIAL')
-break;
-case 17:this.begin('INITIAL')
-break;
-case 18:/* empty */
-break;
-case 19:this.begin('rules')
-break;
-case 20:yy.depth = 0; this.begin('action'); return 22
-break;
-case 21:this.begin('trail'); yy_.yytext = yy_.yytext.substr(2, yy_.yytext.length-4);return 11
-break;
-case 22:yy_.yytext = yy_.yytext.substr(2, yy_.yytext.length-4); return 11
-break;
-case 23:this.begin('rules'); return 11
-break;
-case 24:/* ignore */
-break;
-case 25:/* ignore */
-break;
-case 26:/* */
-break;
-case 27:/* */
-break;
-case 28:return 12
-break;
-case 29:yy_.yytext = yy_.yytext.replace(/\\"/g,'"');return 54
-break;
-case 30:yy_.yytext = yy_.yytext.replace(/\\'/g,"'");return 54
-break;
-case 31:return 32
-break;
-case 32:return 51
-break;
-case 33:return 37
-break;
-case 34:return 37
-break;
-case 35:return 37
-break;
-case 36:return 35
-break;
-case 37:return 36
-break;
-case 38:return 38
-break;
-case 39:return 29
-break;
-case 40:return 39
-break;
-case 41:return 46
-break;
-case 42:return 30
-break;
-case 43:return 47
-break;
-case 44:this.begin('conditions'); return 26
-break;
-case 45:return 41
-break;
-case 46:return 40
-break;
-case 47:return 52
-break;
-case 48:yy_.yytext = yy_.yytext.replace(/^\\/g,''); return 52
-break;
-case 49:return 47
-break;
-case 50:return 45
-break;
-case 51:yy.options = {}; this.begin('options')
-break;
-case 52:this.begin('start_condition');return 14
-break;
-case 53:this.begin('start_condition');return 16
-break;
-case 54:this.begin('rules'); return 5
-break;
-case 55:return 53
-break;
-case 56:return 50
-break;
-case 57:return 22
-break;
-case 58:return 24
-break;
-case 59:/* ignore bad characters */
-break;
-case 60:return 8
-break;
-case 61:return 9
-break;
-}
-};
-lexer.rules = [/^(?:[^{}]+)/,/^(?:\{)/,/^(?:\})/,/^(?:([a-zA-Z_][a-zA-Z0-9_-]*))/,/^(?:>)/,/^(?:,)/,/^(?:\*)/,/^(?:\n+)/,/^(?:\s+)/,/^(?:%%)/,/^(?:[a-zA-Z0-9_]+)/,/^(?:([a-zA-Z_][a-zA-Z0-9_-]*))/,/^(?:\n+)/,/^(?:\s+\n+)/,/^(?:\s+)/,/^(?:([a-zA-Z_][a-zA-Z0-9_-]*))/,/^(?:\n+)/,/^(?:\s+\n+)/,/^(?:\s+)/,/^(?:.*\n+)/,/^(?:\{)/,/^(?:%\{(.|\n)*?%\})/,/^(?:%\{(.|\n)*?%\})/,/^(?:.+)/,/^(?:\/\*(.|\n|\r)*?\*\/)/,/^(?:\/\/.*)/,/^(?:\n+)/,/^(?:\s+)/,/^(?:([a-zA-Z_][a-zA-Z0-9_-]*))/,/^(?:"(\\\\|\\"|[^"])*")/,/^(?:'(\\\\|\\'|[^'])*')/,/^(?:\|)/,/^(?:\[(\\\\|\\\]|[^\]])*\])/,/^(?:\(\?:)/,/^(?:\(\?=)/,/^(?:\(\?!)/,/^(?:\()/,/^(?:\))/,/^(?:\+)/,/^(?:\*)/,/^(?:\?)/,/^(?:\^)/,/^(?:,)/,/^(?:<>)/,/^(?:<)/,/^(?:\/!)/,/^(?:\/)/,/^(?:\\([0-7]{1,3}|[rfntvsSbBwWdD\\*+()${}|[\]\/.^?]|c[A-Z]|x[0-9A-F]{2}|u[a-fA-F0-9]{4}))/,/^(?:\\.)/,/^(?:\$)/,/^(?:\.)/,/^(?:%options\b)/,/^(?:%s\b)/,/^(?:%x\b)/,/^(?:%%)/,/^(?:\{\d+(,\s?\d+|,)?\})/,/^(?:\{([a-zA-Z_][a-zA-Z0-9_-]*)\})/,/^(?:\{)/,/^(?:\})/,/^(?:.)/,/^(?:$)/,/^(?:(.|\n)+)/];
-lexer.conditions = {"code":{"rules":[60,61],"inclusive":false},"start_condition":{"rules":[15,16,17,18,60],"inclusive":false},"options":{"rules":[11,12,13,14,60],"inclusive":false},"conditions":{"rules":[3,4,5,6,60],"inclusive":false},"action":{"rules":[0,1,2,60],"inclusive":false},"indented":{"rules":[20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60],"inclusive":true},"trail":{"rules":[19,22,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60],"inclusive":true},"rules":{"rules":[7,8,9,10,22,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60],"inclusive":true},"INITIAL":{"rules":[22,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60],"inclusive":true}};
-
-
-;
-return lexer;})()
-parser.lexer = lexer;
-function Parser () { this.yy = {}; }Parser.prototype = parser;parser.Parser = Parser;
-return new Parser;
-})();
-if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
-exports.parser = jisonlex;
-exports.Parser = jisonlex.Parser;
-exports.parse = function () { return jisonlex.parse.apply(jisonlex, arguments); }
-exports.main = function commonjsMain(args) {
- if (!args[1])
- throw new Error('Usage: '+args[0]+' FILE');
- var source, cwd;
- if (typeof process !== 'undefined') {
- source = require("fs").readFileSync(require("path").resolve(args[1]), "utf8");
- } else {
- source = require("file").path(require("file").cwd()).join(args[1]).read({charset: "utf-8"});
- }
- return exports.parser.parse(source);
-}
-if (typeof module !== 'undefined' && require.main === module) {
- exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require("system").args);
-}
-}
-//*/
-},requires:["fs","path","file","file","system"]});;
-return require;
-})();
\ No newline at end of file
diff --git a/lib/inventory_fallback.js b/lib/inventory_fallback.js
deleted file mode 100644
index ec4072c8..00000000
--- a/lib/inventory_fallback.js
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- Steam inventories are a mess, adds a fallback onto a deprecated inventory endpoint
-
- We effectively just override some of the inventory URL functions
- */
-
-function CInventory_GetInventoryLoadURL_CSGOFloat() {
- if (g_InventoryFallbackCSGOFloat) {
- return `https://steamcommunity.com/profiles/${this.m_steamid}/inventory/json/${this.m_appid}/${this.m_contextid}`;
- } else {
- /* Fallback to the upstream method */
- return this.g_GetInventoryLoadURL();
- }
-}
-
-function CInventory_AddInventoryData_CSGOFloat(data) {
- if (!g_InventoryFallbackCSGOFloat) {
- /* upstream can handle */
- return this.g_AddInventoryData(data);
- }
-
- /* Preprocess the data to match the other inventory format */
- if (!data || !data.success) {
- alert('failed to fetch inventory');
- return;
- }
-
- const assets = Object.values(data.rgInventory).map(asset => {
- return {
- appid: this.m_appid,
- contextid: this.m_contextid,
- assetid: asset.id,
- classid: asset.classid,
- instanceid: asset.instanceid,
- amount: asset.amount,
- m_pos: asset.pos,
- };
- }).sort((a, b) => a.m_pos - b.m_pos);
-
- const transformedData = {
- assets,
- descriptions: Object.values(data.rgDescriptions),
- total_inventory_count: Math.max(...assets.map(e => e.m_pos)),
- success: true,
- more_items: 0,
- rwgrsn: -2
- };
-
- /* Required to force the page to lazy load images correctly */
- this.m_bNeedsRepagination = true;
-
- return this.g_AddInventoryData(transformedData);
-}
-
-function CInventory_ShowInventoryLoadError_CSGOFloat() {
- const prev_$ErrorDisplay = this.m_$ErrorDisplay;
-
- /* Handle upstream like before */
- this.g_ShowInventoryLoadError();
-
- if (prev_$ErrorDisplay) {
- /* Element already created, nothing special to do */
- return;
- }
-
- this.m_$ErrorDisplay.find(".retry_load_btn").after(`
-
- Try Again using CSGOFloat
-
- `);
- this.m_$ErrorDisplay.find(".retry_load_btn_csgofloat").click(() => {
- g_InventoryFallbackCSGOFloat = true;
- this.RetryLoad()
- });
-}
-
-let fallbackScript = document.createElement('script');
-fallbackScript.innerText = `
- g_InventoryFallbackCSGOFloat = false;
- /* Keep old func references */
- CInventory.prototype.g_GetInventoryLoadURL = CInventory.prototype.GetInventoryLoadURL;
- CInventory.prototype.g_AddInventoryData = CInventory.prototype.AddInventoryData;
- CInventory.prototype.g_ShowInventoryLoadError = CInventory.prototype.ShowInventoryLoadError;
-
- ${CInventory_GetInventoryLoadURL_CSGOFloat.toString()}
- ${CInventory_AddInventoryData_CSGOFloat.toString()}
- ${CInventory_ShowInventoryLoadError_CSGOFloat.toString()}
-
- CInventory.prototype.GetInventoryLoadURL = CInventory_GetInventoryLoadURL_CSGOFloat;
- CInventory.prototype.AddInventoryData = CInventory_AddInventoryData_CSGOFloat;
- CInventory.prototype.ShowInventoryLoadError = CInventory_ShowInventoryLoadError_CSGOFloat;
-`;
-
-document.head.appendChild(fallbackScript);
diff --git a/lib/queue.js b/lib/queue.js
deleted file mode 100644
index a7877523..00000000
--- a/lib/queue.js
+++ /dev/null
@@ -1,112 +0,0 @@
-
-class Queue {
- constructor() {
- this.queue = [];
- this.failedRequests = [];
- this.running = false;
- this.concurrency = 10;
- this.processing = 0;
- }
-
- addJob(link, listingId, force) {
- if (listingId in floatData) {
- showFloat(listingId);
- return;
- }
-
- const job = {
- link,
- listingId
- };
-
- // Stop if this item is already in the queue
- if (this.queue.find(j => j.listingId === listingId)) {
- return;
- }
-
- if (!force) {
- // Prevent us from auto-fetching a previously failed request unless it's a user action
- if (this.failedRequests.find(v => v === listingId)) {
- return;
- }
- }
-
- const promise = new Promise((resolve, reject) => {
- job.resolve = resolve;
- job.reject = reject;
- });
-
- this.queue.push(job);
- this.checkQueue();
-
- return promise;
- }
-
- async checkQueue() {
- if (!this.running) return;
-
- if (this.queue.length > 0 && this.processing < this.concurrency) {
- // there is a free bot, process the job
- let job = this.queue.shift();
-
- this.processing += 1;
-
- const floatDiv = document.querySelector(`#item_${job.listingId}_floatdiv`);
-
- // Changed pages or div not visible, cancel request
- if (!floatDiv || floatDiv.offsetParent === null) {
- this.processing -= 1;
- this.checkQueue();
- return;
- }
-
- const buttonText = floatDiv.querySelector('#getFloatBtn span');
- if (buttonText) {
- buttonText.fetching = true;
- buttonText.innerText = 'Fetching';
- }
-
- const params = { inspectLink: job.link };
-
- if (isMarketListing(job.listingId)) {
- const listingData = (await retrieveListingInfoFromPage(job.listingId))[job.listingId];
- if (listingData.currencyid === 2001) {
- params.listPrice = listingData.price + listingData.fee;
- } else if (listingData.converted_currencyid === 2001) {
- params.listPrice = listingData.converted_price + listingData.converted_fee;
- }
- }
-
- const data = await sendMessage(params);
-
- if (buttonText) {
- buttonText.fetching = false;
- }
-
- if (data && data.iteminfo) {
- floatData[job.listingId] = data.iteminfo;
- showFloat(job.listingId);
- } else {
- // Reset the button text for this itemid
- if (buttonText) buttonText.innerText = 'Get Float';
-
- // Change the message div for this item to the error
- if (floatDiv && floatDiv.querySelector('.floatmessage')) {
- floatDiv.querySelector('.floatmessage').innerText = data.error || 'Unknown Error';
- }
-
- this.failedRequests.push(job.listingId);
- }
-
- this.processing -= 1;
- this.checkQueue();
- }
- }
-
- start() {
- if (!this.running) {
- this.running = true;
- this.checkQueue();
- }
- }
-}
diff --git a/lib/stall.js b/lib/stall.js
deleted file mode 100644
index bf0770d4..00000000
--- a/lib/stall.js
+++ /dev/null
@@ -1,29 +0,0 @@
-class StallFetcher {
- constructor() {
- // Maps string -> stall items
- this.stalls = {};
- }
-
- async getStallItem(steamId, itemId) {
- if (this.stalls[steamId]) {
- return this.stalls[steamId].listings.find(e => (e.offering || e.item).asset_id === itemId);
- }
-
- let stall;
-
- try {
- stall = await sendMessage({ stall: true, steamId});
- if (!stall.listings) {
- // Stub out to prevent further calls
- stall = {listings: []};
- }
- } catch (e) {
- return;
- }
-
- this.stalls[steamId] = stall;
- return stall.listings.find(e => (e.offering || e.item).asset_id === itemId);
- }
-}
-
-const stallFetcher = new StallFetcher();
diff --git a/lib/time_fetcher.js b/lib/time_fetcher.js
deleted file mode 100644
index 60eb6032..00000000
--- a/lib/time_fetcher.js
+++ /dev/null
@@ -1,171 +0,0 @@
-function historyRowHashcode_CSGOFloat(row) {
- const text = row.innerText.replace(/\W/g, '');
-
- /* Based on https://stackoverflow.com/a/8831937 (Java's hashCode() method) */
- let hash = 0;
- if (text.length === 0) {
- return hash;
- }
- for (let i = 0; i < text.length; i++) {
- const char = text.charCodeAt(i);
- hash = ((hash<<5)-hash)+char;
- hash = hash & hash;
- }
-
- return hash;
-}
-
-function getTimestampFromTrade_CSGOFloat(row) {
- const dateDiv = row.querySelector('.tradehistory_date');
- const date = dateDiv.firstChild.nodeValue.trim();
- const time = dateDiv.querySelector('.tradehistory_timestamp').innerText;
-
- const d = new Date(date);
- const pure = time.replace('am', '').replace('pm', '');
- let hours = parseInt(pure.split(':')[0]);
- const minutes = parseInt(pure.split(':')[1]);
- if (time.includes('pm') && hours !== 12) {
- /* Prevent 12:XXpm from getting 12 hours added */
- hours += 12
- } else if (time.includes('am') && hours === 12) {
- /* Prevent 12:XXam from getting 12 hours instead of being 0 */
- hours -= 12
- }
-
- d.setHours(hours);
- d.setMinutes(minutes);
- return d.getTime() / 1000;
-}
-
-async function addVerifyButtons() {
- let rows = document.querySelectorAll('.tradehistoryrow');
-
- for (const [i, row] of rows.entries()) {
- const btnId = `verify_${i}_csgofloat`;
-
- if (row.querySelector(`#${btnId}`)) {
- // Already placed the button
- continue;
- }
-
- let proveBtn = createButton('CSGOFloat Proof', 'green', btnId);
- proveBtn.addEventListener('click', () => {
- window.postMessage(
- {
- type: 'fetchTime',
- index: i
- },
- '*'
- );
- });
-
- row.querySelector('.tradehistory_content').append(proveBtn);
- }
-}
-
-async function hasTradeBeforeTime_CSGOFloat(hashCode, timestamp) {
- const resp = await fetch(`${location.protocol}//${location.host}${location.pathname}?after_time=${timestamp}&l=english`, {
- credentials: 'same-origin'
- });
-
- const body = await resp.text();
-
- if (body.includes('too many requests')) {
- alert('You need to wait a couple seconds before generating the proof due to Valve rate-limits');
- throw 'Too many requests';
- }
-
- const doc = new DOMParser().parseFromString(body, 'text/html');
- const rows = doc.querySelectorAll('.tradehistoryrow');
-
- for (const row of rows) {
-
- const thisCode = historyRowHashcode_CSGOFloat(row);
- if (thisCode === hashCode) {
- return true;
- }
- }
-
- return false;
-}
-
-async function fetchEnglishRow_CSGOFloat(index) {
- let queryParams = location.search;
- if (queryParams === '') {
- queryParams = '?l=english';
- } else {
- queryParams += '&l=english';
- }
-
- /* Forces us to fetch the english version of the row at a given index no matter what */
- const resp = await fetch(`${location.protocol}//${location.host}${location.pathname}${queryParams}`, {
- credentials: 'same-origin'
- });
-
- const body = await resp.text();
-
- const doc = new DOMParser().parseFromString(body, 'text/html');
- const rows = doc.querySelectorAll('.tradehistoryrow');
- return rows[index];
-}
-
-async function fetchListingTime_CSGOFloat(index) {
- const btn = document.querySelector(`#verify_${index}_csgofloat`);
- btn.querySelector('span').innerText = 'Computing Proof...';
-
- const node = await fetchEnglishRow_CSGOFloat(index);
- const hashCode = historyRowHashcode_CSGOFloat(node);
-
- let timestamp;
-
- try {
- timestamp = getTimestampFromTrade_CSGOFloat(node);
- if (!timestamp) {
- throw 'failed timestamp creation';
- }
- } catch(e) {
- console.error(e);
- alert("Failed to parse time, make sure you're on an english version of the page by appending ?l=english to the url");
- return;
- }
-
- let left = 0, right = 60;
- let amt = 0;
- while (left < right && amt < 5) {
- const middle = left + Math.floor((right - left) / 2);
- const hasTrade = await hasTradeBeforeTime_CSGOFloat(hashCode, timestamp + middle);
- if (hasTrade) {
- right = middle;
- } else {
- left = middle;
- }
- amt++;
- }
-
- /* Hello to all the reversers */
- const proof = timestamp + Math.floor((right + left) / 2);
-
- const span = document.createElement('span');
- span.innerText = `Proof: ${proof}`;
- btn.parentNode.append(span);
- btn.parentNode.removeChild(btn);
-}
-
-// register the message listener in the page scope
-let script = document.createElement('script');
-script.innerText = `
- ${fetchEnglishRow_CSGOFloat.toString()}
- ${hasTradeBeforeTime_CSGOFloat.toString()}
- ${fetchListingTime_CSGOFloat.toString()}
- ${historyRowHashcode_CSGOFloat.toString()}
- ${getTimestampFromTrade_CSGOFloat.toString()}
- window.addEventListener('message', (e) => {
- if (e.data.type == 'fetchTime') {
- fetchListingTime_CSGOFloat(e.data.index);
- }
- });
-`;
-
-document.head.appendChild(script);
-
-addVerifyButtons();
diff --git a/lib/trade_offer.js b/lib/trade_offer.js
deleted file mode 100644
index 7c7fe6ca..00000000
--- a/lib/trade_offer.js
+++ /dev/null
@@ -1,217 +0,0 @@
-const getLogoEl = function () {
- const logo = document.createElement('div');
- logo.style.float = 'left';
- const logoImage = document.createElement('img');
- logoImage.src = 'https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/79/798a12316637ad8fbb91ddb7dc63f770b680bd19_full.jpg';
- logoImage.style.height = '32px';
- logo.appendChild(logoImage);
- return logo;
-};
-
-const createBanner = function (backgroundColor) {
- const banner = document.createElement('div');
- banner.style.marginTop = '10px';
- banner.style.marginBottom = '10px';
- banner.style.padding = '15px';
- banner.style.backgroundColor = backgroundColor;
- banner.style.color = 'white';
- banner.style.display = 'flex';
- banner.style.justifyContent = 'space-between';
- banner.style.alignItems = 'center';
- return banner;
-};
-
-const showWarning = function () {
- const tradeNode = createBanner('#b30000');
-
- const content = document.createElement('div');
- tradeNode.appendChild(content);
-
- content.appendChild(getLogoEl());
-
- const name = document.createElement('span');
- name.style.fontSize = '18px';
- name.style.marginLeft = '15px';
- name.style.lineHeight = '32px';
- name.style.fontWeight = 'bold';
- name.innerText = 'Warning!';
- content.appendChild(name);
-
- const detected = document.createElement('div');
- detected.style.paddingLeft = '45px';
- detected.style.color = 'darkgrey';
- detected.innerText = `Some of the items in the offer were not purchased from you on CSGOFloat Market (or you're logged into the wrong account)`;
- content.appendChild(detected);
-
- const tradeArea = document.querySelector('.trade_area');
-
- tradeArea.parentNode.insertBefore(tradeNode, tradeArea);
-};
-
-const showValidated = function f() {
- const tradeNode = createBanner('#006700');
-
- const content = document.createElement('div');
- tradeNode.appendChild(content);
-
- content.appendChild(getLogoEl());
-
- const name = document.createElement('span');
- name.style.fontSize = '18px';
- name.style.marginLeft = '15px';
- name.style.lineHeight = '32px';
- name.style.fontWeight = 'bold';
- name.innerText = 'Trade Validated';
- content.appendChild(name);
-
- const detected = document.createElement('div');
- detected.style.paddingLeft = '45px';
- detected.style.color = 'darkgrey';
- detected.innerText = `All of the items you're sending correspond to a CSGOFloat purchase`;
- detected.style.color = 'darkgrey';
- content.appendChild(detected);
-
- const tradeArea = document.querySelector('.trade_area');
-
- tradeArea.parentNode.insertBefore(tradeNode, tradeArea);
-};
-
-const addAutoFill = function (trades, tradeStatus, isSeller) {
- const type = isSeller ? 'Sale' : 'Purchase';
-
- for (const trade of trades) {
- // TODO: Remove backwards compatibility once rolled out
- const item = trade.contract.offering || trade.contract.item;
-
- if (tradeStatus.them.assets.find(e => e.assetid == item.asset_id)) {
- // They are viewing an offer sent to them that already has the item included
- continue;
- }
-
- const tradeNode = createBanner('#303030');
-
- const left = document.createElement('div');
- tradeNode.appendChild(left);
-
- left.appendChild(getLogoEl());
-
- const name = document.createElement('span');
- name.style.fontSize = '18px';
- name.style.marginLeft = '15px';
- name.style.lineHeight = '32px';
- name.innerText = item.market_hash_name;
- left.appendChild(name);
-
- const detected = document.createElement('div');
- detected.style.paddingLeft = '45px';
- detected.style.color = 'darkgrey';
- detected.innerText = `Detected ${type} (Float: ${item.float_value.toFixed(12)}, Seed: ${item.paint_seed})`;
- detected.style.color = 'darkgrey';
- left.appendChild(detected);
-
- /* right */
- const right = document.createElement('div');
-
- const autoFill = createButton('Auto-Fill', 'green');
- autoFill.addEventListener('click', () => {
- window.postMessage(
- {
- type: 'autoFill',
- id: item.asset_id,
- isSeller
- },
- '*'
- );
-
- document.getElementById('trade_offer_note').value = `CSGOFloat Market Trade Offer #${trade.id} \n\nThanks for using CSGOFloat!`;
- });
-
- right.appendChild(autoFill);
- tradeNode.appendChild(right);
-
- const tradeArea = document.querySelector('.trade_area');
- tradeArea.parentNode.insertBefore(tradeNode, tradeArea);
- }
-};
-
-const addFloatMarketFill = async function () {
- let data;
- try {
- data = await sendMessage({ floatMarket: true });
- } catch (e) {
- return;
- }
-
- if (!data.trades_to_send) {
- // Must be logged out of CSGOFloat
- return;
- }
-
- const partnerId = await retrievePartnerInfo();
-
- const partnerTrades = data.trades_to_send.filter(e => e.buyer_id === partnerId);
- const tradeStatus = await retrieveTradeStatus();
-
- if (tradeStatus.me.assets.length > 0) {
- let hasAutofillText = false;
-
- const tradeMessages = document.getElementsByClassName("included_trade_offer_note_ctn");
- if (tradeMessages.length > 0) {
- const sanitized = tradeMessages[0].innerText.trim().replace(/ /g, '').toLowerCase();
-
- // TODO: Use edit-distance
- hasAutofillText = sanitized.includes('csgofloat') || sanitized.includes('floatmarket');
- }
-
- // Whether all items match a csgofloat purchase from this seller (this account)
- let allItemsMatch = true;
-
- for (const item of tradeStatus.me.assets) {
- const hasTrade = partnerTrades.find(e => (e.contract.offering || e.contract.item).asset_id === item.assetid);
-
- if (!hasTrade) {
- allItemsMatch = false;
- break;
- }
- }
-
- if (allItemsMatch) {
- showValidated();
- } else if (hasAutofillText) {
- // Only show warning if we find csgofloat related text in the description
- // Otherwise we'd show a warning on every non-csgofloat trade offer
- showWarning();
- }
- }
-
- addAutoFill(partnerTrades, tradeStatus, true);
-
- // Auto-fill for buyers
- addAutoFill(data.trades_to_receive.filter(e => e.seller_id === partnerId), tradeStatus, false);
-};
-
-let tScript = document.createElement('script');
-tScript.innerText = `
- window.addEventListener('message', (e) => {
- if (e.data.type == 'autoFill') {
- if (e.data.isSeller) {
- $J('#inventory_select_your_inventory').click();
- MoveItemToTrade(UserYou.findAsset(730, 2, e.data.id).element);
- } else {
- $J('#inventory_select_their_inventory').click();
-
- /* Make sure their inventory is loaded first (it is dynamically loaded when the tab is clicked) */
- const fetchEl = setInterval(() => {
- const item = UserThem.findAsset(730, 2, e.data.id);
- if (item) {
- clearInterval(fetchEl);
- MoveItemToTrade(UserThem.findAsset(730, 2, e.data.id).element);
- }
- }, 250);
- }
- }
- });
-`;
-
-document.head.appendChild(tScript);
-
diff --git a/lib/utils.js b/lib/utils.js
deleted file mode 100644
index 9b3410a6..00000000
--- a/lib/utils.js
+++ /dev/null
@@ -1,251 +0,0 @@
-const createButton = function(text, colour, id) {
- let btn = document.createElement('a');
- btn.classList.add(`btn_${colour}_white_innerfade`);
- btn.classList.add('btn_small');
- btn.classList.add('float-btn');
-
- if (id) btn.id = id;
-
- let span = document.createElement('span');
- span.innerText = text;
- btn.appendChild(span);
-
- return btn;
-};
-
-const removeAllItemsHtml = function() {
- // Iterate through each item on the page
- let listingRows = document.querySelectorAll('.market_listing_row.market_recent_listing_row');
-
- for (let row of listingRows) {
- let id = row.id.replace('listing_', '');
-
- let floatDiv = row.querySelector(`#item_${id}_floatdiv`);
-
- if (floatDiv) {
- row.style.backgroundColor = '';
- floatDiv.parentNode.removeChild(floatDiv);
- }
-
- let stickerDiv = row.querySelector('.float-stickers-container');
- if (stickerDiv) {
- stickerDiv.parentNode.removeChild(stickerDiv);
- }
- }
-};
-
-const hexToRgb = function(hex) {
- let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
- return result ? [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)] : null;
-};
-
-const rgbToHex = function(rgb) {
- return '#' + ((1 << 24) + (rgb[0] << 16) + (rgb[1] << 8) + rgb[2]).toString(16).slice(1);
-};
-
-// Based on https://stackoverflow.com/a/41491220
-const pickTextColour = function(bgColor, lightColour, darkColour) {
- const color = bgColor.charAt(0) === '#' ? bgColor.substring(1, 7) : bgColor;
- const r = parseInt(color.substring(0, 2), 16); // hexToR
- const g = parseInt(color.substring(2, 4), 16); // hexToG
- const b = parseInt(color.substring(4, 6), 16); // hexToB
- const uicolors = [r / 255, g / 255, b / 255];
- const c = uicolors.map(col => {
- if (col <= 0.03928) {
- return col / 12.92;
- }
- return Math.pow((col + 0.055) / 1.055, 2.4);
- });
- const L = 0.2126 * c[0] + 0.7152 * c[1] + 0.0722 * c[2];
- return L > 0.179 ? darkColour : lightColour;
-};
-
-const isInventoryPage = function() {
- return /^\/(profiles|id)\/\S*\/inventory/.test(window.location.pathname);
-};
-
-const isTradePage = function () {
- return /^\/tradeoffer\/\S*/.test(window.location.pathname);
-};
-
-const extractInspectAssetId = function(link) {
- const m = decodeURIComponent(link).match(
- /^steam:\/\/rungame\/730\/\d+\/[+ ]csgo_econ_action_preview [SM]\d+A(\d+)D\d+$/
- );
- return m && m[1];
-};
-
-const extractInspectSteamId = function(link) {
- const m = decodeURIComponent(link).match(
- /^steam:\/\/rungame\/730\/\d+\/[+ ]csgo_econ_action_preview [SM](\d+)A\d+D\d+$/
- );
- return m && m[1];
-};
-
-const wearRanges = [
- [0.0, 0.07],
- [0.07, 0.15],
- [0.15, 0.38],
- [0.38, 0.45],
- [0.45, 1.0]
-];
-
-const rangeFromWear = function(wear) {
- for (const range of wearRanges) {
- if (wear > range[0] && wear <= range[1]) {
- return range;
- }
- }
-};
-
-const dopplerPhases = {
- 418: 'Phase 1',
- 419: 'Phase 2',
- 420: 'Phase 3',
- 421: 'Phase 4',
- 415: 'Ruby',
- 416: 'Sapphire',
- 417: 'Black Pearl',
- 569: 'Phase 1',
- 570: 'Phase 2',
- 571: 'Phase 3',
- 572: 'Phase 4',
- 568: 'Emerald',
- 618: 'Phase 2',
- 619: 'Sapphire',
- 617: 'Black Pearl',
- 852: 'Phase 1',
- 853: 'Phase 2',
- 854: 'Phase 3',
- 855: 'Phase 4',
- 1119: "Emerald",
- 1120: "Phase 1",
- 1121: "Phase 2",
- 1122: "Phase 3",
- 1123: "Phase 4"
-};
-
-const hasDopplerPhase = function(paintIndex) {
- return paintIndex in dopplerPhases;
-};
-
-const getDopplerPhase = function (paintIndex) {
- return dopplerPhases[paintIndex];
-};
-
-/**
- * Compares two software version numbers (e.g. "1.7.1" or "1.2b").
- *
- * This function was born in http://stackoverflow.com/a/6832721.
- *
- * @param {string} v1 The first version to be compared.
- * @param {string} v2 The second version to be compared.
- * @param {object} [options] Optional flags that affect comparison behavior:
- *
- *
- * lexicographical: true compares each part of the version strings lexicographically instead of
- * naturally; this allows suffixes such as "b" or "dev" but will cause "1.10" to be considered smaller than
- * "1.2".
- *
- *
- * zeroExtend: true changes the result if one version string has less parts than the other. In
- * this case the shorter string will be padded with "zero" parts instead of being considered smaller.
- *
- *
- * @returns {number|NaN}
- *
- *
0 if the versions are equal
- *
a negative integer iff v1 < v2
- *
a positive integer iff v1 > v2
- *
NaN if either version string is in the wrong format