diff options
-rw-r--r-- | web/gulpfile.js | 68 | ||||
-rw-r--r-- | web/package.json | 1 | ||||
-rw-r--r-- | web/src/js/components/proxyapp.jsx.js | 1 | ||||
-rw-r--r-- | web/src/js/filt/filt.js | 1647 | ||||
-rw-r--r-- | web/src/js/filt/filt.pegjs | 166 | ||||
-rw-r--r-- | web/src/js/flow/utils.js | 10 |
6 files changed, 1841 insertions, 52 deletions
diff --git a/web/gulpfile.js b/web/gulpfile.js index f7df820d..8dc888e7 100644 --- a/web/gulpfile.js +++ b/web/gulpfile.js @@ -7,6 +7,7 @@ var less = require("gulp-less"); var livereload = require("gulp-livereload"); var minifyCSS = require('gulp-minify-css'); var notify = require("gulp-notify"); +var peg = require("gulp-peg"); var plumber = require("gulp-plumber"); var qunit = require("gulp-qunit"); var react = require("gulp-react"); @@ -15,9 +16,9 @@ var sourcemaps = require('gulp-sourcemaps'); var uglify = require('gulp-uglify'); -var dont_break_on_errors = function(){ - return plumber(function(error){ - notify.onError("Error: <%= error.message %>").apply(this, arguments); +var dont_break_on_errors = function () { + return plumber(function (error) { + notify.onError("<%= error.message %>").apply(this, arguments); this.emit('end'); }); }; @@ -35,6 +36,7 @@ var path = { 'js/utils.js', 'js/dispatcher.js', 'js/actions.js', + 'js/filt/filt.js', 'js/flow/utils.js', 'js/store/store.js', 'js/store/view.js', @@ -53,13 +55,18 @@ var path = { 'js/app.js', ], }, + peg: "js/filt/filt.pegjs", css: { vendor: ["css/vendor.less"], - app: ["css/app.less"] + app: ["css/app.less"], + all: ["css/**"] }, + vendor: ["vendor/**"], fonts: ["src/vendor/fontawesome/fontawesome-webfont.*"], - html: ["src/*.html", "!src/benchmark.html", "!src/test.html"], - images: "src/images", + html: ["*.html", "!benchmark.html", "!test.html"], + images: ["images/**"], + test: ["test.html"], + opts: {base: "src", cwd: "src"} }; @@ -70,13 +77,13 @@ gulp.task("fonts", function () { function styles_dev(files) { - return (gulp.src(files, {base: "src", cwd: "src"}) + return (gulp.src(files, path.opts) .pipe(dont_break_on_errors()) .pipe(sourcemaps.init()) .pipe(less()) .pipe(sourcemaps.write(".", {sourceRoot: "/static"})) .pipe(gulp.dest(path.dist + "static")) - .pipe(livereload({ auto: false }))); + .pipe(livereload({auto: false}))); } gulp.task("styles-app-dev", styles_dev.bind(undefined, path.css.app)); gulp.task("styles-vendor-dev", styles_dev.bind(undefined, path.css.vendor)); @@ -84,13 +91,13 @@ gulp.task("styles-dev", ["styles-app-dev", "styles-vendor-dev"]); function styles_prod(files) { - return (gulp.src(files, {base: "src", cwd: "src"}) + return (gulp.src(files, path.opts) .pipe(less()) // No sourcemaps support yet :-/ // https://github.com/jonathanepollack/gulp-minify-css/issues/34 .pipe(minifyCSS()) .pipe(gulp.dest(path.dist + "static")) - .pipe(livereload({ auto: false }))); + .pipe(livereload({auto: false}))); } gulp.task("styles-app-prod", styles_prod.bind(undefined, path.css.app)); gulp.task("styles-vendor-prod", styles_prod.bind(undefined, path.css.vendor)); @@ -98,14 +105,14 @@ gulp.task("styles-prod", ["styles-app-prod", "styles-vendor-prod"]); function scripts_dev(files, filename) { - return gulp.src(files, {base: "src", cwd: "src"}) + return gulp.src(files, path.opts) .pipe(dont_break_on_errors()) .pipe(sourcemaps.init()) .pipe(react()) .pipe(concat(filename)) .pipe(sourcemaps.write(".", {sourceRoot: "/static"})) .pipe(gulp.dest(path.dist + "static/js")) - .pipe(livereload({ auto: false })); + .pipe(livereload({auto: false})); } gulp.task("scripts-app-dev", scripts_dev.bind(undefined, path.js.app, "app.js")); gulp.task("scripts-vendor-dev", scripts_dev.bind(undefined, path.js.vendor, "vendor.js")); @@ -113,12 +120,12 @@ gulp.task("scripts-dev", ["scripts-app-dev", "scripts-vendor-dev"]); function scripts_prod(files, filename) { - return gulp.src(files, {base: "src", cwd: "src"}) + return gulp.src(files, path.opts) .pipe(react()) .pipe(concat(filename)) .pipe(uglify()) .pipe(gulp.dest(path.dist + "static/js")) - .pipe(livereload({ auto: false })); + .pipe(livereload({auto: false})); } gulp.task("scripts-app-prod", scripts_prod.bind(undefined, path.js.app, "app.js")); gulp.task("scripts-vendor-prod", scripts_prod.bind(undefined, path.js.vendor, "vendor.js")); @@ -126,41 +133,48 @@ gulp.task("scripts-prod", ["scripts-app-prod", "scripts-vendor-prod"]); gulp.task("jshint", function () { - return gulp.src(["src/js/**"]) + return gulp.src(path.js.app.concat(["!"+path.peg.replace("pegjs","js")]), path.opts) .pipe(dont_break_on_errors()) .pipe(react()) .pipe(jshint()) .pipe(jshint.reporter("jshint-stylish")); }); +gulp.task("peg", function () { + return gulp.src(path.peg, path.opts) + .pipe(dont_break_on_errors()) + .pipe(peg({exportVar:"Filt"})) + .pipe(gulp.dest(".", path.opts)); +}); + gulp.task("images", function () { //(spriting code in commit 4ca720b55680e40b3a4361141a2ad39f9de81111) - return gulp.src(["src/images/**"]) - .pipe(gulp.dest(path.dist + "static/images")); + return gulp.src(path.images, path.opts) + .pipe(gulp.dest(path.dist + "static")); }); gulp.task("html", function () { - return gulp.src(path.html) + return gulp.src(path.html, path.opts) .pipe(gulp.dest(path.dist + "templates")) - .pipe(livereload({ auto: false })); + .pipe(livereload({auto: false})); }); -gulp.task('test', function() { - return gulp.src('src/test.html') +gulp.task('test', function () { + return gulp.src(path.test, path.opts) .pipe(qunit({verbose: true})); }); -common = ["fonts", "html", "jshint", "images"]; +common = ["fonts", "html", "jshint", "peg", "images"]; gulp.task("dev", common.concat(["styles-dev", "scripts-dev"])); gulp.task("prod", common.concat(["styles-prod", "scripts-prod"])); gulp.task("default", ["dev"], function () { livereload.listen({auto: true}); - gulp.watch(["src/vendor/**"], ["scripts-vendor-dev", "styles-vendor-dev"]); - gulp.watch(["src/js/**"], ["scripts-app-dev", "jshint"]); - gulp.watch(["src/css/**"], ["styles-app-dev"]); - gulp.watch(["src/images/**", "src/css/sprites.less"], ["sprites"]); - gulp.watch(["src/*.html"], ["html"]); + gulp.watch(path.vendor, path.opts, ["scripts-vendor-dev", "styles-vendor-dev"]); + gulp.watch(path.js.app, path.opts, ["scripts-app-dev", "jshint"]); + gulp.watch(path.peg, path.opts, ["peg"]); + gulp.watch(path.css.all, path.opts, ["styles-app-dev"]); + gulp.watch(path.html, path.opts, ["html"]); }); diff --git a/web/package.json b/web/package.json index aa7ba2ef..8e33396a 100644 --- a/web/package.json +++ b/web/package.json @@ -12,6 +12,7 @@ "gulp-livereload": "", "gulp-minify-css": "", "gulp-notify": "", + "gulp-peg": "", "gulp-plumber": "", "gulp-qunit": "", "gulp-react": "", diff --git a/web/src/js/components/proxyapp.jsx.js b/web/src/js/components/proxyapp.jsx.js index 20162ad1..91cd268f 100644 --- a/web/src/js/components/proxyapp.jsx.js +++ b/web/src/js/components/proxyapp.jsx.js @@ -24,6 +24,7 @@ var ProxyAppMain = React.createClass({ }, componentDidMount: function () { this.state.settings.addListener("recalculate", this.onSettingsChange); + window.app = this; }, componentWillUnmount: function () { this.state.settings.removeListener("recalculate", this.onSettingsChange); diff --git a/web/src/js/filt/filt.js b/web/src/js/filt/filt.js new file mode 100644 index 00000000..330a5001 --- /dev/null +++ b/web/src/js/filt/filt.js @@ -0,0 +1,1647 @@ +Filt = (function() { + /* + * Generated by PEG.js 0.8.0. + * + * http://pegjs.majda.cz/ + */ + + function peg$subclass(child, parent) { + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor(); + } + + function SyntaxError(message, expected, found, offset, line, column) { + this.message = message; + this.expected = expected; + this.found = found; + this.offset = offset; + this.line = line; + this.column = column; + + this.name = "SyntaxError"; + } + + peg$subclass(SyntaxError, Error); + + function parse(input) { + var options = arguments.length > 1 ? arguments[1] : {}, + + peg$FAILED = {}, + + peg$startRuleFunctions = { start: peg$parsestart }, + peg$startRuleFunction = peg$parsestart, + + peg$c0 = { type: "other", description: "filter expression" }, + peg$c1 = peg$FAILED, + peg$c2 = function(orExpr) { return orExpr; }, + peg$c3 = { type: "other", description: "whitespace" }, + peg$c4 = /^[ \t\n\r]/, + peg$c5 = { type: "class", value: "[ \\t\\n\\r]", description: "[ \\t\\n\\r]" }, + peg$c6 = { type: "other", description: "control character" }, + peg$c7 = /^[|&!()~"]/, + peg$c8 = { type: "class", value: "[|&!()~\"]", description: "[|&!()~\"]" }, + peg$c9 = { type: "other", description: "optional whitespace" }, + peg$c10 = [], + peg$c11 = "|", + peg$c12 = { type: "literal", value: "|", description: "\"|\"" }, + peg$c13 = function(first, second) { return or(first, second); }, + peg$c14 = "&", + peg$c15 = { type: "literal", value: "&", description: "\"&\"" }, + peg$c16 = function(first, second) { return and(first, second); }, + peg$c17 = "!", + peg$c18 = { type: "literal", value: "!", description: "\"!\"" }, + peg$c19 = function(expr) { return not(expr); }, + peg$c20 = "(", + peg$c21 = { type: "literal", value: "(", description: "\"(\"" }, + peg$c22 = ")", + peg$c23 = { type: "literal", value: ")", description: "\")\"" }, + peg$c24 = function(expr) { return binding(orExpr); }, + peg$c25 = "~a", + peg$c26 = { type: "literal", value: "~a", description: "\"~a\"" }, + peg$c27 = function() { return assetFilter; }, + peg$c28 = "~e", + peg$c29 = { type: "literal", value: "~e", description: "\"~e\"" }, + peg$c30 = function() { return errorFilter; }, + peg$c31 = "~q", + peg$c32 = { type: "literal", value: "~q", description: "\"~q\"" }, + peg$c33 = function() { return noResponseFilter; }, + peg$c34 = "~s", + peg$c35 = { type: "literal", value: "~s", description: "\"~s\"" }, + peg$c36 = function() { return responseFilter; }, + peg$c37 = "true", + peg$c38 = { type: "literal", value: "true", description: "\"true\"" }, + peg$c39 = function() { return trueFilter; }, + peg$c40 = "false", + peg$c41 = { type: "literal", value: "false", description: "\"false\"" }, + peg$c42 = function() { return falseFilter; }, + peg$c43 = "~c", + peg$c44 = { type: "literal", value: "~c", description: "\"~c\"" }, + peg$c45 = function(s) { return responseCode(s); }, + peg$c46 = "~d", + peg$c47 = { type: "literal", value: "~d", description: "\"~d\"" }, + peg$c48 = function(s) { return domain(s); }, + peg$c49 = "~h", + peg$c50 = { type: "literal", value: "~h", description: "\"~h\"" }, + peg$c51 = function(s) { return header(s); }, + peg$c52 = "~hq", + peg$c53 = { type: "literal", value: "~hq", description: "\"~hq\"" }, + peg$c54 = function(s) { return requestHeader(s); }, + peg$c55 = "~hs", + peg$c56 = { type: "literal", value: "~hs", description: "\"~hs\"" }, + peg$c57 = function(s) { return responseHeader(s); }, + peg$c58 = "~m", + peg$c59 = { type: "literal", value: "~m", description: "\"~m\"" }, + peg$c60 = function(s) { return method(s); }, + peg$c61 = "~t", + peg$c62 = { type: "literal", value: "~t", description: "\"~t\"" }, + peg$c63 = function(s) { return contentType(s); }, + peg$c64 = "~tq", + peg$c65 = { type: "literal", value: "~tq", description: "\"~tq\"" }, + peg$c66 = function(s) { return requestContentType(s); }, + peg$c67 = "~ts", + peg$c68 = { type: "literal", value: "~ts", description: "\"~ts\"" }, + peg$c69 = function(s) { return responseContentType(s); }, + peg$c70 = "~u", + peg$c71 = { type: "literal", value: "~u", description: "\"~u\"" }, + peg$c72 = function(s) { return url(s); }, + peg$c73 = { type: "other", description: "string" }, + peg$c74 = "\"", + peg$c75 = { type: "literal", value: "\"", description: "\"\\\"\"" }, + peg$c76 = function(chars) { return chars.join(""); }, + peg$c77 = "'", + peg$c78 = { type: "literal", value: "'", description: "\"'\"" }, + peg$c79 = void 0, + peg$c80 = /^["\\]/, + peg$c81 = { type: "class", value: "[\"\\\\]", description: "[\"\\\\]" }, + peg$c82 = { type: "any", description: "any character" }, + peg$c83 = function(char) { return char; }, + peg$c84 = "\\", + peg$c85 = { type: "literal", value: "\\", description: "\"\\\\\"" }, + peg$c86 = /^['\\]/, + peg$c87 = { type: "class", value: "['\\\\]", description: "['\\\\]" }, + peg$c88 = /^['"\\]/, + peg$c89 = { type: "class", value: "['\"\\\\]", description: "['\"\\\\]" }, + peg$c90 = "n", + peg$c91 = { type: "literal", value: "n", description: "\"n\"" }, + peg$c92 = function() { return "\n"; }, + peg$c93 = "r", + peg$c94 = { type: "literal", value: "r", description: "\"r\"" }, + peg$c95 = function() { return "\r"; }, + peg$c96 = "t", + peg$c97 = { type: "literal", value: "t", description: "\"t\"" }, + peg$c98 = function() { return "\t"; }, + + peg$currPos = 0, + peg$reportedPos = 0, + peg$cachedPos = 0, + peg$cachedPosDetails = { line: 1, column: 1, seenCR: false }, + peg$maxFailPos = 0, + peg$maxFailExpected = [], + peg$silentFails = 0, + + peg$result; + + if ("startRule" in options) { + if (!(options.startRule in peg$startRuleFunctions)) { + throw new Error("Can't start parsing from rule \"" + options.startRule + "\"."); + } + + peg$startRuleFunction = peg$startRuleFunctions[options.startRule]; + } + + function text() { + return input.substring(peg$reportedPos, peg$currPos); + } + + function offset() { + return peg$reportedPos; + } + + function line() { + return peg$computePosDetails(peg$reportedPos).line; + } + + function column() { + return peg$computePosDetails(peg$reportedPos).column; + } + + function expected(description) { + throw peg$buildException( + null, + [{ type: "other", description: description }], + peg$reportedPos + ); + } + + function error(message) { + throw peg$buildException(message, null, peg$reportedPos); + } + + function peg$computePosDetails(pos) { + function advance(details, startPos, endPos) { + var p, ch; + + for (p = startPos; p < endPos; p++) { + ch = input.charAt(p); + if (ch === "\n") { + if (!details.seenCR) { details.line++; } + details.column = 1; + details.seenCR = false; + } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") { + details.line++; + details.column = 1; + details.seenCR = true; + } else { + details.column++; + details.seenCR = false; + } + } + } + + if (peg$cachedPos !== pos) { + if (peg$cachedPos > pos) { + peg$cachedPos = 0; + peg$cachedPosDetails = { line: 1, column: 1, seenCR: false }; + } + advance(peg$cachedPosDetails, peg$cachedPos, pos); + peg$cachedPos = pos; + } + + return peg$cachedPosDetails; + } + + function peg$fail(expected) { + if (peg$currPos < peg$maxFailPos) { return; } + + if (peg$currPos > peg$maxFailPos) { + peg$maxFailPos = peg$currPos; + peg$maxFailExpected = []; + } + + peg$maxFailExpected.push(expected); + } + + function peg$buildException(message, expected, pos) { + function cleanupExpected(expected) { + var i = 1; + + expected.sort(function(a, b) { + if (a.description < b.description) { + return -1; + } else if (a.description > b.description) { + return 1; + } else { + return 0; + } + }); + + while (i < expected.length) { + if (expected[i - 1] === expected[i]) { + expected.splice(i, 1); + } else { + i++; + } + } + } + + function buildMessage(expected, found) { + function stringEscape(s) { + function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); } + + return s + .replace(/\\/g, '\\\\') + .replace(/"/g, '\\"') + .replace(/\x08/g, '\\b') + .replace(/\t/g, '\\t') + .replace(/\n/g, '\\n') + .replace(/\f/g, '\\f') + .replace(/\r/g, '\\r') + .replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); }) + .replace(/[\x10-\x1F\x80-\xFF]/g, function(ch) { return '\\x' + hex(ch); }) + .replace(/[\u0180-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); }) + .replace(/[\u1080-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); }); + } + + var expectedDescs = new Array(expected.length), + expectedDesc, foundDesc, i; + + for (i = 0; i < expected.length; i++) { + expectedDescs[i] = expected[i].description; + } + + expectedDesc = (expected.length > 1 + ? expectedDescs.slice(0, -1).join(", ") + + " or " + + expectedDescs[expected.length - 1] + : expectedDescs[0]); + + foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input"; + + return "Expected " + expectedDesc + " but " + foundDesc + " found."; + } + + var posDetails = peg$computePosDetails(pos), + found = pos < input.length ? input.charAt(pos) : null; + + if (expected !== null) { + cleanupExpected(expected); + } + + return new SyntaxError( + message !== null ? message : buildMessage(expected, found), + expected, + found, + pos, + posDetails.line, + posDetails.column + ); + } + + function peg$parsestart() { + var s0, s1, s2, s3; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parse__(); + if (s1 !== peg$FAILED) { + s2 = peg$parseOrExpr(); + if (s2 !== peg$FAILED) { + s3 = peg$parse__(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c2(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c0); } + } + + return s0; + } + + function peg$parsews() { + var s0, s1; + + peg$silentFails++; + if (peg$c4.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c5); } + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c3); } + } + + return s0; + } + + function peg$parsecc() { + var s0, s1; + + peg$silentFails++; + if (peg$c7.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c8); } + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c6); } + } + + return s0; + } + + function peg$parse__() { + var s0, s1; + + peg$silentFails++; + s0 = []; + s1 = peg$parsews(); + while (s1 !== peg$FAILED) { + s0.push(s1); + s1 = peg$parsews(); + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c9); } + } + + return s0; + } + + function peg$parseOrExpr() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + s1 = peg$parseAndExpr(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 124) { + s3 = peg$c11; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c12); } + } + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + if (s4 !== peg$FAILED) { + s5 = peg$parseOrExpr(); + if (s5 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c13(s1, s5); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$parseAndExpr(); + } + + return s0; + } + + function peg$parseAndExpr() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + s1 = peg$parseNotExpr(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 38) { + s3 = peg$c14; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c15); } + } + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + if (s4 !== peg$FAILED) { + s5 = peg$parseAndExpr(); + if (s5 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c16(s1, s5); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseNotExpr(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + } else { + s2 = peg$c1; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseAndExpr(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c16(s1, s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$parseNotExpr(); + } + } + + return s0; + } + + function peg$parseNotExpr() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 33) { + s1 = peg$c17; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c18); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + if (s2 !== peg$FAILED) { + s3 = peg$parseNotExpr(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c19(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$parseBindingExpr(); + } + + return s0; + } + + function peg$parseBindingExpr() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 40) { + s1 = peg$c20; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c21); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + if (s2 !== peg$FAILED) { + s3 = peg$parseOrExpr(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 41) { + s5 = peg$c22; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c23); } + } + if (s5 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c24(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$parseExpr(); + } + + return s0; + } + + function peg$parseExpr() { + var s0; + + s0 = peg$parseNullaryExpr(); + if (s0 === peg$FAILED) { + s0 = peg$parseUnaryExpr(); + } + + return s0; + } + + function peg$parseNullaryExpr() { + var s0, s1; + + s0 = peg$parseBooleanLiteral(); + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c25) { + s1 = peg$c25; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c26); } + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c27(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c28) { + s1 = peg$c28; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c29); } + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c30(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c31) { + s1 = peg$c31; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c32); } + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c33(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c34) { + s1 = peg$c34; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c35); } + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c36(); + } + s0 = s1; + } + } + } + } + + return s0; + } + + function peg$parseBooleanLiteral() { + var s0, s1; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4) === peg$c37) { + s1 = peg$c37; + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c38); } + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c39(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 5) === peg$c40) { + s1 = peg$c40; + peg$currPos += 5; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c41); } + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c42(); + } + s0 = s1; + } + + return s0; + } + + function peg$parseUnaryExpr() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c43) { + s1 = peg$c43; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c44); } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + } else { + s2 = peg$c1; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c45(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c46) { + s1 = peg$c46; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c47); } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + } else { + s2 = peg$c1; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c48(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c49) { + s1 = peg$c49; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c50); } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + } else { + s2 = peg$c1; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c51(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 3) === peg$c52) { + s1 = peg$c52; + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c53); } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + } else { + s2 = peg$c1; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c54(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 3) === peg$c55) { + s1 = peg$c55; + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c56); } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + } else { + s2 = peg$c1; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c57(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c58) { + s1 = peg$c58; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c59); } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + } else { + s2 = peg$c1; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c60(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c61) { + s1 = peg$c61; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c62); } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + } else { + s2 = peg$c1; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c63(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 3) === peg$c64) { + s1 = peg$c64; + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c65); } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + } else { + s2 = peg$c1; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c66(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 3) === peg$c67) { + s1 = peg$c67; + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c68); } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + } else { + s2 = peg$c1; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c69(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c70) { + s1 = peg$c70; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c71); } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + } else { + s2 = peg$c1; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c72(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseStringLiteral(); + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c72(s1); + } + s0 = s1; + } + } + } + } + } + } + } + } + } + } + + return s0; + } + + function peg$parseStringLiteral() { + var s0, s1, s2, s3; + + peg$silentFails++; + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 34) { + s1 = peg$c74; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c75); } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parseDoubleStringChar(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parseDoubleStringChar(); + } + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 34) { + s3 = peg$c74; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c75); } + } + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c76(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 39) { + s1 = peg$c77; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c78); } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parseSingleStringChar(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parseSingleStringChar(); + } + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 39) { + s3 = peg$c77; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c78); } + } + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c76(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$currPos; + peg$silentFails++; + s2 = peg$parsecc(); + peg$silentFails--; + if (s2 === peg$FAILED) { + s1 = peg$c79; + } else { + peg$currPos = s1; + s1 = peg$c1; + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parseUnquotedStringChar(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parseUnquotedStringChar(); + } + } else { + s2 = peg$c1; + } + if (s2 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c76(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c73); } + } + + return s0; + } + + function peg$parseDoubleStringChar() { + var s0, s1, s2; + + s0 = peg$currPos; + s1 = peg$currPos; + peg$silentFails++; + if (peg$c80.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c81); } + } + peg$silentFails--; + if (s2 === peg$FAILED) { + s1 = peg$c79; + } else { + peg$currPos = s1; + s1 = peg$c1; + } + if (s1 !== peg$FAILED) { + if (input.length > peg$currPos) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c82); } + } + if (s2 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c83(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 92) { + s1 = peg$c84; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c85); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parseEscapeSequence(); + if (s2 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c83(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } + + return s0; + } + + function peg$parseSingleStringChar() { + var s0, s1, s2; + + s0 = peg$currPos; + s1 = peg$currPos; + peg$silentFails++; + if (peg$c86.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c87); } + } + peg$silentFails--; + if (s2 === peg$FAILED) { + s1 = peg$c79; + } else { + peg$currPos = s1; + s1 = peg$c1; + } + if (s1 !== peg$FAILED) { + if (input.length > peg$currPos) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c82); } + } + if (s2 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c83(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 92) { + s1 = peg$c84; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c85); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parseEscapeSequence(); + if (s2 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c83(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } + + return s0; + } + + function peg$parseUnquotedStringChar() { + var s0, s1, s2; + + s0 = peg$currPos; + s1 = peg$currPos; + peg$silentFails++; + s2 = peg$parsews(); + peg$silentFails--; + if (s2 === peg$FAILED) { + s1 = peg$c79; + } else { + peg$currPos = s1; + s1 = peg$c1; + } + if (s1 !== peg$FAILED) { + if (input.length > peg$currPos) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c82); } + } + if (s2 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c83(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + + return s0; + } + + function peg$parseEscapeSequence() { + var s0, s1; + + if (peg$c88.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c89); } + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 110) { + s1 = peg$c90; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c91); } + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c92(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 114) { + s1 = peg$c93; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c94); } + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c95(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 116) { + s1 = peg$c96; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c97); } + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c98(); + } + s0 = s1; + } + } + } + + return s0; + } + + + function or(first, second) { + // Add explicit function names to ease debugging. + return function orFilter() { + first.apply(this, arguments) || second.apply(this, arguments); + }; + } + function and(first, second) { + return function andFilter() { + return first.apply(this, arguments) && second.apply(this, arguments); + } + } + function not(expr) { + return function notFilter() { + return !expr.apply(this, arguments); + }; + } + function binding(expr) { + return function bindingFilter() { + return expr.apply(this, arguments); + }; + } + function trueFilter(flow) { + return true; + } + function falseFilter(flow) { + return false; + } + var ASSET_TYPES = [ + new RegExp("text/javascript"), + new RegExp("application/x-javascript"), + new RegExp("application/javascript"), + new RegExp("text/css"), + new RegExp("image/.*"), + new RegExp("application/x-shockwave-flash") + ]; + function assetFilter(flow) { + if (flow.response) { + var ct = ResponseUtils.getContentType(flow.response); + var i = ASSET_TYPES.length; + while (i--) { + if (ASSET_TYPES[i].test(ct)) { + return true; + } + } + } + return false; + } + function responseCode(code){ + code = parseInt(code); + return function responseCodeFilter(flow){ + return flow.response && flow.response.code === code; + }; + } + function domain(regex){ + regex = new RegExp(regex, "i"); + return function domainFilter(flow){ + return flow.request && regex.test(flow.request.host); + }; + } + function errorFilter(flow){ + return !!flow.error; + } + function header(regex){ + regex = new RegExp(regex, "i"); + return function headerFilter(flow){ + return ( + (flow.request && RequestUtils.match_header(flow.request, regex)) + || + (flow.response && ResponseUtils.match_header(flow.response, regex)) + ); + }; + } + function requestHeader(regex){ + regex = new RegExp(regex, "i"); + return function requestHeaderFilter(flow){ + return (flow.request && RequestUtils.match_header(flow.request, regex)); + } + } + function responseHeader(regex){ + regex = new RegExp(regex, "i"); + return function responseHeaderFilter(flow){ + return (flow.response && ResponseUtils.match_header(flow.response, regex)); + } + } + function method(regex){ + regex = new RegExp(regex, "i"); + return function methodFilter(flow){ + return flow.request && regex.test(flow.request.method); + }; + } + function noResponseFilter(flow){ + return flow.request && !flow.response; + } + function responseFilter(flow){ + return !!flow.response; + } + + function contentType(regex){ + regex = new RegExp(regex, "i"); + return function contentTypeFilter(flow){ + return ( + (flow.request && regex.test(RequestUtils.getContentType(flow.request))) + || + (flow.response && regex.test(ResponseUtils.getContentType(flow.response))) + ); + }; + } + function requestContentType(regex){ + regex = new RegExp(regex, "i"); + return function requestContentTypeFilter(flow){ + return flow.request && regex.test(RequestUtils.getContentType(flow.request)); + }; + } + function responseContentType(regex){ + regex = new RegExp(regex, "i"); + return function responseContentTypeFilter(flow){ + return flow.response && regex.test(ResponseUtils.getContentType(flow.response)); + }; + } + function url(regex){ + regex = new RegExp(regex, "i"); + return function urlFilter(flow){ + return flow.request && regex.test(RequestUtils.pretty_url(flow.request)); + } + } + + + peg$result = peg$startRuleFunction(); + + if (peg$result !== peg$FAILED && peg$currPos === input.length) { + return peg$result; + } else { + if (peg$result !== peg$FAILED && peg$currPos < input.length) { + peg$fail({ type: "end", description: "end of input" }); + } + + throw peg$buildException(null, peg$maxFailExpected, peg$maxFailPos); + } + } + + return { + SyntaxError: SyntaxError, + parse: parse + }; +})();
\ No newline at end of file diff --git a/web/src/js/filt/filt.pegjs b/web/src/js/filt/filt.pegjs index 06e2ecb3..c363e774 100644 --- a/web/src/js/filt/filt.pegjs +++ b/web/src/js/filt/filt.pegjs @@ -1,28 +1,131 @@ // PEG.js filter rules - see http://pegjs.majda.cz/online -/* Explain Filter */ { - var or = function(first, second) { - return first + " or " + second; - }; - var and = function(first, second) { - return first + " and " + second; - }; - var not = function(expr) { - return "not " + expr; - }; - var binding = function(expr) { - return "(" + expr + ")"; - } - var assetFilter = "is asset"; - var trueFilter = true; - var falseFilter = false; - var bodyFilter = function(s) { - return "body ~= '" + s + "'"; - } - var urlFilter = function(s) { - return "url ~= '" + s + "'"; - } +function or(first, second) { + // Add explicit function names to ease debugging. + return function orFilter() { + first.apply(this, arguments) || second.apply(this, arguments); + }; +} +function and(first, second) { + return function andFilter() { + return first.apply(this, arguments) && second.apply(this, arguments); + } +} +function not(expr) { + return function notFilter() { + return !expr.apply(this, arguments); + }; +} +function binding(expr) { + return function bindingFilter() { + return expr.apply(this, arguments); + }; +} +function trueFilter(flow) { + return true; +} +function falseFilter(flow) { + return false; +} +var ASSET_TYPES = [ + new RegExp("text/javascript"), + new RegExp("application/x-javascript"), + new RegExp("application/javascript"), + new RegExp("text/css"), + new RegExp("image/.*"), + new RegExp("application/x-shockwave-flash") +]; +function assetFilter(flow) { + if (flow.response) { + var ct = ResponseUtils.getContentType(flow.response); + var i = ASSET_TYPES.length; + while (i--) { + if (ASSET_TYPES[i].test(ct)) { + return true; + } + } + } + return false; +} +function responseCode(code){ + code = parseInt(code); + return function responseCodeFilter(flow){ + return flow.response && flow.response.code === code; + }; +} +function domain(regex){ + regex = new RegExp(regex, "i"); + return function domainFilter(flow){ + return flow.request && regex.test(flow.request.host); + }; +} +function errorFilter(flow){ + return !!flow.error; +} +function header(regex){ + regex = new RegExp(regex, "i"); + return function headerFilter(flow){ + return ( + (flow.request && RequestUtils.match_header(flow.request, regex)) + || + (flow.response && ResponseUtils.match_header(flow.response, regex)) + ); + }; +} +function requestHeader(regex){ + regex = new RegExp(regex, "i"); + return function requestHeaderFilter(flow){ + return (flow.request && RequestUtils.match_header(flow.request, regex)); + } +} +function responseHeader(regex){ + regex = new RegExp(regex, "i"); + return function responseHeaderFilter(flow){ + return (flow.response && ResponseUtils.match_header(flow.response, regex)); + } +} +function method(regex){ + regex = new RegExp(regex, "i"); + return function methodFilter(flow){ + return flow.request && regex.test(flow.request.method); + }; +} +function noResponseFilter(flow){ + return flow.request && !flow.response; +} +function responseFilter(flow){ + return !!flow.response; +} + +function contentType(regex){ + regex = new RegExp(regex, "i"); + return function contentTypeFilter(flow){ + return ( + (flow.request && regex.test(RequestUtils.getContentType(flow.request))) + || + (flow.response && regex.test(ResponseUtils.getContentType(flow.response))) + ); + }; +} +function requestContentType(regex){ + regex = new RegExp(regex, "i"); + return function requestContentTypeFilter(flow){ + return flow.request && regex.test(RequestUtils.getContentType(flow.request)); + }; +} +function responseContentType(regex){ + regex = new RegExp(regex, "i"); + return function responseContentTypeFilter(flow){ + return flow.response && regex.test(ResponseUtils.getContentType(flow.response)); + }; +} +function url(regex){ + regex = new RegExp(regex, "i"); + return function urlFilter(flow){ + return flow.request && regex.test(RequestUtils.pretty_url(flow.request)); + } +} } start "filter expression" @@ -60,15 +163,28 @@ Expr NullaryExpr = BooleanLiteral - / "~a" { return assetFilter; }; + / "~a" { return assetFilter; } + / "~e" { return errorFilter; } + / "~q" { return noResponseFilter; } + / "~s" { return responseFilter; } + BooleanLiteral = "true" { return trueFilter; } / "false" { return falseFilter; } UnaryExpr - = "~b" ws+ s:StringLiteral { return bodyFilter(s); } - / s:StringLiteral { return urlFilter(s); } + = "~c" ws+ s:StringLiteral { return responseCode(s); } + / "~d" ws+ s:StringLiteral { return domain(s); } + / "~h" ws+ s:StringLiteral { return header(s); } + / "~hq" ws+ s:StringLiteral { return requestHeader(s); } + / "~hs" ws+ s:StringLiteral { return responseHeader(s); } + / "~m" ws+ s:StringLiteral { return method(s); } + / "~t" ws+ s:StringLiteral { return contentType(s); } + / "~tq" ws+ s:StringLiteral { return requestContentType(s); } + / "~ts" ws+ s:StringLiteral { return responseContentType(s); } + / "~u" ws+ s:StringLiteral { return url(s); } + / s:StringLiteral { return url(s); } StringLiteral "string" = '"' chars:DoubleStringChar* '"' { return chars.join(""); } diff --git a/web/src/js/flow/utils.js b/web/src/js/flow/utils.js index e54f7c59..988629b9 100644 --- a/web/src/js/flow/utils.js +++ b/web/src/js/flow/utils.js @@ -22,6 +22,16 @@ var _MessageUtils = { message._headerLookups[regex] = header ? header[1] : undefined; } return message._headerLookups[regex]; + }, + match_header: function(message, regex){ + var headers = message.headers; + var i = headers.length; + while(i--){ + if(regex.test(headers[i].join(" "))){ + return headers[i]; + } + } + return false; } }; |