From e8f3a8478a61a5fb681d098c9b1c556bb39b705a Mon Sep 17 00:00:00 2001 From: Dino Chiesa Date: Tue, 27 Feb 2024 15:03:26 -0800 Subject: [PATCH 1/2] fix: handle unusual spacing in conditions --- build/ConditionParser.js | 252 ++++++++++--------- lib/package/plugins/CC007-ConditionSyntax.js | 4 +- lib/peggy/Apigee-Condition.pegjs | 8 +- test/specs/CC007-Condition-Syntax-Test.js | 56 +++++ test/specs/ConditionParserTest.js | 4 +- 5 files changed, 199 insertions(+), 125 deletions(-) diff --git a/build/ConditionParser.js b/build/ConditionParser.js index c0070da..1d1d29f 100644 --- a/build/ConditionParser.js +++ b/build/ConditionParser.js @@ -529,40 +529,22 @@ function peg$parse(input, options) { 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$FAILED; + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); } - if (s2 !== peg$FAILED) { - s3 = peg$parseop_boolean(); - if (s3 !== peg$FAILED) { - s4 = []; + s3 = peg$parseop_boolean(); + if (s3 !== peg$FAILED) { + s4 = []; + s5 = peg$parsews(); + while (s5 !== peg$FAILED) { + s4.push(s5); s5 = peg$parsews(); - if (s5 !== peg$FAILED) { - while (s5 !== peg$FAILED) { - s4.push(s5); - s5 = peg$parsews(); - } - } else { - s4 = peg$FAILED; - } - if (s4 !== peg$FAILED) { - s5 = peg$parseboolean_stmt1(); - if (s5 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f0(s1, s3, s5); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } + } + s5 = peg$parseboolean_stmt1(); + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f0(s1, s3, s5); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -675,67 +657,79 @@ function peg$parse(input, options) { } function peg$parseprimary() { - var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9; + var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12; s0 = peg$currPos; + s1 = []; + s2 = peg$parsews(); + while (s2 !== peg$FAILED) { + s1.push(s2); + s2 = peg$parsews(); + } if (input.charCodeAt(peg$currPos) === 40) { - s1 = peg$c0; + s2 = peg$c0; peg$currPos++; } else { - s1 = peg$FAILED; + s2 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e0); } } - if (s1 !== peg$FAILED) { - s2 = []; - s3 = peg$parsews(); - while (s3 !== peg$FAILED) { - s2.push(s3); - s3 = peg$parsews(); + if (s2 !== peg$FAILED) { + s3 = []; + s4 = peg$parsews(); + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$parsews(); } - s3 = peg$parsetoken(); - if (s3 !== peg$FAILED) { - s4 = []; - s5 = peg$parsews(); - if (s5 !== peg$FAILED) { - while (s5 !== peg$FAILED) { - s4.push(s5); - s5 = peg$parsews(); + s4 = peg$parsetoken(); + if (s4 !== peg$FAILED) { + s5 = []; + s6 = peg$parsews(); + if (s6 !== peg$FAILED) { + while (s6 !== peg$FAILED) { + s5.push(s6); + s6 = peg$parsews(); } } else { - s4 = peg$FAILED; + s5 = peg$FAILED; } - if (s4 !== peg$FAILED) { - s5 = peg$parseop_accepts_literal(); - if (s5 !== peg$FAILED) { - s6 = []; - s7 = peg$parsews(); - if (s7 !== peg$FAILED) { - while (s7 !== peg$FAILED) { - s6.push(s7); - s7 = peg$parsews(); + if (s5 !== peg$FAILED) { + s6 = peg$parseop_accepts_literal(); + if (s6 !== peg$FAILED) { + s7 = []; + s8 = peg$parsews(); + if (s8 !== peg$FAILED) { + while (s8 !== peg$FAILED) { + s7.push(s8); + s8 = peg$parsews(); } } else { - s6 = peg$FAILED; + s7 = peg$FAILED; } - if (s6 !== peg$FAILED) { - s7 = peg$parsevalue(); - if (s7 !== peg$FAILED) { - s8 = []; - s9 = peg$parsews(); - while (s9 !== peg$FAILED) { - s8.push(s9); - s9 = peg$parsews(); + if (s7 !== peg$FAILED) { + s8 = peg$parsevalue(); + if (s8 !== peg$FAILED) { + s9 = []; + s10 = peg$parsews(); + while (s10 !== peg$FAILED) { + s9.push(s10); + s10 = peg$parsews(); } if (input.charCodeAt(peg$currPos) === 41) { - s9 = peg$c1; + s10 = peg$c1; peg$currPos++; } else { - s9 = peg$FAILED; + s10 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e1); } } - if (s9 !== peg$FAILED) { + if (s10 !== peg$FAILED) { + s11 = []; + s12 = peg$parsews(); + while (s12 !== peg$FAILED) { + s11.push(s12); + s12 = peg$parsews(); + } peg$savedPos = s0; - s0 = peg$f3(s3, s5, s7); + s0 = peg$f3(s4, s6, s8); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -818,64 +812,76 @@ function peg$parse(input, options) { } if (s0 === peg$FAILED) { s0 = peg$currPos; + s1 = []; + s2 = peg$parsews(); + while (s2 !== peg$FAILED) { + s1.push(s2); + s2 = peg$parsews(); + } if (input.charCodeAt(peg$currPos) === 40) { - s1 = peg$c0; + s2 = peg$c0; peg$currPos++; } else { - s1 = peg$FAILED; + s2 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e0); } } - if (s1 !== peg$FAILED) { - s2 = []; - s3 = peg$parsews(); - while (s3 !== peg$FAILED) { - s2.push(s3); - s3 = peg$parsews(); + if (s2 !== peg$FAILED) { + s3 = []; + s4 = peg$parsews(); + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$parsews(); } - s3 = peg$parsetoken(); - if (s3 !== peg$FAILED) { - s4 = []; - s5 = peg$parsews(); - if (s5 !== peg$FAILED) { - while (s5 !== peg$FAILED) { - s4.push(s5); - s5 = peg$parsews(); + s4 = peg$parsetoken(); + if (s4 !== peg$FAILED) { + s5 = []; + s6 = peg$parsews(); + if (s6 !== peg$FAILED) { + while (s6 !== peg$FAILED) { + s5.push(s6); + s6 = peg$parsews(); } } else { - s4 = peg$FAILED; + s5 = peg$FAILED; } - if (s4 !== peg$FAILED) { - s5 = peg$parseop_accepts_variable(); - if (s5 !== peg$FAILED) { - s6 = []; - s7 = peg$parsews(); - if (s7 !== peg$FAILED) { - while (s7 !== peg$FAILED) { - s6.push(s7); - s7 = peg$parsews(); + if (s5 !== peg$FAILED) { + s6 = peg$parseop_accepts_variable(); + if (s6 !== peg$FAILED) { + s7 = []; + s8 = peg$parsews(); + if (s8 !== peg$FAILED) { + while (s8 !== peg$FAILED) { + s7.push(s8); + s8 = peg$parsews(); } } else { - s6 = peg$FAILED; + s7 = peg$FAILED; } - if (s6 !== peg$FAILED) { - s7 = peg$parsetoken(); - if (s7 !== peg$FAILED) { - s8 = []; - s9 = peg$parsews(); - while (s9 !== peg$FAILED) { - s8.push(s9); - s9 = peg$parsews(); + if (s7 !== peg$FAILED) { + s8 = peg$parsetoken(); + if (s8 !== peg$FAILED) { + s9 = []; + s10 = peg$parsews(); + while (s10 !== peg$FAILED) { + s9.push(s10); + s10 = peg$parsews(); } if (input.charCodeAt(peg$currPos) === 41) { - s9 = peg$c1; + s10 = peg$c1; peg$currPos++; } else { - s9 = peg$FAILED; + s10 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e1); } } - if (s9 !== peg$FAILED) { + if (s10 !== peg$FAILED) { + s11 = []; + s12 = peg$parsews(); + while (s12 !== peg$FAILED) { + s11.push(s12); + s12 = peg$parsews(); + } peg$savedPos = s0; - s0 = peg$f5(s3, s5, s7); + s0 = peg$f5(s4, s6, s8); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -974,18 +980,30 @@ function peg$parse(input, options) { if (peg$silentFails === 0) { peg$fail(peg$e0); } } if (s1 !== peg$FAILED) { - s2 = peg$parsetoken(); - if (s2 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + s3 = peg$parsetoken(); + if (s3 !== peg$FAILED) { + s4 = []; + s5 = peg$parsews(); + while (s5 !== peg$FAILED) { + s4.push(s5); + s5 = peg$parsews(); + } if (input.charCodeAt(peg$currPos) === 41) { - s3 = peg$c1; + s5 = peg$c1; peg$currPos++; } else { - s3 = peg$FAILED; + s5 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e1); } } - if (s3 !== peg$FAILED) { + if (s5 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f8(s2); + s0 = peg$f8(s3); } else { peg$currPos = s0; s0 = peg$FAILED; diff --git a/lib/package/plugins/CC007-ConditionSyntax.js b/lib/package/plugins/CC007-ConditionSyntax.js index 0ccbbce..c96b8a3 100644 --- a/lib/package/plugins/CC007-ConditionSyntax.js +++ b/lib/package/plugins/CC007-ConditionSyntax.js @@ -1,5 +1,5 @@ /* - Copyright 2019-2023 Google LLC + Copyright 2019-2024 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -31,7 +31,7 @@ const plugin = { const onCondition = function (condition, cb) { debug(`onCondition (${condition.getExpression()})`); let flagged = false; - const expr = condition.getExpression(); + const expr = condition.getExpression().trim(); try { parser.parse(expr); } catch (e) { diff --git a/lib/peggy/Apigee-Condition.pegjs b/lib/peggy/Apigee-Condition.pegjs index 47fec58..72d1fef 100644 --- a/lib/peggy/Apigee-Condition.pegjs +++ b/lib/peggy/Apigee-Condition.pegjs @@ -66,7 +66,7 @@ start = boolean_stmt1 boolean_stmt1 - = left:boolean_stmt2 ws+ op1:op_boolean ws+ right:boolean_stmt1 { return {operator:op1, operands:[left, right] } } + = left:boolean_stmt2 ws* op1:op_boolean ws* right:boolean_stmt1 { return {operator:op1, operands:[left, right] } } / boolean_stmt2 boolean_stmt2 @@ -78,20 +78,20 @@ factor / primary primary - = "(" ws* t1:token ws+ op1:op_accepts_literal ws+ v1:value ws* ")" { + = ws* "(" ws* t1:token ws+ op1:op_accepts_literal ws+ v1:value ws* ")" ws* { return parseBinaryOp(t1,op1,v1,error); } / t1:token ws+ op1:op_accepts_literal ws+ v1:value { return parseBinaryOp(t1,op1,v1,error); } - / "(" ws* t1:token ws+ op1:op_accepts_variable ws+ t2:token ws* ")" { + / ws* "(" ws* t1:token ws+ op1:op_accepts_variable ws+ t2:token ws* ")" ws* { return { operator:op1, operands:[t1, t2]}; } / t1:token ws+ op1:op_accepts_variable ws+ t2:token { return { operator:op1, operands:[t1, t2]}; } / token1:token { return token1; } - / "(" token1:token ")" { return token1; } + / "(" ws* token1:token ws* ")" { return token1; } / "(" stmt1:boolean_stmt1 ")" { return stmt1; } op_boolean diff --git a/test/specs/CC007-Condition-Syntax-Test.js b/test/specs/CC007-Condition-Syntax-Test.js index 3ec54b5..df6e730 100644 --- a/test/specs/CC007-Condition-Syntax-Test.js +++ b/test/specs/CC007-Condition-Syntax-Test.js @@ -96,6 +96,62 @@ describe(`${testID} - ${plugin.plugin.name}`, function () { expression: 'request.header.content-type = "application/json" AND request.verb = "GET"', expectError: false + }, + + { + expression: + 'not(request.header.content-type = "application/json")AND(request.verb = "GET")', + expectError: false + }, + { + expression: '(true)AND(request.verb = "GET")', + expectError: false + }, + { + expression: '(true) AND(request.verb = "GET")', + expectError: false + }, + { + expression: '( true ) AND( request.verb = "GET" )', + expectError: false + }, + { + expression: '( true )AND( request.verb = "GET" )', + expectError: false + }, + { + expression: '(true )AND(request.verb = "GET")', + expectError: false + }, + { + expression: '(true ) AND(request.verb = "GET")', + expectError: false + }, + { + expression: '(true ) AND( request.verb = "GET" )', + expectError: false + }, + + /* The following four cases differ only in spacing */ + { + expression: + '((a MatchesPath "/b/d") or (b MatchesPath "/c/d/e")) and (request.verb = "GET")', + expectError: false + }, + { + expression: + '((a MatchesPath "/b/d") or (b MatchesPath "/c/d/e"))and (request.verb = "GET")', + expectError: false + }, + { + expression: + '((a MatchesPath "/b/d") or (b MatchesPath "/c/d/e") )and (request.verb = "GET") ', + expectError: false + }, + { + expression: + '( ( a MatchesPath "/b/d") or (b MatchesPath "/c/d/e") )and (request.verb = "GET")', + expectError: false } ]; cases.forEach((testcase, i) => { diff --git a/test/specs/ConditionParserTest.js b/test/specs/ConditionParserTest.js index 8146ec6..d90a2aa 100644 --- a/test/specs/ConditionParserTest.js +++ b/test/specs/ConditionParserTest.js @@ -336,7 +336,7 @@ describe("ConditionParser", function () { expect.fail(); } catch (e) { expect(e.toString()).to.include("SyntaxError"); - expect(e.toString()).to.include("Expected [ \\t\\n] or end"); + expect(e.toString()).to.include("Expected "); } try { parser.parse(c1.slice(0, -1)); @@ -428,7 +428,7 @@ describe("ConditionParser", function () { expect.fail(); } catch (e) { expect(e.toString()).to.include("SyntaxError"); - expect(e.toString()).to.include('Expected ")"'); + expect(e.toString()).to.include("Expected "); } try { const result = parser.parse(c1.replace('code"', 'code")')); From 4f5d9747fc6e57601b6cdf6594b7cb96edf5ee21 Mon Sep 17 00:00:00 2001 From: Dino Chiesa Date: Tue, 27 Feb 2024 15:46:38 -0800 Subject: [PATCH 2/2] fix: handle no spaces surrounding symbolic operator forms --- build/ConditionParser.js | 1257 ++++++++++++++++++++--------- lib/peggy/Apigee-Condition.pegjs | 67 +- test/specs/ConditionParserTest.js | 28 + 3 files changed, 959 insertions(+), 393 deletions(-) diff --git a/build/ConditionParser.js b/build/ConditionParser.js index 1d1d29f..242d705 100644 --- a/build/ConditionParser.js +++ b/build/ConditionParser.js @@ -308,51 +308,81 @@ function peg$parse(input, options) { var peg$f4 = function(t1, op1, v1) { return parseBinaryOp(t1,op1,v1,error); }; - var peg$f5 = function(t1, op1, t2) { + var peg$f5 = function(t1, op1, v1) { + return parseBinaryOp(t1,op1,v1,error); + }; + var peg$f6 = function(t1, op1, v1) { + return parseBinaryOp(t1,op1,v1,error); + }; + var peg$f7 = function(t1, op1, t2) { + return { operator:op1, operands:[t1, t2]}; + }; + var peg$f8 = function(t1, op1, t2) { + return { operator:op1, operands:[t1, t2]}; + }; + var peg$f9 = function(t1, op1, t2) { return { operator:op1, operands:[t1, t2]}; }; - var peg$f6 = function(t1, op1, t2) { + var peg$f10 = function(t1, op1, t2) { return { operator:op1, operands:[t1, t2]}; }; - var peg$f7 = function(token1) { return token1; }; - var peg$f8 = function(token1) { return token1; }; - var peg$f9 = function(stmt1) { return stmt1; }; - var peg$f10 = function() {return "AND"; }; - var peg$f11 = function() {return "OR"; }; - var peg$f12 = function() { return "EqualsCaseInsensitive"; }; - var peg$f13 = function() {return "StartsWith";}; - var peg$f14 = function() { return "NotEquals"; }; - var peg$f15 = function() { return "Equals"; }; - var peg$f16 = function() {return "GreaterThanOrEquals";}; - var peg$f17 = function() {return "GreaterThan";}; - var peg$f18 = function() {return "LesserThanOrEquals";}; - var peg$f19 = function() {return "LesserThan";}; - var peg$f20 = function() {return "JavaRegex";}; - var peg$f21 = function() {return "MatchesPath";}; - var peg$f22 = function() {return "Matches";}; - var peg$f23 = function() {return "StartsWith";}; - var peg$f24 = function() { return "NotEquals"; }; - var peg$f25 = function() { return "Equals"; }; - var peg$f26 = function() {return "GreaterThanOrEquals";}; - var peg$f27 = function() {return "GreaterThan";}; - var peg$f28 = function() {return "LesserThanOrEquals";}; - var peg$f29 = function() {return "LesserThan";}; - var peg$f30 = function(int1) { return "." + chars.join(''); }; - var peg$f31 = function() { + var peg$f11 = function(token1) { return token1; }; + var peg$f12 = function(token1) { return token1; }; + var peg$f13 = function(stmt1) { return stmt1; }; + var peg$f14 = function() {return "AND"; }; + var peg$f15 = function() {return "OR"; }; + var peg$f16 = function() { return "EqualsCaseInsensitive"; }; + var peg$f17 = function() {return "StartsWith";}; + var peg$f18 = function() { return "NotEquals"; }; + var peg$f19 = function() { return "Equals"; }; + var peg$f20 = function() {return "GreaterThanOrEquals";}; + var peg$f21 = function() {return "GreaterThan";}; + var peg$f22 = function() {return "LesserThanOrEquals";}; + var peg$f23 = function() {return "LesserThan";}; + var peg$f24 = function() {return "JavaRegex";}; + var peg$f25 = function() {return "MatchesPath";}; + var peg$f26 = function() {return "Matches";}; + var peg$f27 = function() { return "EqualsCaseInsensitive"; }; + var peg$f28 = function() {return "StartsWith";}; + var peg$f29 = function() { return "NotEquals"; }; + var peg$f30 = function() { return "Equals"; }; + var peg$f31 = function() {return "GreaterThanOrEquals";}; + var peg$f32 = function() {return "GreaterThan";}; + var peg$f33 = function() {return "LesserThanOrEquals";}; + var peg$f34 = function() {return "LesserThan";}; + var peg$f35 = function() {return "JavaRegex";}; + var peg$f36 = function() {return "MatchesPath";}; + var peg$f37 = function() {return "Matches";}; + var peg$f38 = function() {return "StartsWith";}; + var peg$f39 = function() { return "NotEquals"; }; + var peg$f40 = function() { return "Equals"; }; + var peg$f41 = function() {return "GreaterThanOrEquals";}; + var peg$f42 = function() {return "GreaterThan";}; + var peg$f43 = function() {return "LesserThanOrEquals";}; + var peg$f44 = function() {return "LesserThan";}; + var peg$f45 = function() {return "StartsWith";}; + var peg$f46 = function() { return "NotEquals"; }; + var peg$f47 = function() { return "Equals"; }; + var peg$f48 = function() {return "GreaterThanOrEquals";}; + var peg$f49 = function() {return "GreaterThan";}; + var peg$f50 = function() {return "LesserThanOrEquals";}; + var peg$f51 = function() {return "LesserThan";}; + var peg$f52 = function(int1) { return "." + chars.join(''); }; + var peg$f53 = function() { return { type: "Literal", value: parseFloat(text()) }; }; - var peg$f32 = function() { + var peg$f54 = function() { return { type: "Literal", value: parseFloat(text()) }; }; - var peg$f33 = function() { + var peg$f55 = function() { return { type: "Literal", value: parseInt(text()) }; }; - var peg$f34 = function() { return text(); }; - var peg$f35 = function(value) { value.unshift("'"); value.push("'"); return value; }; - var peg$f36 = function() { return null; }; - var peg$f37 = function() { return false; }; - var peg$f38 = function() { return true; }; - var peg$f39 = function(value) { return value.value; }; + var peg$f56 = function() { return text(); }; + var peg$f57 = function(value) { value.unshift("'"); value.push("'"); return value; }; + var peg$f58 = function() { return null; }; + var peg$f59 = function() { return false; }; + var peg$f60 = function() { return true; }; + var peg$f61 = function(value) { return value.value; }; var peg$currPos = 0; var peg$savedPos = 0; var peg$posDetailsCache = [{ line: 1, column: 1 }]; @@ -760,36 +790,66 @@ function peg$parse(input, options) { } if (s0 === peg$FAILED) { s0 = peg$currPos; - s1 = peg$parsetoken(); - 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$FAILED; + s1 = []; + s2 = peg$parsews(); + while (s2 !== peg$FAILED) { + s1.push(s2); + s2 = peg$parsews(); + } + if (input.charCodeAt(peg$currPos) === 40) { + s2 = peg$c0; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e0); } + } + if (s2 !== peg$FAILED) { + s3 = []; + s4 = peg$parsews(); + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$parsews(); } - if (s2 !== peg$FAILED) { - s3 = peg$parseop_accepts_literal(); - if (s3 !== peg$FAILED) { - s4 = []; - s5 = peg$parsews(); - if (s5 !== peg$FAILED) { - while (s5 !== peg$FAILED) { - s4.push(s5); - s5 = peg$parsews(); - } - } else { - s4 = peg$FAILED; + s4 = peg$parsetoken(); + if (s4 !== peg$FAILED) { + s5 = []; + s6 = peg$parsews(); + while (s6 !== peg$FAILED) { + s5.push(s6); + s6 = peg$parsews(); + } + s6 = peg$parseop_accepts_literal_sym(); + if (s6 !== peg$FAILED) { + s7 = []; + s8 = peg$parsews(); + while (s8 !== peg$FAILED) { + s7.push(s8); + s8 = peg$parsews(); } - if (s4 !== peg$FAILED) { - s5 = peg$parsevalue(); - if (s5 !== peg$FAILED) { + s8 = peg$parsevalue(); + if (s8 !== peg$FAILED) { + s9 = []; + s10 = peg$parsews(); + while (s10 !== peg$FAILED) { + s9.push(s10); + s10 = peg$parsews(); + } + if (input.charCodeAt(peg$currPos) === 41) { + s10 = peg$c1; + peg$currPos++; + } else { + s10 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e1); } + } + if (s10 !== peg$FAILED) { + s11 = []; + s12 = peg$parsews(); + while (s12 !== peg$FAILED) { + s11.push(s12); + s12 = peg$parsews(); + } peg$savedPos = s0; - s0 = peg$f4(s1, s3, s5); + s0 = peg$f4(s4, s6, s8); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -812,84 +872,36 @@ function peg$parse(input, options) { } if (s0 === peg$FAILED) { s0 = peg$currPos; - s1 = []; - s2 = peg$parsews(); - while (s2 !== peg$FAILED) { - s1.push(s2); - s2 = peg$parsews(); - } - if (input.charCodeAt(peg$currPos) === 40) { - s2 = peg$c0; - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e0); } - } - if (s2 !== peg$FAILED) { - s3 = []; - s4 = peg$parsews(); - while (s4 !== peg$FAILED) { - s3.push(s4); - s4 = peg$parsews(); - } - s4 = peg$parsetoken(); - if (s4 !== peg$FAILED) { - s5 = []; - s6 = peg$parsews(); - if (s6 !== peg$FAILED) { - while (s6 !== peg$FAILED) { - s5.push(s6); - s6 = peg$parsews(); - } - } else { - s5 = peg$FAILED; + s1 = peg$parsetoken(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); } - if (s5 !== peg$FAILED) { - s6 = peg$parseop_accepts_variable(); - if (s6 !== peg$FAILED) { - s7 = []; - s8 = peg$parsews(); - if (s8 !== peg$FAILED) { - while (s8 !== peg$FAILED) { - s7.push(s8); - s8 = peg$parsews(); - } - } else { - s7 = peg$FAILED; + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseop_accepts_literal(); + if (s3 !== peg$FAILED) { + s4 = []; + s5 = peg$parsews(); + if (s5 !== peg$FAILED) { + while (s5 !== peg$FAILED) { + s4.push(s5); + s5 = peg$parsews(); } - if (s7 !== peg$FAILED) { - s8 = peg$parsetoken(); - if (s8 !== peg$FAILED) { - s9 = []; - s10 = peg$parsews(); - while (s10 !== peg$FAILED) { - s9.push(s10); - s10 = peg$parsews(); - } - if (input.charCodeAt(peg$currPos) === 41) { - s10 = peg$c1; - peg$currPos++; - } else { - s10 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e1); } - } - if (s10 !== peg$FAILED) { - s11 = []; - s12 = peg$parsews(); - while (s12 !== peg$FAILED) { - s11.push(s12); - s12 = peg$parsews(); - } - peg$savedPos = s0; - s0 = peg$f5(s4, s6, s8); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } + } else { + s4 = peg$FAILED; + } + if (s4 !== peg$FAILED) { + s5 = peg$parsevalue(); + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f5(s1, s3, s5); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -916,32 +928,118 @@ function peg$parse(input, options) { if (s1 !== peg$FAILED) { s2 = []; s3 = peg$parsews(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + s3 = peg$parseop_accepts_literal_sym(); if (s3 !== peg$FAILED) { - while (s3 !== peg$FAILED) { - s2.push(s3); - s3 = peg$parsews(); + s4 = []; + s5 = peg$parsews(); + while (s5 !== peg$FAILED) { + s4.push(s5); + s5 = peg$parsews(); + } + s5 = peg$parsevalue(); + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f6(s1, s3, s5); + } else { + peg$currPos = s0; + s0 = peg$FAILED; } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = []; + s2 = peg$parsews(); + while (s2 !== peg$FAILED) { + s1.push(s2); + s2 = peg$parsews(); + } + if (input.charCodeAt(peg$currPos) === 40) { + s2 = peg$c0; + peg$currPos++; } else { s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e0); } } if (s2 !== peg$FAILED) { - s3 = peg$parseop_accepts_variable(); - if (s3 !== peg$FAILED) { - s4 = []; - s5 = peg$parsews(); - if (s5 !== peg$FAILED) { - while (s5 !== peg$FAILED) { - s4.push(s5); - s5 = peg$parsews(); + s3 = []; + s4 = peg$parsews(); + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$parsews(); + } + s4 = peg$parsetoken(); + if (s4 !== peg$FAILED) { + s5 = []; + s6 = peg$parsews(); + if (s6 !== peg$FAILED) { + while (s6 !== peg$FAILED) { + s5.push(s6); + s6 = peg$parsews(); } } else { - s4 = peg$FAILED; + s5 = peg$FAILED; } - if (s4 !== peg$FAILED) { - s5 = peg$parsetoken(); - if (s5 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f6(s1, s3, s5); + if (s5 !== peg$FAILED) { + s6 = peg$parseop_accepts_variable(); + if (s6 !== peg$FAILED) { + s7 = []; + s8 = peg$parsews(); + if (s8 !== peg$FAILED) { + while (s8 !== peg$FAILED) { + s7.push(s8); + s8 = peg$parsews(); + } + } else { + s7 = peg$FAILED; + } + if (s7 !== peg$FAILED) { + s8 = peg$parsetoken(); + if (s8 !== peg$FAILED) { + s9 = []; + s10 = peg$parsews(); + while (s10 !== peg$FAILED) { + s9.push(s10); + s10 = peg$parsews(); + } + if (input.charCodeAt(peg$currPos) === 41) { + s10 = peg$c1; + peg$currPos++; + } else { + s10 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e1); } + } + if (s10 !== peg$FAILED) { + s11 = []; + s12 = peg$parsews(); + while (s12 !== peg$FAILED) { + s11.push(s12); + s12 = peg$parsews(); + } + peg$savedPos = s0; + s0 = peg$f7(s4, s6, s8); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } } else { peg$currPos = s0; s0 = peg$FAILED; @@ -958,52 +1056,76 @@ function peg$parse(input, options) { peg$currPos = s0; s0 = peg$FAILED; } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$parsetoken(); - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f7(s1); - } - s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; + s1 = []; + s2 = peg$parsews(); + while (s2 !== peg$FAILED) { + s1.push(s2); + s2 = peg$parsews(); + } if (input.charCodeAt(peg$currPos) === 40) { - s1 = peg$c0; + s2 = peg$c0; peg$currPos++; } else { - s1 = peg$FAILED; + s2 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e0); } } - if (s1 !== peg$FAILED) { - s2 = []; - s3 = peg$parsews(); - while (s3 !== peg$FAILED) { - s2.push(s3); - s3 = peg$parsews(); + if (s2 !== peg$FAILED) { + s3 = []; + s4 = peg$parsews(); + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$parsews(); } - s3 = peg$parsetoken(); - if (s3 !== peg$FAILED) { - s4 = []; - s5 = peg$parsews(); - while (s5 !== peg$FAILED) { - s4.push(s5); - s5 = peg$parsews(); - } - if (input.charCodeAt(peg$currPos) === 41) { - s5 = peg$c1; - peg$currPos++; - } else { - s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e1); } + s4 = peg$parsetoken(); + if (s4 !== peg$FAILED) { + s5 = []; + s6 = peg$parsews(); + while (s6 !== peg$FAILED) { + s5.push(s6); + s6 = peg$parsews(); } - if (s5 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f8(s3); + s6 = peg$parseop_accepts_variable_sym(); + if (s6 !== peg$FAILED) { + s7 = []; + s8 = peg$parsews(); + while (s8 !== peg$FAILED) { + s7.push(s8); + s8 = peg$parsews(); + } + s8 = peg$parsetoken(); + if (s8 !== peg$FAILED) { + s9 = []; + s10 = peg$parsews(); + while (s10 !== peg$FAILED) { + s9.push(s10); + s10 = peg$parsews(); + } + if (input.charCodeAt(peg$currPos) === 41) { + s10 = peg$c1; + peg$currPos++; + } else { + s10 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e1); } + } + if (s10 !== peg$FAILED) { + s11 = []; + s12 = peg$parsews(); + while (s12 !== peg$FAILED) { + s11.push(s12); + s12 = peg$parsews(); + } + peg$savedPos = s0; + s0 = peg$f8(s4, s6, s8); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1018,26 +1140,44 @@ function peg$parse(input, options) { } if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 40) { - s1 = peg$c0; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e0); } - } + s1 = peg$parsetoken(); if (s1 !== peg$FAILED) { - s2 = peg$parseboolean_stmt1(); - if (s2 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 41) { - s3 = peg$c1; - peg$currPos++; - } else { - s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e1); } + s2 = []; + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); } + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseop_accepts_variable(); if (s3 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f9(s2); + s4 = []; + s5 = peg$parsews(); + if (s5 !== peg$FAILED) { + while (s5 !== peg$FAILED) { + s4.push(s5); + s5 = peg$parsews(); + } + } else { + s4 = peg$FAILED; + } + if (s4 !== peg$FAILED) { + s5 = peg$parsetoken(); + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f9(s1, s3, s5); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1050,6 +1190,132 @@ function peg$parse(input, options) { peg$currPos = s0; s0 = peg$FAILED; } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parsetoken(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + s3 = peg$parseop_accepts_variable_sym(); + if (s3 !== peg$FAILED) { + s4 = []; + s5 = peg$parsews(); + while (s5 !== peg$FAILED) { + s4.push(s5); + s5 = peg$parsews(); + } + s5 = peg$parsetoken(); + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f10(s1, s3, s5); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parsetoken(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f11(s1); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 40) { + s1 = peg$c0; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e0); } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + s3 = peg$parsetoken(); + if (s3 !== peg$FAILED) { + s4 = []; + s5 = peg$parsews(); + while (s5 !== peg$FAILED) { + s4.push(s5); + s5 = peg$parsews(); + } + if (input.charCodeAt(peg$currPos) === 41) { + s5 = peg$c1; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e1); } + } + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f12(s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 40) { + s1 = peg$c0; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e0); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parseboolean_stmt1(); + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 41) { + s3 = peg$c1; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e1); } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f13(s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + } + } + } } } } @@ -1067,7 +1333,7 @@ function peg$parse(input, options) { s1 = peg$parseop_and(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f10(); + s1 = peg$f14(); } s0 = s1; if (s0 === peg$FAILED) { @@ -1075,7 +1341,7 @@ function peg$parse(input, options) { s1 = peg$parseop_or(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f11(); + s1 = peg$f15(); } s0 = s1; } @@ -1152,94 +1418,94 @@ function peg$parse(input, options) { return s0; } - function peg$parseop_accepts_literal() { + function peg$parseop_accepts_literal_sym() { var s0, s1; s0 = peg$currPos; - s1 = peg$parseop_equalsnocase(); + s1 = peg$parseop_equalsnocase_sym(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f12(); + s1 = peg$f16(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - s1 = peg$parseop_startswith(); + s1 = peg$parseop_startswith_sym(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f13(); + s1 = peg$f17(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - s1 = peg$parseop_notequals(); + s1 = peg$parseop_notequals_sym(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f14(); + s1 = peg$f18(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - s1 = peg$parseop_equals(); + s1 = peg$parseop_equals_sym(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f15(); + s1 = peg$f19(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - s1 = peg$parseop_greatereq(); + s1 = peg$parseop_greatereq_sym(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f16(); + s1 = peg$f20(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - s1 = peg$parseop_greater(); + s1 = peg$parseop_greater_sym(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f17(); + s1 = peg$f21(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - s1 = peg$parseop_lessereq(); + s1 = peg$parseop_lessereq_sym(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f18(); + s1 = peg$f22(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - s1 = peg$parseop_lesser(); + s1 = peg$parseop_lesser_sym(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f19(); + s1 = peg$f23(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - s1 = peg$parseop_regexmatch(); + s1 = peg$parseop_regexmatch_sym(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f20(); + s1 = peg$f24(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - s1 = peg$parseop_matchespath(); + s1 = peg$parseop_matchespath_sym(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f21(); + s1 = peg$f25(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - s1 = peg$parseop_matches(); + s1 = peg$parseop_matches_sym(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f22(); + s1 = peg$f26(); } s0 = s1; } @@ -1256,64 +1522,100 @@ function peg$parse(input, options) { return s0; } - function peg$parseop_accepts_variable() { + function peg$parseop_accepts_literal() { var s0, s1; s0 = peg$currPos; - s1 = peg$parseop_startswith(); + s1 = peg$parseop_equalsnocase(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f23(); + s1 = peg$f27(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - s1 = peg$parseop_notequals(); + s1 = peg$parseop_startswith(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f24(); + s1 = peg$f28(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - s1 = peg$parseop_equals(); + s1 = peg$parseop_notequals(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f25(); + s1 = peg$f29(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - s1 = peg$parseop_greatereq(); + s1 = peg$parseop_equals(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f26(); + s1 = peg$f30(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - s1 = peg$parseop_greater(); + s1 = peg$parseop_greatereq(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f27(); + s1 = peg$f31(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - s1 = peg$parseop_lessereq(); + s1 = peg$parseop_greater(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f28(); + s1 = peg$f32(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - s1 = peg$parseop_lesser(); + s1 = peg$parseop_lessereq(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f29(); + s1 = peg$f33(); } s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseop_lesser(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f34(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseop_regexmatch(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f35(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseop_matchespath(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f36(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseop_matches(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f37(); + } + s0 = s1; + } + } + } + } } } } @@ -1324,7 +1626,143 @@ function peg$parse(input, options) { return s0; } - function peg$parseop_equals() { + function peg$parseop_accepts_variable_sym() { + var s0, s1; + + s0 = peg$currPos; + s1 = peg$parseop_startswith_sym(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f38(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseop_notequals_sym(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f39(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseop_equals_sym(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f40(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseop_greatereq_sym(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f41(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseop_greater_sym(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f42(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseop_lessereq_sym(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f43(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseop_lesser_sym(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f44(); + } + s0 = s1; + } + } + } + } + } + } + + return s0; + } + + function peg$parseop_accepts_variable() { + var s0, s1; + + s0 = peg$currPos; + s1 = peg$parseop_startswith(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f45(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseop_notequals(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f46(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseop_equals(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f47(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseop_greatereq(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f48(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseop_greater(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f49(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseop_lessereq(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f50(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseop_lesser(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f51(); + } + s0 = s1; + } + } + } + } + } + } + + return s0; + } + + function peg$parseop_equals_sym() { var s0; if (input.substr(peg$currPos, 2) === peg$c8) { @@ -1342,30 +1780,35 @@ function peg$parse(input, options) { s0 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e9); } } - if (s0 === peg$FAILED) { - if (input.substr(peg$currPos, 6).toLowerCase() === peg$c10) { - s0 = input.substr(peg$currPos, 6); - peg$currPos += 6; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e10); } - } - if (s0 === peg$FAILED) { - if (input.substr(peg$currPos, 2).toLowerCase() === peg$c11) { - s0 = input.substr(peg$currPos, 2); - peg$currPos += 2; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e11); } - } - } + } + + return s0; + } + + function peg$parseop_equals() { + var s0; + + if (input.substr(peg$currPos, 6).toLowerCase() === peg$c10) { + s0 = input.substr(peg$currPos, 6); + peg$currPos += 6; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e10); } + } + if (s0 === peg$FAILED) { + if (input.substr(peg$currPos, 2).toLowerCase() === peg$c11) { + s0 = input.substr(peg$currPos, 2); + peg$currPos += 2; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e11); } } } return s0; } - function peg$parseop_notequals() { + function peg$parseop_notequals_sym() { var s0; if (input.substr(peg$currPos, 2) === peg$c12) { @@ -1375,29 +1818,34 @@ function peg$parse(input, options) { s0 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e12); } } + + return s0; + } + + function peg$parseop_notequals() { + var s0; + + if (input.substr(peg$currPos, 9).toLowerCase() === peg$c13) { + s0 = input.substr(peg$currPos, 9); + peg$currPos += 9; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e13); } + } if (s0 === peg$FAILED) { - if (input.substr(peg$currPos, 9).toLowerCase() === peg$c13) { - s0 = input.substr(peg$currPos, 9); - peg$currPos += 9; + if (input.substr(peg$currPos, 5).toLowerCase() === peg$c14) { + s0 = input.substr(peg$currPos, 5); + peg$currPos += 5; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e13); } - } - if (s0 === peg$FAILED) { - if (input.substr(peg$currPos, 5).toLowerCase() === peg$c14) { - s0 = input.substr(peg$currPos, 5); - peg$currPos += 5; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e14); } - } + if (peg$silentFails === 0) { peg$fail(peg$e14); } } } return s0; } - function peg$parseop_equalsnocase() { + function peg$parseop_equalsnocase_sym() { var s0; if (input.substr(peg$currPos, 2) === peg$c15) { @@ -1407,20 +1855,25 @@ function peg$parse(input, options) { s0 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e15); } } - if (s0 === peg$FAILED) { - if (input.substr(peg$currPos, 21).toLowerCase() === peg$c16) { - s0 = input.substr(peg$currPos, 21); - peg$currPos += 21; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e16); } - } + + return s0; + } + + function peg$parseop_equalsnocase() { + var s0; + + if (input.substr(peg$currPos, 21).toLowerCase() === peg$c16) { + s0 = input.substr(peg$currPos, 21); + peg$currPos += 21; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e16); } } return s0; } - function peg$parseop_greater() { + function peg$parseop_greater_sym() { var s0; if (input.charCodeAt(peg$currPos) === 62) { @@ -1430,20 +1883,25 @@ function peg$parse(input, options) { s0 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e17); } } - if (s0 === peg$FAILED) { - if (input.substr(peg$currPos, 11).toLowerCase() === peg$c18) { - s0 = input.substr(peg$currPos, 11); - peg$currPos += 11; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e18); } - } + + return s0; + } + + function peg$parseop_greater() { + var s0; + + if (input.substr(peg$currPos, 11).toLowerCase() === peg$c18) { + s0 = input.substr(peg$currPos, 11); + peg$currPos += 11; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e18); } } return s0; } - function peg$parseop_greatereq() { + function peg$parseop_greatereq_sym() { var s0; if (input.substr(peg$currPos, 2) === peg$c19) { @@ -1453,20 +1911,25 @@ function peg$parse(input, options) { s0 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e19); } } - if (s0 === peg$FAILED) { - if (input.substr(peg$currPos, 19).toLowerCase() === peg$c20) { - s0 = input.substr(peg$currPos, 19); - peg$currPos += 19; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e20); } - } + + return s0; + } + + function peg$parseop_greatereq() { + var s0; + + if (input.substr(peg$currPos, 19).toLowerCase() === peg$c20) { + s0 = input.substr(peg$currPos, 19); + peg$currPos += 19; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e20); } } return s0; } - function peg$parseop_lesser() { + function peg$parseop_lesser_sym() { var s0; if (input.charCodeAt(peg$currPos) === 60) { @@ -1476,20 +1939,25 @@ function peg$parse(input, options) { s0 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e21); } } - if (s0 === peg$FAILED) { - if (input.substr(peg$currPos, 10).toLowerCase() === peg$c22) { - s0 = input.substr(peg$currPos, 10); - peg$currPos += 10; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e22); } - } + + return s0; + } + + function peg$parseop_lesser() { + var s0; + + if (input.substr(peg$currPos, 10).toLowerCase() === peg$c22) { + s0 = input.substr(peg$currPos, 10); + peg$currPos += 10; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e22); } } return s0; } - function peg$parseop_lessereq() { + function peg$parseop_lessereq_sym() { var s0; if (input.substr(peg$currPos, 2) === peg$c23) { @@ -1499,20 +1967,25 @@ function peg$parse(input, options) { s0 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e23); } } - if (s0 === peg$FAILED) { - if (input.substr(peg$currPos, 18).toLowerCase() === peg$c24) { - s0 = input.substr(peg$currPos, 18); - peg$currPos += 18; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e24); } - } + + return s0; + } + + function peg$parseop_lessereq() { + var s0; + + if (input.substr(peg$currPos, 18).toLowerCase() === peg$c24) { + s0 = input.substr(peg$currPos, 18); + peg$currPos += 18; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e24); } } return s0; } - function peg$parseop_regexmatch() { + function peg$parseop_regexmatch_sym() { var s0; if (input.substr(peg$currPos, 2) === peg$c25) { @@ -1522,20 +1995,25 @@ function peg$parse(input, options) { s0 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e25); } } - if (s0 === peg$FAILED) { - if (input.substr(peg$currPos, 9).toLowerCase() === peg$c26) { - s0 = input.substr(peg$currPos, 9); - peg$currPos += 9; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e26); } - } + + return s0; + } + + function peg$parseop_regexmatch() { + var s0; + + if (input.substr(peg$currPos, 9).toLowerCase() === peg$c26) { + s0 = input.substr(peg$currPos, 9); + peg$currPos += 9; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e26); } } return s0; } - function peg$parseop_matches() { + function peg$parseop_matches_sym() { var s0; if (input.charCodeAt(peg$currPos) === 126) { @@ -1545,29 +2023,34 @@ function peg$parse(input, options) { s0 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e27); } } + + return s0; + } + + function peg$parseop_matches() { + var s0; + + if (input.substr(peg$currPos, 7).toLowerCase() === peg$c28) { + s0 = input.substr(peg$currPos, 7); + peg$currPos += 7; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e28); } + } if (s0 === peg$FAILED) { - if (input.substr(peg$currPos, 7).toLowerCase() === peg$c28) { - s0 = input.substr(peg$currPos, 7); - peg$currPos += 7; + if (input.substr(peg$currPos, 4).toLowerCase() === peg$c29) { + s0 = input.substr(peg$currPos, 4); + peg$currPos += 4; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e28); } - } - if (s0 === peg$FAILED) { - if (input.substr(peg$currPos, 4).toLowerCase() === peg$c29) { - s0 = input.substr(peg$currPos, 4); - peg$currPos += 4; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e29); } - } + if (peg$silentFails === 0) { peg$fail(peg$e29); } } } return s0; } - function peg$parseop_matchespath() { + function peg$parseop_matchespath_sym() { var s0; if (input.substr(peg$currPos, 2) === peg$c30) { @@ -1577,29 +2060,34 @@ function peg$parse(input, options) { s0 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e30); } } + + return s0; + } + + function peg$parseop_matchespath() { + var s0; + + if (input.substr(peg$currPos, 11).toLowerCase() === peg$c31) { + s0 = input.substr(peg$currPos, 11); + peg$currPos += 11; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e31); } + } if (s0 === peg$FAILED) { - if (input.substr(peg$currPos, 11).toLowerCase() === peg$c31) { - s0 = input.substr(peg$currPos, 11); - peg$currPos += 11; + if (input.substr(peg$currPos, 8).toLowerCase() === peg$c32) { + s0 = input.substr(peg$currPos, 8); + peg$currPos += 8; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e31); } - } - if (s0 === peg$FAILED) { - if (input.substr(peg$currPos, 8).toLowerCase() === peg$c32) { - s0 = input.substr(peg$currPos, 8); - peg$currPos += 8; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e32); } - } + if (peg$silentFails === 0) { peg$fail(peg$e32); } } } return s0; } - function peg$parseop_startswith() { + function peg$parseop_startswith_sym() { var s0; if (input.substr(peg$currPos, 2) === peg$c33) { @@ -1609,14 +2097,19 @@ function peg$parse(input, options) { s0 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e33); } } - if (s0 === peg$FAILED) { - if (input.substr(peg$currPos, 10).toLowerCase() === peg$c34) { - s0 = input.substr(peg$currPos, 10); - peg$currPos += 10; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e34); } - } + + return s0; + } + + function peg$parseop_startswith() { + var s0; + + if (input.substr(peg$currPos, 10).toLowerCase() === peg$c34) { + s0 = input.substr(peg$currPos, 10); + peg$currPos += 10; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e34); } } return s0; @@ -1637,7 +2130,7 @@ function peg$parse(input, options) { s2 = peg$parseDecimalIntegerLiteral(); if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f30(s2); + s0 = peg$f52(s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1693,7 +2186,7 @@ function peg$parse(input, options) { } if (s4 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f31(); + s0 = peg$f53(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1735,7 +2228,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f32(); + s0 = peg$f54(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1759,7 +2252,7 @@ function peg$parse(input, options) { s2 = peg$parseDecimalIntegerLiteral(); if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f33(); + s0 = peg$f55(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1872,7 +2365,7 @@ function peg$parse(input, options) { } } peg$savedPos = s0; - s0 = peg$f34(); + s0 = peg$f56(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1920,7 +2413,7 @@ function peg$parse(input, options) { } if (s3 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f35(s2); + s0 = peg$f57(s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1940,7 +2433,7 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f36(); + s1 = peg$f58(); } s0 = s1; if (s0 === peg$FAILED) { @@ -1954,7 +2447,7 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f37(); + s1 = peg$f59(); } s0 = s1; if (s0 === peg$FAILED) { @@ -1968,7 +2461,7 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f38(); + s1 = peg$f60(); } s0 = s1; if (s0 === peg$FAILED) { @@ -1976,7 +2469,7 @@ function peg$parse(input, options) { s1 = peg$parseDecimalLiteral(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f39(s1); + s1 = peg$f61(s1); } s0 = s1; } diff --git a/lib/peggy/Apigee-Condition.pegjs b/lib/peggy/Apigee-Condition.pegjs index 72d1fef..8e709b4 100644 --- a/lib/peggy/Apigee-Condition.pegjs +++ b/lib/peggy/Apigee-Condition.pegjs @@ -81,15 +81,27 @@ primary = ws* "(" ws* t1:token ws+ op1:op_accepts_literal ws+ v1:value ws* ")" ws* { return parseBinaryOp(t1,op1,v1,error); } + / ws* "(" ws* t1:token ws* op1:op_accepts_literal_sym ws* v1:value ws* ")" ws* { + return parseBinaryOp(t1,op1,v1,error); + } / t1:token ws+ op1:op_accepts_literal ws+ v1:value { return parseBinaryOp(t1,op1,v1,error); } + / t1:token ws* op1:op_accepts_literal_sym ws* v1:value { + return parseBinaryOp(t1,op1,v1,error); + } / ws* "(" ws* t1:token ws+ op1:op_accepts_variable ws+ t2:token ws* ")" ws* { return { operator:op1, operands:[t1, t2]}; } + / ws* "(" ws* t1:token ws* op1:op_accepts_variable_sym ws* t2:token ws* ")" ws* { + return { operator:op1, operands:[t1, t2]}; + } / t1:token ws+ op1:op_accepts_variable ws+ t2:token { return { operator:op1, operands:[t1, t2]}; } + / t1:token ws* op1:op_accepts_variable_sym ws* t2:token { + return { operator:op1, operands:[t1, t2]}; + } / token1:token { return token1; } / "(" ws* token1:token ws* ")" { return token1; } / "(" stmt1:boolean_stmt1 ")" { return stmt1; } @@ -107,6 +119,19 @@ op_or = "or"i / "||" // Ordering is important. For operators that share a common prefix, // list the longer, more specific operator, first. +op_accepts_literal_sym + = op_equalsnocase_sym { return "EqualsCaseInsensitive"; } + / op_startswith_sym {return "StartsWith";} + / op_notequals_sym { return "NotEquals"; } + / op_equals_sym { return "Equals"; } + / op_greatereq_sym {return "GreaterThanOrEquals";} + / op_greater_sym {return "GreaterThan";} + / op_lessereq_sym {return "LesserThanOrEquals";} + / op_lesser_sym {return "LesserThan";} + / op_regexmatch_sym {return "JavaRegex";} + / op_matchespath_sym {return "MatchesPath";} + / op_matches_sym {return "Matches";} + op_accepts_literal = op_equalsnocase { return "EqualsCaseInsensitive"; } / op_startswith {return "StartsWith";} @@ -120,6 +145,15 @@ op_accepts_literal / op_matchespath {return "MatchesPath";} / op_matches {return "Matches";} +op_accepts_variable_sym + = op_startswith_sym {return "StartsWith";} + / op_notequals_sym { return "NotEquals"; } + / op_equals_sym { return "Equals"; } + / op_greatereq_sym {return "GreaterThanOrEquals";} + / op_greater_sym {return "GreaterThan";} + / op_lessereq_sym {return "LesserThanOrEquals";} + / op_lesser_sym {return "LesserThan";} + op_accepts_variable = op_startswith {return "StartsWith";} / op_notequals { return "NotEquals"; } @@ -130,27 +164,38 @@ op_accepts_variable / op_lesser {return "LesserThan";} -op_equals = "==" / "=" / "Equals"i / "Is"i +op_equals_sym = "==" / "=" +op_equals = "Equals"i / "Is"i -op_notequals = "!=" / "NotEquals"i / "IsNot"i +op_notequals_sym = "!=" +op_notequals = "NotEquals"i / "IsNot"i -op_equalsnocase = ":=" / "EqualsCaseInsensitive"i +op_equalsnocase_sym = ":=" +op_equalsnocase = "EqualsCaseInsensitive"i -op_greater = ">" / "GreaterThan"i +op_greater_sym = ">" +op_greater = "GreaterThan"i -op_greatereq = ">=" / "GreaterThanOrEquals"i +op_greatereq_sym = ">=" +op_greatereq = "GreaterThanOrEquals"i -op_lesser = "<" / "LesserThan"i +op_lesser_sym = "<" +op_lesser = "LesserThan"i -op_lessereq = "<=" / "LesserThanOrEquals"i +op_lessereq_sym = "<=" +op_lessereq = "LesserThanOrEquals"i -op_regexmatch = "~~" / "JavaRegex"i +op_regexmatch_sym = "~~" +op_regexmatch = "JavaRegex"i -op_matches = "~" / "Matches"i / "Like"i +op_matches_sym = "~" +op_matches = "Matches"i / "Like"i -op_matchespath = "~/" / "MatchesPath"i / "LikePath"i +op_matchespath_sym = "~/" +op_matchespath = "MatchesPath"i / "LikePath"i -op_startswith = "=|" / "StartsWith"i +op_startswith_sym = "=|" +op_startswith = "StartsWith"i frac_string diff --git a/test/specs/ConditionParserTest.js b/test/specs/ConditionParserTest.js index d90a2aa..7698adb 100644 --- a/test/specs/ConditionParserTest.js +++ b/test/specs/ConditionParserTest.js @@ -21,6 +21,34 @@ const expect = require("chai").expect; //const debug = require("debug")(`apigeelint:ConditionParser`); describe("ConditionParser", function () { + describe("Spacing", function () { + const testcases = [ + [`request.verb="GET"`, `request.verb = "GET"`, "Equals"], + [`request.verb=="GET"`, `request.verb == "GET"`, "Equals"], + [`request.verb=="GET"`, `request.verb =="GET"`, "Equals"], + [`request.verb!="GET"`, `request.verb != "GET"`, "NotEquals"], + [`request.verb!="GET"`, `request.verb!= "GET"`, "NotEquals"], + ["A>250", "A > 250", "GreaterThan"], + ["A<250", "A < 250", "LesserThan"], + ["A>=250", "A >= 250", "GreaterThanOrEquals"], + ["A<=250", "A <= 250", "LesserThanOrEquals"], + [`A:="seven"`, `A := "seven"`, "EqualsCaseInsensitive"], + [`A=|"seven"`, `A =| "seven"`, "StartsWith"], + [`A~"seven"`, `A ~ "seven"`, "Matches"], + [`A~~"^foo(a|b)$"`, `A ~~ "^foo(a|b)$"`, "JavaRegex"], + [`proxy.pathsuffix~/"/a/b"`, `proxy.pathsuffix ~/ "/a/b"`, "MatchesPath"] + ]; + + testcases.forEach((testcase) => { + it(`treats [${testcase[0]}] and [${testcase[1]}] expressions as equivalent`, function () { + const result1 = parser.parse(testcase[0]); + const result2 = parser.parse(testcase[1]); + expect(JSON.stringify(result1)).to.equal(JSON.stringify(result2)); + expect(result1.operator).to.equal(testcase[2]); + }); + }); + }); + describe("Parens", function () { it("treats parenthesized and non-parenthesized atoms as equivalent", function () { const c1 = "valid";