text: /*! odata-array-filter - v0.0.1 - https://github.com/jasongardnerlv/odata-array-filter - (c) 2016 Jason Gardner - licensed MIT */
  ODataParser = (function(){
    /*
     * Generated by PEG.js 0.7.0.
     *
     * http://pegjs.majda.cz/
     */
    
    function quote(s) {
      /*
       * ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a
       * string literal except for the closing quote character, backslash,
       * carriage return, line separator, paragraph separator, and line feed.
       * Any character may appear in the form of an escape sequence.
       *
       * For portability, we also escape escape all control and non-ASCII
       * characters. Note that "\0" and "\v" escape sequences are not used
       * because JSHint does not like the first and IE the second.
       */
       return '"' + s
        .replace(/\\/g, '\\\\')  // backslash
        .replace(/"/g, '\\"')    // closing quote character
        .replace(/\x08/g, '\\b') // backspace
        .replace(/\t/g, '\\t')   // horizontal tab
        .replace(/\n/g, '\\n')   // line feed
        .replace(/\f/g, '\\f')   // form feed
        .replace(/\r/g, '\\r')   // carriage return
        .replace(/[\x00-\x07\x0B\x0E-\x1F\x80-\uFFFF]/g, escape)
        + '"';
    }
    
    var result = {
      /*
       * Parses the input with a generated parser. If the parsing is successfull,
       * returns a value explicitly or implicitly specified by the grammar from
       * which the parser was generated (see |PEG.buildParser|). If the parsing is
       * unsuccessful, throws |PEG.parser.SyntaxError| describing the error.
       */
      parse: function(input, startRule) {
        var parseFunctions = {
          "WSP": parse_WSP,
          "DIGIT": parse_DIGIT,
          "INT": parse_INT,
          "HEXDIG": parse_HEXDIG,
          "HEXDIG2": parse_HEXDIG2,
          "HEXDIG4": parse_HEXDIG4,
          "HEXDIG8": parse_HEXDIG8,
          "SQUOTE": parse_SQUOTE,
          "primitiveLiteral": parse_primitiveLiteral,
          "null": parse_null,
          "binary": parse_binary,
          "boolean": parse_boolean,
          "byte": parse_byte,
          "dateTime": parse_dateTime,
          "dateTimeOffset": parse_dateTimeOffset,
          "dateTimeBodyA": parse_dateTimeBodyA,
          "dateTimeBodyB": parse_dateTimeBodyB,
          "dateTimeBodyC": parse_dateTimeBodyC,
          "dateTimeBodyD": parse_dateTimeBodyD,
          "dateTimeBody": parse_dateTimeBody,
          "dateTimeOffsetBody": parse_dateTimeOffsetBody,
          "decimal": parse_decimal,
          "double": parse_double,
          "guid": parse_guid,
          "int32": parse_int32,
          "int64": parse_int64,
          "sbyte": parse_sbyte,
          "single": parse_single,
          "string": parse_string,
          "oneToNine": parse_oneToNine,
          "zeroToTwelve": parse_zeroToTwelve,
          "zeroToThirteen": parse_zeroToThirteen,
          "zeroToSixty": parse_zeroToSixty,
          "zeroToThirtyOne": parse_zeroToThirtyOne,
          "zeroToTwentyFour": parse_zeroToTwentyFour,
          "year": parse_year,
          "sign": parse_sign,
          "nan": parse_nan,
          "negativeInfinity": parse_negativeInfinity,
          "positiveInfinity": parse_positiveInfinity,
          "nanInfinity": parse_nanInfinity,
          "unreserved": parse_unreserved,
          "validstring": parse_validstring,
          "escapedQuote": parse_escapedQuote,
          "identifierPart": parse_identifierPart,
          "identifier": parse_identifier,
          "callback": parse_callback,
          "top": parse_top,
          "expand": parse_expand,
          "expandList": parse_expandList,
          "skip": parse_skip,
          "format": parse_format,
          "inlinecount": parse_inlinecount,
          "orderby": parse_orderby,
          "orderbyList": parse_orderbyList,
          "select": parse_select,
          "identifierPathParts": parse_identifierPathParts,
          "identifierPath": parse_identifierPath,
          "selectList": parse_selectList,
          "filter": parse_filter,
          "filterExpr": parse_filterExpr,
          "booleanFunctions2Args": parse_booleanFunctions2Args,
          "booleanFunc": parse_booleanFunc,
          "otherFunctions1Arg": parse_otherFunctions1Arg,
          "otherFunc1": parse_otherFunc1,
          "otherFunctions2Arg": parse_otherFunctions2Arg,
          "otherFunc2": parse_otherFunc2,
          "cond": parse_cond,
          "part": parse_part,
          "op": parse_op,
          "unsupported": parse_unsupported,
          "expList": parse_expList,
          "exp": parse_exp,
          "query": parse_query
        };
        
        if (startRule !== undefined) {
          if (parseFunctions[startRule] === undefined) {
            throw new Error("Invalid rule name: " + quote(startRule) + ".");
          }
        } else {
          startRule = "query";
        }
        
        var pos = 0;
        var reportFailures = 0;
        var rightmostFailuresPos = 0;
        var rightmostFailuresExpected = [];
        
        function padLeft(input, padding, length) {
          var result = input;
          
          var padLength = length - input.length;
          for (var i = 0; i < padLength; i++) {
            result = padding + result;
          }
          
          return result;
        }
        
        function escape(ch) {
          var charCode = ch.charCodeAt(0);
          var escapeChar;
          var length;
          
          if (charCode <= 0xFF) {
            escapeChar = 'x';
            length = 2;
          } else {
            escapeChar = 'u';
            length = 4;
          }
          
          return '\\' + escapeChar + padLeft(charCode.toString(16).toUpperCase(), '0', length);
        }
        
        function matchFailed(failure) {
          if (pos < rightmostFailuresPos) {
            return;
          }
          
          if (pos > rightmostFailuresPos) {
            rightmostFailuresPos = pos;
            rightmostFailuresExpected = [];
          }
          
          rightmostFailuresExpected.push(failure);
        }
        
        function parse_WSP() {
          var result0;
          
          if (input.charCodeAt(pos) === 32) {
            result0 = " ";
            pos++;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\" \"");
            }
          }
          return result0;
        }
        
        function parse_DIGIT() {
          var result0;
          
          if (/^[0-9]/.test(input.charAt(pos))) {
            result0 = input.charAt(pos);
            pos++;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("[0-9]");
            }
          }
          return result0;
        }
        
        function parse_INT() {
          var result0, result1;
          var pos0;
          
          pos0 = pos;
          result1 = parse_DIGIT();
          if (result1 !== null) {
            result0 = [];
            while (result1 !== null) {
              result0.push(result1);
              result1 = parse_DIGIT();
            }
          } else {
            result0 = null;
          }
          if (result0 !== null) {
            result0 = (function(offset, a) { return a.join(''); })(pos0, result0);
          }
          if (result0 === null) {
            pos = pos0;
          }
          return result0;
        }
        
        function parse_HEXDIG() {
          var result0;
          
          if (/^[0-9a-fA-F]/.test(input.charAt(pos))) {
            result0 = input.charAt(pos);
            pos++;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("[0-9a-fA-F]");
            }
          }
          return result0;
        }
        
        function parse_HEXDIG2() {
          var result0, result1;
          var pos0;
          
          pos0 = pos;
          result0 = parse_HEXDIG();
          if (result0 !== null) {
            result1 = parse_HEXDIG();
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos0;
            }
          } else {
            result0 = null;
            pos = pos0;
          }
          return result0;
        }
        
        function parse_HEXDIG4() {
          var result0, result1;
          var pos0;
          
          pos0 = pos;
          result0 = parse_HEXDIG2();
          if (result0 !== null) {
            result1 = parse_HEXDIG2();
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos0;
            }
          } else {
            result0 = null;
            pos = pos0;
          }
          return result0;
        }
        
        function parse_HEXDIG8() {
          var result0, result1;
          var pos0;
          
          pos0 = pos;
          result0 = parse_HEXDIG4();
          if (result0 !== null) {
            result1 = parse_HEXDIG8();
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos0;
            }
          } else {
            result0 = null;
            pos = pos0;
          }
          return result0;
        }
        
        function parse_SQUOTE() {
          var result0;
          
          if (input.substr(pos, 4) === "%x27") {
            result0 = "%x27";
            pos += 4;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"%x27\"");
            }
          }
          if (result0 === null) {
            if (input.charCodeAt(pos) === 39) {
              result0 = "'";
              pos++;
            } else {
              result0 = null;
              if (reportFailures === 0) {
                matchFailed("\"'\"");
              }
            }
          }
          return result0;
        }
        
        function parse_primitiveLiteral() {
          var result0;
          
          result0 = parse_null();
          if (result0 === null) {
            result0 = parse_binary();
            if (result0 === null) {
              result0 = parse_dateTime();
              if (result0 === null) {
                result0 = parse_dateTimeOffset();
                if (result0 === null) {
                  result0 = parse_guid();
                  if (result0 === null) {
                    result0 = parse_double();
                    if (result0 === null) {
                      result0 = parse_decimal();
                      if (result0 === null) {
                        result0 = parse_single();
                        if (result0 === null) {
                          result0 = parse_int32();
                          if (result0 === null) {
                            result0 = parse_int64();
                            if (result0 === null) {
                              result0 = parse_byte();
                              if (result0 === null) {
                                result0 = parse_sbyte();
                                if (result0 === null) {
                                  result0 = parse_boolean();
                                  if (result0 === null) {
                                    result0 = parse_string();
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
          return result0;
        }
        
        function parse_null() {
          var result0, result1, result2, result3;
          var pos0, pos1;
          
          pos0 = pos;
          if (input.substr(pos, 4) === "null") {
            result0 = "null";
            pos += 4;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"null\"");
            }
          }
          if (result0 !== null) {
            pos1 = pos;
            if (input.charCodeAt(pos) === 39) {
              result1 = "'";
              pos++;
            } else {
              result1 = null;
              if (reportFailures === 0) {
                matchFailed("\"'\"");
              }
            }
            if (result1 !== null) {
              result2 = parse_identifier();
              if (result2 !== null) {
                if (input.charCodeAt(pos) === 39) {
                  result3 = "'";
                  pos++;
                } else {
                  result3 = null;
                  if (reportFailures === 0) {
                    matchFailed("\"'\"");
                  }
                }
                if (result3 !== null) {
                  result1 = [result1, result2, result3];
                } else {
                  result1 = null;
                  pos = pos1;
                }
              } else {
                result1 = null;
                pos = pos1;
              }
            } else {
              result1 = null;
              pos = pos1;
            }
            result1 = result1 !== null ? result1 : "";
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos0;
            }
          } else {
            result0 = null;
            pos = pos0;
          }
          return result0;
        }
        
        function parse_binary() {
          var result0, result1, result2, result3, result4;
          var pos0;
          
          pos0 = pos;
          if (input.substr(pos, 4) === "%d88") {
            result0 = "%d88";
            pos += 4;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"%d88\"");
            }
          }
          if (result0 === null) {
            if (input.substr(pos, 6) === "binary") {
              result0 = "binary";
              pos += 6;
            } else {
              result0 = null;
              if (reportFailures === 0) {
                matchFailed("\"binary\"");
              }
            }
          }
          if (result0 !== null) {
            result1 = parse_SQUOTE();
            if (result1 !== null) {
              result2 = parse_HEXDIG();
              if (result2 !== null) {
                result3 = parse_HEXDIG();
                if (result3 !== null) {
                  result4 = parse_SQUOTE();
                  if (result4 !== null) {
                    result0 = [result0, result1, result2, result3, result4];
                  } else {
                    result0 = null;
                    pos = pos0;
                  }
                } else {
                  result0 = null;
                  pos = pos0;
                }
              } else {
                result0 = null;
                pos = pos0;
              }
            } else {
              result0 = null;
              pos = pos0;
            }
          } else {
            result0 = null;
            pos = pos0;
          }
          return result0;
        }
        
        function parse_boolean() {
          var result0;
          var pos0;
          
          pos0 = pos;
          if (input.substr(pos, 4) === "true") {
            result0 = "true";
            pos += 4;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"true\"");
            }
          }
          if (result0 !== null) {
            result0 = (function(offset) { return true; })(pos0);
          }
          if (result0 === null) {
            pos = pos0;
          }
          if (result0 === null) {
            pos0 = pos;
            if (input.charCodeAt(pos) === 49) {
              result0 = "1";
              pos++;
            } else {
              result0 = null;
              if (reportFailures === 0) {
                matchFailed("\"1\"");
              }
            }
            if (result0 !== null) {
              result0 = (function(offset) { return true; })(pos0);
            }
            if (result0 === null) {
              pos = pos0;
            }
            if (result0 === null) {
              pos0 = pos;
              if (input.substr(pos, 5) === "false") {
                result0 = "false";
                pos += 5;
              } else {
                result0 = null;
                if (reportFailures === 0) {
                  matchFailed("\"false\"");
                }
              }
              if (result0 !== null) {
                result0 = (function(offset) { return false; })(pos0);
              }
              if (result0 === null) {
                pos = pos0;
              }
              if (result0 === null) {
                pos0 = pos;
                if (input.charCodeAt(pos) === 48) {
                  result0 = "0";
                  pos++;
                } else {
                  result0 = null;
                  if (reportFailures === 0) {
                    matchFailed("\"0\"");
                  }
                }
                if (result0 !== null) {
                  result0 = (function(offset) { return false; })(pos0);
                }
                if (result0 === null) {
                  pos = pos0;
                }
              }
            }
          }
          return result0;
        }
        
        function parse_byte() {
          var result0, result1, result2;
          var pos0;
          
          pos0 = pos;
          result0 = parse_DIGIT();
          if (result0 !== null) {
            result1 = parse_DIGIT();
            if (result1 !== null) {
              result2 = parse_DIGIT();
              if (result2 !== null) {
                result0 = [result0, result1, result2];
              } else {
                result0 = null;
                pos = pos0;
              }
            } else {
              result0 = null;
              pos = pos0;
            }
          } else {
            result0 = null;
            pos = pos0;
          }
          return result0;
        }
        
        function parse_dateTime() {
          var result0, result1, result2, result3;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          if (input.substr(pos, 8) === "datetime") {
            result0 = "datetime";
            pos += 8;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"datetime\"");
            }
          }
          if (result0 !== null) {
            result1 = parse_SQUOTE();
            if (result1 !== null) {
              result2 = parse_dateTimeBody();
              if (result2 !== null) {
                result3 = parse_SQUOTE();
                if (result3 !== null) {
                  result0 = [result0, result1, result2, result3];
                } else {
                  result0 = null;
                  pos = pos1;
                }
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, a) { return new Date(a); })(pos0, result0[2]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          return result0;
        }
        
        function parse_dateTimeOffset() {
          var result0, result1, result2, result3;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          if (input.substr(pos, 14) === "datetimeoffset") {
            result0 = "datetimeoffset";
            pos += 14;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"datetimeoffset\"");
            }
          }
          if (result0 !== null) {
            result1 = parse_SQUOTE();
            if (result1 !== null) {
              result2 = parse_dateTimeOffsetBody();
              if (result2 !== null) {
                result3 = parse_SQUOTE();
                if (result3 !== null) {
                  result0 = [result0, result1, result2, result3];
                } else {
                  result0 = null;
                  pos = pos1;
                }
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, a) { return new Date(a); })(pos0, result0[2]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          return result0;
        }
        
        function parse_dateTimeBodyA() {
          var result0, result1, result2, result3, result4, result5, result6, result7, result8;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          result0 = parse_year();
          if (result0 !== null) {
            if (input.charCodeAt(pos) === 45) {
              result1 = "-";
              pos++;
            } else {
              result1 = null;
              if (reportFailures === 0) {
                matchFailed("\"-\"");
              }
            }
            if (result1 !== null) {
              result2 = parse_zeroToTwelve();
              if (result2 !== null) {
                if (input.charCodeAt(pos) === 45) {
                  result3 = "-";
                  pos++;
                } else {
                  result3 = null;
                  if (reportFailures === 0) {
                    matchFailed("\"-\"");
                  }
                }
                if (result3 !== null) {
                  result4 = parse_zeroToThirtyOne();
                  if (result4 !== null) {
                    if (input.charCodeAt(pos) === 84) {
                      result5 = "T";
                      pos++;
                    } else {
                      result5 = null;
                      if (reportFailures === 0) {
                        matchFailed("\"T\"");
                      }
                    }
                    if (result5 !== null) {
                      result6 = parse_zeroToTwentyFour();
                      if (result6 !== null) {
                        if (input.charCodeAt(pos) === 58) {
                          result7 = ":";
                          pos++;
                        } else {
                          result7 = null;
                          if (reportFailures === 0) {
                            matchFailed("\":\"");
                          }
                        }
                        if (result7 !== null) {
                          result8 = parse_zeroToSixty();
                          if (result8 !== null) {
                            result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8];
                          } else {
                            result0 = null;
                            pos = pos1;
                          }
                        } else {
                          result0 = null;
                          pos = pos1;
                        }
                      } else {
                        result0 = null;
                        pos = pos1;
                      }
                    } else {
                      result0 = null;
                      pos = pos1;
                    }
                  } else {
                    result0 = null;
                    pos = pos1;
                  }
                } else {
                  result0 = null;
                  pos = pos1;
                }
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, a, b, c, d, e) {
                                              return a + '-' + b + '-' + c + "T" + d + ":" + e;
                                          })(pos0, result0[0], result0[2], result0[4], result0[6], result0[8]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          return result0;
        }
        
        function parse_dateTimeBodyB() {
          var result0, result1, result2;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          result0 = parse_dateTimeBodyA();
          if (result0 !== null) {
            if (input.charCodeAt(pos) === 58) {
              result1 = ":";
              pos++;
            } else {
              result1 = null;
              if (reportFailures === 0) {
                matchFailed("\":\"");
              }
            }
            if (result1 !== null) {
              result2 = parse_zeroToSixty();
              if (result2 !== null) {
                result0 = [result0, result1, result2];
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, a, b) { return a + ":" + b; })(pos0, result0[0], result0[2]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          return result0;
        }
        
        function parse_dateTimeBodyC() {
          var result0, result1, result2;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          result0 = parse_dateTimeBodyB();
          if (result0 !== null) {
            if (input.charCodeAt(pos) === 46) {
              result1 = ".";
              pos++;
            } else {
              result1 = null;
              if (reportFailures === 0) {
                matchFailed("\".\"");
              }
            }
            if (result1 !== null) {
              result2 = parse_INT();
              if (result2 !== null) {
                result0 = [result0, result1, result2];
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, a, b) { return a + "." + b; })(pos0, result0[0], result0[2]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          return result0;
        }
        
        function parse_dateTimeBodyD() {
          var result0, result1, result2, result3, result4;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          result0 = parse_dateTimeBodyC();
          if (result0 !== null) {
            if (input.charCodeAt(pos) === 45) {
              result1 = "-";
              pos++;
            } else {
              result1 = null;
              if (reportFailures === 0) {
                matchFailed("\"-\"");
              }
            }
            if (result1 !== null) {
              result2 = parse_zeroToTwentyFour();
              if (result2 !== null) {
                if (input.charCodeAt(pos) === 58) {
                  result3 = ":";
                  pos++;
                } else {
                  result3 = null;
                  if (reportFailures === 0) {
                    matchFailed("\":\"");
                  }
                }
                if (result3 !== null) {
                  result4 = parse_zeroToSixty();
                  if (result4 !== null) {
                    result0 = [result0, result1, result2, result3, result4];
                  } else {
                    result0 = null;
                    pos = pos1;
                  }
                } else {
                  result0 = null;
                  pos = pos1;
                }
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, a, b, c) {
                                              return a + "-" + b + ":" + c;
                                          })(pos0, result0[0], result0[2], result0[4]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          return result0;
        }
        
        function parse_dateTimeBody() {
          var result0;
          
          result0 = parse_dateTimeBodyD();
          if (result0 === null) {
            result0 = parse_dateTimeBodyC();
            if (result0 === null) {
              result0 = parse_dateTimeBodyB();
              if (result0 === null) {
                result0 = parse_dateTimeBodyA();
              }
            }
          }
          return result0;
        }
        
        function parse_dateTimeOffsetBody() {
          var result0, result1, result2, result3, result4;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          result0 = parse_dateTimeBody();
          if (result0 !== null) {
            if (input.charCodeAt(pos) === 90) {
              result1 = "Z";
              pos++;
            } else {
              result1 = null;
              if (reportFailures === 0) {
                matchFailed("\"Z\"");
              }
            }
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, a) { return a + "Z"; })(pos0, result0[0]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          if (result0 === null) {
            pos0 = pos;
            pos1 = pos;
            result0 = parse_dateTimeBody();
            if (result0 !== null) {
              result1 = parse_sign();
              if (result1 !== null) {
                result2 = parse_zeroToThirteen();
                if (result2 !== null) {
                  if (input.substr(pos, 3) === ":00") {
                    result3 = ":00";
                    pos += 3;
                  } else {
                    result3 = null;
                    if (reportFailures === 0) {
                      matchFailed("\":00\"");
                    }
                  }
                  if (result3 !== null) {
                    result0 = [result0, result1, result2, result3];
                  } else {
                    result0 = null;
                    pos = pos1;
                  }
                } else {
                  result0 = null;
                  pos = pos1;
                }
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
            if (result0 !== null) {
              result0 = (function(offset, a, b, c) { return a + b + c + ":00"; })(pos0, result0[0], result0[1], result0[2]);
            }
            if (result0 === null) {
              pos = pos0;
            }
            if (result0 === null) {
              pos0 = pos;
              pos1 = pos;
              result0 = parse_dateTimeBody();
              if (result0 !== null) {
                result1 = parse_sign();
                if (result1 !== null) {
                  result2 = parse_zeroToThirteen();
                  if (result2 !== null) {
                    result0 = [result0, result1, result2];
                  } else {
                    result0 = null;
                    pos = pos1;
                  }
                } else {
                  result0 = null;
                  pos = pos1;
                }
              } else {
                result0 = null;
                pos = pos1;
              }
              if (result0 !== null) {
                result0 = (function(offset, a, b, c) { return a + b + c; })(pos0, result0[0], result0[1], result0[2]);
              }
              if (result0 === null) {
                pos = pos0;
              }
              if (result0 === null) {
                pos0 = pos;
                pos1 = pos;
                result0 = parse_dateTimeBody();
                if (result0 !== null) {
                  result1 = parse_sign();
                  if (result1 !== null) {
                    result2 = parse_zeroToTwelve();
                    if (result2 !== null) {
                      if (input.charCodeAt(pos) === 58) {
                        result3 = ":";
                        pos++;
                      } else {
                        result3 = null;
                        if (reportFailures === 0) {
                          matchFailed("\":\"");
                        }
                      }
                      if (result3 !== null) {
                        result4 = parse_zeroToSixty();
                        if (result4 !== null) {
                          result0 = [result0, result1, result2, result3, result4];
                        } else {
                          result0 = null;
                          pos = pos1;
                        }
                      } else {
                        result0 = null;
                        pos = pos1;
                      }
                    } else {
                      result0 = null;
                      pos = pos1;
                    }
                  } else {
                    result0 = null;
                    pos = pos1;
                  }
                } else {
                  result0 = null;
                  pos = pos1;
                }
                if (result0 !== null) {
                  result0 = (function(offset, a, b, c, d) { return a + b + c + ":" + d; })(pos0, result0[0], result0[1], result0[2], result0[4]);
                }
                if (result0 === null) {
                  pos = pos0;
                }
                if (result0 === null) {
                  pos0 = pos;
                  pos1 = pos;
                  result0 = parse_dateTimeBody();
                  if (result0 !== null) {
                    result1 = parse_sign();
                    if (result1 !== null) {
                      result2 = parse_zeroToTwelve();
                      if (result2 !== null) {
                        result0 = [result0, result1, result2];
                      } else {
                        result0 = null;
                        pos = pos1;
                      }
                    } else {
                      result0 = null;
                      pos = pos1;
                    }
                  } else {
                    result0 = null;
                    pos = pos1;
                  }
                  if (result0 !== null) {
                    result0 = (function(offset, a, b, c) { return a + b + c; })(pos0, result0[0], result0[1], result0[2]);
                  }
                  if (result0 === null) {
                    pos = pos0;
                  }
                }
              }
            }
          }
          return result0;
        }
        
        function parse_decimal() {
          var result0, result1, result2, result3, result4;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          result0 = parse_sign();
          result0 = result0 !== null ? result0 : "";
          if (result0 !== null) {
            result2 = parse_DIGIT();
            if (result2 !== null) {
              result1 = [];
              while (result2 !== null) {
                result1.push(result2);
                result2 = parse_DIGIT();
              }
            } else {
              result1 = null;
            }
            if (result1 !== null) {
              if (input.charCodeAt(pos) === 46) {
                result2 = ".";
                pos++;
              } else {
                result2 = null;
                if (reportFailures === 0) {
                  matchFailed("\".\"");
                }
              }
              if (result2 !== null) {
                result4 = parse_DIGIT();
                if (result4 !== null) {
                  result3 = [];
                  while (result4 !== null) {
                    result3.push(result4);
                    result4 = parse_DIGIT();
                  }
                } else {
                  result3 = null;
                }
                if (result3 !== null) {
                  if (input.charCodeAt(pos) === 77) {
                    result4 = "M";
                    pos++;
                  } else {
                    result4 = null;
                    if (reportFailures === 0) {
                      matchFailed("\"M\"");
                    }
                  }
                  if (result4 === null) {
                    if (input.charCodeAt(pos) === 109) {
                      result4 = "m";
                      pos++;
                    } else {
                      result4 = null;
                      if (reportFailures === 0) {
                        matchFailed("\"m\"");
                      }
                    }
                  }
                  result4 = result4 !== null ? result4 : "";
                  if (result4 !== null) {
                    result0 = [result0, result1, result2, result3, result4];
                  } else {
                    result0 = null;
                    pos = pos1;
                  }
                } else {
                  result0 = null;
                  pos = pos1;
                }
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, sign, digit, decimal) { return sign + digit.join('') + '.' + decimal.join(''); })(pos0, result0[0], result0[1], result0[3]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          if (result0 === null) {
            pos0 = pos;
            pos1 = pos;
            result0 = parse_sign();
            result0 = result0 !== null ? result0 : "";
            if (result0 !== null) {
              result2 = parse_DIGIT();
              if (result2 !== null) {
                result1 = [];
                while (result2 !== null) {
                  result1.push(result2);
                  result2 = parse_DIGIT();
                }
              } else {
                result1 = null;
              }
              if (result1 !== null) {
                if (input.charCodeAt(pos) === 77) {
                  result2 = "M";
                  pos++;
                } else {
                  result2 = null;
                  if (reportFailures === 0) {
                    matchFailed("\"M\"");
                  }
                }
                if (result2 === null) {
                  if (input.charCodeAt(pos) === 109) {
                    result2 = "m";
                    pos++;
                  } else {
                    result2 = null;
                    if (reportFailures === 0) {
                      matchFailed("\"m\"");
                    }
                  }
                }
                if (result2 !== null) {
                  result0 = [result0, result1, result2];
                } else {
                  result0 = null;
                  pos = pos1;
                }
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
            if (result0 !== null) {
              result0 = (function(offset, sign, digit) { return sign + digit.join(''); })(pos0, result0[0], result0[1]);
            }
            if (result0 === null) {
              pos = pos0;
            }
          }
          return result0;
        }
        
        function parse_double() {
          var result0, result1, result2, result3, result4, result5, result6, result7;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          result0 = parse_sign();
          result0 = result0 !== null ? result0 : "";
          if (result0 !== null) {
            result1 = parse_DIGIT();
            if (result1 !== null) {
              if (input.charCodeAt(pos) === 46) {
                result2 = ".";
                pos++;
              } else {
                result2 = null;
                if (reportFailures === 0) {
                  matchFailed("\".\"");
                }
              }
              if (result2 !== null) {
                result4 = parse_DIGIT();
                if (result4 !== null) {
                  result3 = [];
                  while (result4 !== null) {
                    result3.push(result4);
                    result4 = parse_DIGIT();
                  }
                } else {
                  result3 = null;
                }
                if (result3 !== null) {
                  if (input.charCodeAt(pos) === 101) {
                    result4 = "e";
                    pos++;
                  } else {
                    result4 = null;
                    if (reportFailures === 0) {
                      matchFailed("\"e\"");
                    }
                  }
                  if (result4 === null) {
                    if (input.charCodeAt(pos) === 69) {
                      result4 = "E";
                      pos++;
                    } else {
                      result4 = null;
                      if (reportFailures === 0) {
                        matchFailed("\"E\"");
                      }
                    }
                  }
                  if (result4 !== null) {
                    result5 = parse_sign();
                    result5 = result5 !== null ? result5 : "";
                    if (result5 !== null) {
                      result7 = parse_DIGIT();
                      if (result7 !== null) {
                        result6 = [];
                        while (result7 !== null) {
                          result6.push(result7);
                          result7 = parse_DIGIT();
                        }
                      } else {
                        result6 = null;
                      }
                      if (result6 !== null) {
                        if (input.charCodeAt(pos) === 68) {
                          result7 = "D";
                          pos++;
                        } else {
                          result7 = null;
                          if (reportFailures === 0) {
                            matchFailed("\"D\"");
                          }
                        }
                        if (result7 === null) {
                          if (input.charCodeAt(pos) === 100) {
                            result7 = "d";
                            pos++;
                          } else {
                            result7 = null;
                            if (reportFailures === 0) {
                              matchFailed("\"d\"");
                            }
                          }
                        }
                        result7 = result7 !== null ? result7 : "";
                        if (result7 !== null) {
                          result0 = [result0, result1, result2, result3, result4, result5, result6, result7];
                        } else {
                          result0 = null;
                          pos = pos1;
                        }
                      } else {
                        result0 = null;
                        pos = pos1;
                      }
                    } else {
                      result0 = null;
                      pos = pos1;
                    }
                  } else {
                    result0 = null;
                    pos = pos1;
                  }
                } else {
                  result0 = null;
                  pos = pos1;
                }
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, sign, digit, decimal, signexp, exp) { return sign + digit + '.' + decimal.join('') + 'e' + signexp + exp.join(''); })(pos0, result0[0], result0[1], result0[3], result0[5], result0[6]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          if (result0 === null) {
            pos0 = pos;
            pos1 = pos;
            result0 = parse_sign();
            result0 = result0 !== null ? result0 : "";
            if (result0 !== null) {
              result2 = parse_DIGIT();
              if (result2 !== null) {
                result1 = [];
                while (result2 !== null) {
                  result1.push(result2);
                  result2 = parse_DIGIT();
                }
              } else {
                result1 = null;
              }
              if (result1 !== null) {
                if (input.charCodeAt(pos) === 46) {
                  result2 = ".";
                  pos++;
                } else {
                  result2 = null;
                  if (reportFailures === 0) {
                    matchFailed("\".\"");
                  }
                }
                if (result2 !== null) {
                  result4 = parse_DIGIT();
                  if (result4 !== null) {
                    result3 = [];
                    while (result4 !== null) {
                      result3.push(result4);
                      result4 = parse_DIGIT();
                    }
                  } else {
                    result3 = null;
                  }
                  if (result3 !== null) {
                    if (input.charCodeAt(pos) === 68) {
                      result4 = "D";
                      pos++;
                    } else {
                      result4 = null;
                      if (reportFailures === 0) {
                        matchFailed("\"D\"");
                      }
                    }
                    if (result4 === null) {
                      if (input.charCodeAt(pos) === 100) {
                        result4 = "d";
                        pos++;
                      } else {
                        result4 = null;
                        if (reportFailures === 0) {
                          matchFailed("\"d\"");
                        }
                      }
                    }
                    if (result4 !== null) {
                      result0 = [result0, result1, result2, result3, result4];
                    } else {
                      result0 = null;
                      pos = pos1;
                    }
                  } else {
                    result0 = null;
                    pos = pos1;
                  }
                } else {
                  result0 = null;
                  pos = pos1;
                }
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
            if (result0 !== null) {
              result0 = (function(offset, sign, digit, decimal) { return sign + digit.join('') + '.' + decimal.join(''); })(pos0, result0[0], result0[1], result0[3]);
            }
            if (result0 === null) {
              pos = pos0;
            }
            if (result0 === null) {
              pos0 = pos;
              pos1 = pos;
              result0 = parse_sign();
              result0 = result0 !== null ? result0 : "";
              if (result0 !== null) {
                result2 = parse_DIGIT();
                if (result2 !== null) {
                  result1 = [];
                  while (result2 !== null) {
                    result1.push(result2);
                    result2 = parse_DIGIT();
                  }
                } else {
                  result1 = null;
                }
                if (result1 !== null) {
                  if (input.charCodeAt(pos) === 68) {
                    result2 = "D";
                    pos++;
                  } else {
                    result2 = null;
                    if (reportFailures === 0) {
                      matchFailed("\"D\"");
                    }
                  }
                  if (result2 === null) {
                    if (input.charCodeAt(pos) === 100) {
                      result2 = "d";
                      pos++;
                    } else {
                      result2 = null;
                      if (reportFailures === 0) {
                        matchFailed("\"d\"");
                      }
                    }
                  }
                  if (result2 !== null) {
                    result0 = [result0, result1, result2];
                  } else {
                    result0 = null;
                    pos = pos1;
                  }
                } else {
                  result0 = null;
                  pos = pos1;
                }
              } else {
                result0 = null;
                pos = pos1;
              }
              if (result0 !== null) {
                result0 = (function(offset, sign, digit) { return sign + digit.join(''); })(pos0, result0[0], result0[1]);
              }
              if (result0 === null) {
                pos = pos0;
              }
              if (result0 === null) {
                pos0 = pos;
                result0 = parse_nanInfinity();
                if (result0 !== null) {
                  if (input.charCodeAt(pos) === 68) {
                    result1 = "D";
                    pos++;
                  } else {
                    result1 = null;
                    if (reportFailures === 0) {
                      matchFailed("\"D\"");
                    }
                  }
                  if (result1 === null) {
                    if (input.charCodeAt(pos) === 100) {
                      result1 = "d";
                      pos++;
                    } else {
                      result1 = null;
                      if (reportFailures === 0) {
                        matchFailed("\"d\"");
                      }
                    }
                  }
                  result1 = result1 !== null ? result1 : "";
                  if (result1 !== null) {
                    result0 = [result0, result1];
                  } else {
                    result0 = null;
                    pos = pos0;
                  }
                } else {
                  result0 = null;
                  pos = pos0;
                }
              }
            }
          }
          return result0;
        }
        
        function parse_guid() {
          var result0, result1, result2, result3, result4, result5, result6, result7, result8, result9, result10;
          var pos0;
          
          pos0 = pos;
          if (input.substr(pos, 4) === "guid") {
            result0 = "guid";
            pos += 4;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"guid\"");
            }
          }
          if (result0 !== null) {
            result1 = parse_SQUOTE();
            if (result1 !== null) {
              result2 = parse_HEXDIG8();
              if (result2 !== null) {
                if (input.charCodeAt(pos) === 45) {
                  result3 = "-";
                  pos++;
                } else {
                  result3 = null;
                  if (reportFailures === 0) {
                    matchFailed("\"-\"");
                  }
                }
                if (result3 !== null) {
                  result4 = parse_HEXDIG4();
                  if (result4 !== null) {
                    if (input.charCodeAt(pos) === 45) {
                      result5 = "-";
                      pos++;
                    } else {
                      result5 = null;
                      if (reportFailures === 0) {
                        matchFailed("\"-\"");
                      }
                    }
                    if (result5 !== null) {
                      result6 = parse_HEXDIG4();
                      if (result6 !== null) {
                        if (input.charCodeAt(pos) === 45) {
                          result7 = "-";
                          pos++;
                        } else {
                          result7 = null;
                          if (reportFailures === 0) {
                            matchFailed("\"-\"");
                          }
                        }
                        if (result7 !== null) {
                          result8 = parse_HEXDIG8();
                          if (result8 !== null) {
                            result9 = parse_HEXDIG4();
                            if (result9 !== null) {
                              result10 = parse_SQUOTE();
                              if (result10 !== null) {
                                result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8, result9, result10];
                              } else {
                                result0 = null;
                                pos = pos0;
                              }
                            } else {
                              result0 = null;
                              pos = pos0;
                            }
                          } else {
                            result0 = null;
                            pos = pos0;
                          }
                        } else {
                          result0 = null;
                          pos = pos0;
                        }
                      } else {
                        result0 = null;
                        pos = pos0;
                      }
                    } else {
                      result0 = null;
                      pos = pos0;
                    }
                  } else {
                    result0 = null;
                    pos = pos0;
                  }
                } else {
                  result0 = null;
                  pos = pos0;
                }
              } else {
                result0 = null;
                pos = pos0;
              }
            } else {
              result0 = null;
              pos = pos0;
            }
          } else {
            result0 = null;
            pos = pos0;
          }
          return result0;
        }
        
        function parse_int32() {
          var result0, result1, result2;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          result0 = parse_sign();
          result0 = result0 !== null ? result0 : "";
          if (result0 !== null) {
            result2 = parse_DIGIT();
            if (result2 !== null) {
              result1 = [];
              while (result2 !== null) {
                result1.push(result2);
                result2 = parse_DIGIT();
              }
            } else {
              result1 = null;
            }
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, sign, digit) { return parseInt(digit.join('')) * (sign === '-' ? -1 : 1); })(pos0, result0[0], result0[1]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          return result0;
        }
        
        function parse_int64() {
          var result0, result1, result2;
          var pos0;
          
          pos0 = pos;
          result0 = parse_sign();
          result0 = result0 !== null ? result0 : "";
          if (result0 !== null) {
            result2 = parse_DIGIT();
            if (result2 !== null) {
              result1 = [];
              while (result2 !== null) {
                result1.push(result2);
                result2 = parse_DIGIT();
              }
            } else {
              result1 = null;
            }
            if (result1 !== null) {
              if (input.charCodeAt(pos) === 76) {
                result2 = "L";
                pos++;
              } else {
                result2 = null;
                if (reportFailures === 0) {
                  matchFailed("\"L\"");
                }
              }
              if (result2 === null) {
                if (input.charCodeAt(pos) === 108) {
                  result2 = "l";
                  pos++;
                } else {
                  result2 = null;
                  if (reportFailures === 0) {
                    matchFailed("\"l\"");
                  }
                }
              }
              result2 = result2 !== null ? result2 : "";
              if (result2 !== null) {
                result0 = [result0, result1, result2];
              } else {
                result0 = null;
                pos = pos0;
              }
            } else {
              result0 = null;
              pos = pos0;
            }
          } else {
            result0 = null;
            pos = pos0;
          }
          return result0;
        }
        
        function parse_sbyte() {
          var result0, result1, result2, result3;
          var pos0;
          
          pos0 = pos;
          result0 = parse_sign();
          result0 = result0 !== null ? result0 : "";
          if (result0 !== null) {
            result1 = parse_DIGIT();
            if (result1 !== null) {
              result2 = parse_DIGIT();
              result2 = result2 !== null ? result2 : "";
              if (result2 !== null) {
                result3 = parse_DIGIT();
                result3 = result3 !== null ? result3 : "";
                if (result3 !== null) {
                  result0 = [result0, result1, result2, result3];
                } else {
                  result0 = null;
                  pos = pos0;
                }
              } else {
                result0 = null;
                pos = pos0;
              }
            } else {
              result0 = null;
              pos = pos0;
            }
          } else {
            result0 = null;
            pos = pos0;
          }
          return result0;
        }
        
        function parse_single() {
          var result0, result1, result2, result3, result4, result5, result6, result7;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          result0 = parse_sign();
          if (result0 !== null) {
            result1 = parse_DIGIT();
            if (result1 !== null) {
              if (input.charCodeAt(pos) === 46) {
                result2 = ".";
                pos++;
              } else {
                result2 = null;
                if (reportFailures === 0) {
                  matchFailed("\".\"");
                }
              }
              if (result2 !== null) {
                result4 = parse_DIGIT();
                if (result4 !== null) {
                  result3 = [];
                  while (result4 !== null) {
                    result3.push(result4);
                    result4 = parse_DIGIT();
                  }
                } else {
                  result3 = null;
                }
                if (result3 !== null) {
                  if (input.charCodeAt(pos) === 101) {
                    result4 = "e";
                    pos++;
                  } else {
                    result4 = null;
                    if (reportFailures === 0) {
                      matchFailed("\"e\"");
                    }
                  }
                  if (result4 === null) {
                    if (input.charCodeAt(pos) === 69) {
                      result4 = "E";
                      pos++;
                    } else {
                      result4 = null;
                      if (reportFailures === 0) {
                        matchFailed("\"E\"");
                      }
                    }
                  }
                  if (result4 !== null) {
                    result5 = parse_sign();
                    if (result5 !== null) {
                      result7 = parse_DIGIT();
                      if (result7 !== null) {
                        result6 = [];
                        while (result7 !== null) {
                          result6.push(result7);
                          result7 = parse_DIGIT();
                        }
                      } else {
                        result6 = null;
                      }
                      if (result6 !== null) {
                        result0 = [result0, result1, result2, result3, result4, result5, result6];
                      } else {
                        result0 = null;
                        pos = pos1;
                      }
                    } else {
                      result0 = null;
                      pos = pos1;
                    }
                  } else {
                    result0 = null;
                    pos = pos1;
                  }
                } else {
                  result0 = null;
                  pos = pos1;
                }
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 === null) {
            pos1 = pos;
            result0 = parse_sign();
            if (result0 !== null) {
              result1 = [];
              result2 = parse_DIGIT();
              while (result2 !== null) {
                result1.push(result2);
                result2 = parse_DIGIT();
              }
              if (result1 !== null) {
                if (input.charCodeAt(pos) === 46) {
                  result2 = ".";
                  pos++;
                } else {
                  result2 = null;
                  if (reportFailures === 0) {
                    matchFailed("\".\"");
                  }
                }
                if (result2 !== null) {
                  result4 = parse_DIGIT();
                  if (result4 !== null) {
                    result3 = [];
                    while (result4 !== null) {
                      result3.push(result4);
                      result4 = parse_DIGIT();
                    }
                  } else {
                    result3 = null;
                  }
                  if (result3 !== null) {
                    result0 = [result0, result1, result2, result3];
                  } else {
                    result0 = null;
                    pos = pos1;
                  }
                } else {
                  result0 = null;
                  pos = pos1;
                }
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
            if (result0 === null) {
              pos1 = pos;
              result0 = parse_sign();
              if (result0 !== null) {
                result2 = parse_DIGIT();
                if (result2 !== null) {
                  result1 = [];
                  while (result2 !== null) {
                    result1.push(result2);
                    result2 = parse_DIGIT();
                  }
                } else {
                  result1 = null;
                }
                if (result1 !== null) {
                  result0 = [result0, result1];
                } else {
                  result0 = null;
                  pos = pos1;
                }
              } else {
                result0 = null;
                pos = pos1;
              }
            }
          }
          if (result0 !== null) {
            if (input.charCodeAt(pos) === 70) {
              result1 = "F";
              pos++;
            } else {
              result1 = null;
              if (reportFailures === 0) {
                matchFailed("\"F\"");
              }
            }
            if (result1 === null) {
              if (input.charCodeAt(pos) === 102) {
                result1 = "f";
                pos++;
              } else {
                result1 = null;
                if (reportFailures === 0) {
                  matchFailed("\"f\"");
                }
              }
            }
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos0;
            }
          } else {
            result0 = null;
            pos = pos0;
          }
          if (result0 === null) {
            pos0 = pos;
            result0 = parse_nanInfinity();
            if (result0 !== null) {
              if (input.charCodeAt(pos) === 70) {
                result1 = "F";
                pos++;
              } else {
                result1 = null;
                if (reportFailures === 0) {
                  matchFailed("\"F\"");
                }
              }
              if (result1 === null) {
                if (input.charCodeAt(pos) === 102) {
                  result1 = "f";
                  pos++;
                } else {
                  result1 = null;
                  if (reportFailures === 0) {
                    matchFailed("\"f\"");
                  }
                }
              }
              result1 = result1 !== null ? result1 : "";
              if (result1 !== null) {
                result0 = [result0, result1];
              } else {
                result0 = null;
                pos = pos0;
              }
            } else {
              result0 = null;
              pos = pos0;
            }
          }
          return result0;
        }
        
        function parse_string() {
          var result0, result1, result2;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          result0 = parse_SQUOTE();
          if (result0 !== null) {
            result1 = parse_validstring();
            if (result1 !== null) {
              result2 = parse_SQUOTE();
              if (result2 !== null) {
                result0 = [result0, result1, result2];
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, l, v, r) { return v; })(pos0, result0[0], result0[1], result0[2]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          return result0;
        }
        
        function parse_oneToNine() {
          var result0;
          
          if (/^[1-9]/.test(input.charAt(pos))) {
            result0 = input.charAt(pos);
            pos++;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("[1-9]");
            }
          }
          return result0;
        }
        
        function parse_zeroToTwelve() {
          var result0, result1;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          if (input.charCodeAt(pos) === 48) {
            result0 = "0";
            pos++;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"0\"");
            }
          }
          if (result0 !== null) {
            if (/^[1-9]/.test(input.charAt(pos))) {
              result1 = input.charAt(pos);
              pos++;
            } else {
              result1 = null;
              if (reportFailures === 0) {
                matchFailed("[1-9]");
              }
            }
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, a, b) { return a + b;})(pos0, result0[0], result0[1]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          if (result0 === null) {
            pos0 = pos;
            pos1 = pos;
            if (input.charCodeAt(pos) === 49) {
              result0 = "1";
              pos++;
            } else {
              result0 = null;
              if (reportFailures === 0) {
                matchFailed("\"1\"");
              }
            }
            if (result0 !== null) {
              if (/^[0-2]/.test(input.charAt(pos))) {
                result1 = input.charAt(pos);
                pos++;
              } else {
                result1 = null;
                if (reportFailures === 0) {
                  matchFailed("[0-2]");
                }
              }
              if (result1 !== null) {
                result0 = [result0, result1];
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
            if (result0 !== null) {
              result0 = (function(offset, a, b) { return a + b; })(pos0, result0[0], result0[1]);
            }
            if (result0 === null) {
              pos = pos0;
            }
          }
          return result0;
        }
        
        function parse_zeroToThirteen() {
          var result0;
          
          result0 = parse_zeroToTwelve();
          if (result0 === null) {
            if (input.substr(pos, 2) === "13") {
              result0 = "13";
              pos += 2;
            } else {
              result0 = null;
              if (reportFailures === 0) {
                matchFailed("\"13\"");
              }
            }
          }
          return result0;
        }
        
        function parse_zeroToSixty() {
          var result0, result1;
          var pos0, pos1;
          
          if (input.substr(pos, 2) === "60") {
            result0 = "60";
            pos += 2;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"60\"");
            }
          }
          if (result0 === null) {
            pos0 = pos;
            pos1 = pos;
            if (/^[0-5]/.test(input.charAt(pos))) {
              result0 = input.charAt(pos);
              pos++;
            } else {
              result0 = null;
              if (reportFailures === 0) {
                matchFailed("[0-5]");
              }
            }
            if (result0 !== null) {
              result1 = parse_DIGIT();
              if (result1 !== null) {
                result0 = [result0, result1];
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
            if (result0 !== null) {
              result0 = (function(offset, a, b) { return a + b; })(pos0, result0[0], result0[1]);
            }
            if (result0 === null) {
              pos = pos0;
            }
          }
          return result0;
        }
        
        function parse_zeroToThirtyOne() {
          var result0, result1;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          if (input.charCodeAt(pos) === 51) {
            result0 = "3";
            pos++;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"3\"");
            }
          }
          if (result0 !== null) {
            if (/^[0-1]/.test(input.charAt(pos))) {
              result1 = input.charAt(pos);
              pos++;
            } else {
              result1 = null;
              if (reportFailures === 0) {
                matchFailed("[0-1]");
              }
            }
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, a) { return "3" + a; })(pos0, result0[1]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          if (result0 === null) {
            pos0 = pos;
            pos1 = pos;
            if (/^[0-2]/.test(input.charAt(pos))) {
              result0 = input.charAt(pos);
              pos++;
            } else {
              result0 = null;
              if (reportFailures === 0) {
                matchFailed("[0-2]");
              }
            }
            if (result0 !== null) {
              result1 = parse_DIGIT();
              if (result1 !== null) {
                result0 = [result0, result1];
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
            if (result0 !== null) {
              result0 = (function(offset, a, b) { return a + b; })(pos0, result0[0], result0[1]);
            }
            if (result0 === null) {
              pos = pos0;
            }
          }
          return result0;
        }
        
        function parse_zeroToTwentyFour() {
          var result0, result1;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          if (input.charCodeAt(pos) === 50) {
            result0 = "2";
            pos++;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"2\"");
            }
          }
          if (result0 !== null) {
            if (/^[0-4]/.test(input.charAt(pos))) {
              result1 = input.charAt(pos);
              pos++;
            } else {
              result1 = null;
              if (reportFailures === 0) {
                matchFailed("[0-4]");
              }
            }
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, a) { return "2" + a; })(pos0, result0[1]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          if (result0 === null) {
            pos0 = pos;
            pos1 = pos;
            if (/^[0-1]/.test(input.charAt(pos))) {
              result0 = input.charAt(pos);
              pos++;
            } else {
              result0 = null;
              if (reportFailures === 0) {
                matchFailed("[0-1]");
              }
            }
            if (result0 !== null) {
              result1 = parse_DIGIT();
              if (result1 !== null) {
                result0 = [result0, result1];
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
            if (result0 !== null) {
              result0 = (function(offset, a, b) { return a + b; })(pos0, result0[0], result0[1]);
            }
            if (result0 === null) {
              pos = pos0;
            }
          }
          return result0;
        }
        
        function parse_year() {
          var result0, result1, result2, result3;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          result0 = parse_DIGIT();
          if (result0 !== null) {
            result1 = parse_DIGIT();
            if (result1 !== null) {
              result2 = parse_DIGIT();
              if (result2 !== null) {
                result3 = parse_DIGIT();
                if (result3 !== null) {
                  result0 = [result0, result1, result2, result3];
                } else {
                  result0 = null;
                  pos = pos1;
                }
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, a, b, c, d) { return a + b + c + d; })(pos0, result0[0], result0[1], result0[2], result0[3]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          return result0;
        }
        
        function parse_sign() {
          var result0;
          
          if (input.charCodeAt(pos) === 43) {
            result0 = "+";
            pos++;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"+\"");
            }
          }
          if (result0 === null) {
            if (input.charCodeAt(pos) === 45) {
              result0 = "-";
              pos++;
            } else {
              result0 = null;
              if (reportFailures === 0) {
                matchFailed("\"-\"");
              }
            }
          }
          return result0;
        }
        
        function parse_nan() {
          var result0;
          
          if (input.substr(pos, 3) === "NaN") {
            result0 = "NaN";
            pos += 3;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"NaN\"");
            }
          }
          return result0;
        }
        
        function parse_negativeInfinity() {
          var result0;
          
          if (input.substr(pos, 4) === "-INF") {
            result0 = "-INF";
            pos += 4;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"-INF\"");
            }
          }
          return result0;
        }
        
        function parse_positiveInfinity() {
          var result0;
          
          if (input.substr(pos, 3) === "INF") {
            result0 = "INF";
            pos += 3;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"INF\"");
            }
          }
          return result0;
        }
        
        function parse_nanInfinity() {
          var result0;
          
          result0 = parse_nan();
          if (result0 === null) {
            result0 = parse_negativeInfinity();
            if (result0 === null) {
              result0 = parse_positiveInfinity();
            }
          }
          return result0;
        }
        
        function parse_unreserved() {
          var result0, result1;
          var pos0;
          
          pos0 = pos;
          if (/^[a-zA-Z0-9\-_]/.test(input.charAt(pos))) {
            result1 = input.charAt(pos);
            pos++;
          } else {
            result1 = null;
            if (reportFailures === 0) {
              matchFailed("[a-zA-Z0-9\\-_]");
            }
          }
          if (result1 !== null) {
            result0 = [];
            while (result1 !== null) {
              result0.push(result1);
              if (/^[a-zA-Z0-9\-_]/.test(input.charAt(pos))) {
                result1 = input.charAt(pos);
                pos++;
              } else {
                result1 = null;
                if (reportFailures === 0) {
                  matchFailed("[a-zA-Z0-9\\-_]");
                }
              }
            }
          } else {
            result0 = null;
          }
          if (result0 !== null) {
            result0 = (function(offset, a) { return a.join(''); })(pos0, result0);
          }
          if (result0 === null) {
            pos = pos0;
          }
          return result0;
        }
        
        function parse_validstring() {
          var result0, result1;
          var pos0;
          
          pos0 = pos;
          result0 = [];
          if (/^[^']/.test(input.charAt(pos))) {
            result1 = input.charAt(pos);
            pos++;
          } else {
            result1 = null;
            if (reportFailures === 0) {
              matchFailed("[^']");
            }
          }
          if (result1 === null) {
            result1 = parse_escapedQuote();
          }
          while (result1 !== null) {
            result0.push(result1);
            if (/^[^']/.test(input.charAt(pos))) {
              result1 = input.charAt(pos);
              pos++;
            } else {
              result1 = null;
              if (reportFailures === 0) {
                matchFailed("[^']");
              }
            }
            if (result1 === null) {
              result1 = parse_escapedQuote();
            }
          }
          if (result0 !== null) {
            result0 = (function(offset, a) { return a.join('').replace(/('')/g, "'"); })(pos0, result0);
          }
          if (result0 === null) {
            pos = pos0;
          }
          return result0;
        }
        
        function parse_escapedQuote() {
          var result0;
          var pos0;
          
          pos0 = pos;
          if (input.substr(pos, 2) === "''") {
            result0 = "''";
            pos += 2;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"''\"");
            }
          }
          if (result0 !== null) {
            result0 = (function(offset, a) { return a; })(pos0, result0);
          }
          if (result0 === null) {
            pos = pos0;
          }
          return result0;
        }
        
        function parse_identifierPart() {
          var result0, result1;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          if (/^[_a-zA-Z]/.test(input.charAt(pos))) {
            result0 = input.charAt(pos);
            pos++;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("[_a-zA-Z]");
            }
          }
          if (result0 !== null) {
            result1 = parse_unreserved();
            result1 = result1 !== null ? result1 : "";
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, a, b) { return a + b; })(pos0, result0[0], result0[1]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          return result0;
        }
        
        function parse_identifier() {
          var result0, result1, result2;
          var pos0, pos1, pos2, pos3;
          
          pos0 = pos;
          pos1 = pos;
          result0 = parse_identifierPart();
          if (result0 !== null) {
            pos2 = pos;
            pos3 = pos;
            if (input.charCodeAt(pos) === 46) {
              result1 = ".";
              pos++;
            } else {
              result1 = null;
              if (reportFailures === 0) {
                matchFailed("\".\"");
              }
            }
            if (result1 !== null) {
              result2 = parse_identifier();
              if (result2 !== null) {
                result1 = [result1, result2];
              } else {
                result1 = null;
                pos = pos3;
              }
            } else {
              result1 = null;
              pos = pos3;
            }
            if (result1 !== null) {
              result1 = (function(offset, i) {return i;})(pos2, result1[1]);
            }
            if (result1 === null) {
              pos = pos2;
            }
            result1 = result1 !== null ? result1 : "";
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, a, list) {
                                              if (list === "") list = [];
                                              if (Array.isArray(list[0])) {
                                                  list = list[0];
                                              }
                                              list.unshift(a);
                                              return list.join('.');
                                          })(pos0, result0[0], result0[1]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          return result0;
        }
        
        function parse_callback() {
          var result0, result1;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          if (input.substr(pos, 10) === "$callback=") {
            result0 = "$callback=";
            pos += 10;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"$callback=\"");
            }
          }
          if (result0 !== null) {
            result1 = parse_identifier();
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, a) { return { '$callback': a }; })(pos0, result0[1]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          return result0;
        }
        
        function parse_top() {
          var result0, result1, result2;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          if (input.substr(pos, 5) === "$top=") {
            result0 = "$top=";
            pos += 5;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"$top=\"");
            }
          }
          if (result0 !== null) {
            result1 = parse_INT();
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, a) { return { '$top': ~~a }; })(pos0, result0[1]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          if (result0 === null) {
            pos0 = pos;
            pos1 = pos;
            if (input.substr(pos, 5) === "$top=") {
              result0 = "$top=";
              pos += 5;
            } else {
              result0 = null;
              if (reportFailures === 0) {
                matchFailed("\"$top=\"");
              }
            }
            if (result0 !== null) {
              result1 = [];
              if (input.length > pos) {
                result2 = input.charAt(pos);
                pos++;
              } else {
                result2 = null;
                if (reportFailures === 0) {
                  matchFailed("any character");
                }
              }
              while (result2 !== null) {
                result1.push(result2);
                if (input.length > pos) {
                  result2 = input.charAt(pos);
                  pos++;
                } else {
                  result2 = null;
                  if (reportFailures === 0) {
                    matchFailed("any character");
                  }
                }
              }
              if (result1 !== null) {
                result0 = [result0, result1];
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
            if (result0 !== null) {
              result0 = (function(offset) { return {"error": 'invalid $top parameter'}; })(pos0);
            }
            if (result0 === null) {
              pos = pos0;
            }
          }
          return result0;
        }
        
        function parse_expand() {
          var result0, result1, result2;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          if (input.substr(pos, 8) === "$expand=") {
            result0 = "$expand=";
            pos += 8;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"$expand=\"");
            }
          }
          if (result0 !== null) {
            result1 = parse_expandList();
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, list) { return { "$expand": list }; })(pos0, result0[1]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          if (result0 === null) {
            pos0 = pos;
            pos1 = pos;
            if (input.substr(pos, 8) === "$expand=") {
              result0 = "$expand=";
              pos += 8;
            } else {
              result0 = null;
              if (reportFailures === 0) {
                matchFailed("\"$expand=\"");
              }
            }
            if (result0 !== null) {
              result1 = [];
              if (input.length > pos) {
                result2 = input.charAt(pos);
                pos++;
              } else {
                result2 = null;
                if (reportFailures === 0) {
                  matchFailed("any character");
                }
              }
              while (result2 !== null) {
                result1.push(result2);
                if (input.length > pos) {
                  result2 = input.charAt(pos);
                  pos++;
                } else {
                  result2 = null;
                  if (reportFailures === 0) {
                    matchFailed("any character");
                  }
                }
              }
              if (result1 !== null) {
                result0 = [result0, result1];
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
            if (result0 !== null) {
              result0 = (function(offset) { return {"error": 'invalid $expand parameter'}; })(pos0);
            }
            if (result0 === null) {
              pos = pos0;
            }
          }
          return result0;
        }
        
        function parse_expandList() {
          var result0, result1, result2, result3;
          var pos0, pos1, pos2, pos3;
          
          pos0 = pos;
          pos1 = pos;
          result0 = parse_identifierPath();
          if (result0 !== null) {
            pos2 = pos;
            pos3 = pos;
            if (input.charCodeAt(pos) === 44) {
              result1 = ",";
              pos++;
            } else {
              result1 = null;
              if (reportFailures === 0) {
                matchFailed("\",\"");
              }
            }
            if (result1 !== null) {
              result2 = parse_WSP();
              result2 = result2 !== null ? result2 : "";
              if (result2 !== null) {
                result3 = parse_expandList();
                if (result3 !== null) {
                  result1 = [result1, result2, result3];
                } else {
                  result1 = null;
                  pos = pos3;
                }
              } else {
                result1 = null;
                pos = pos3;
              }
            } else {
              result1 = null;
              pos = pos3;
            }
            if (result1 !== null) {
              result1 = (function(offset, l) {return l;})(pos2, result1[2]);
            }
            if (result1 === null) {
              pos = pos2;
            }
            result1 = result1 !== null ? result1 : "";
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, i, list) {
                                              if (list === "") list = [];
                                              if (Array.isArray(list[0])) {
                                                  list = list[0];
                                              }
                                              list.unshift(i);
                                              return list;
                                          })(pos0, result0[0], result0[1]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          return result0;
        }
        
        function parse_skip() {
          var result0, result1, result2;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          if (input.substr(pos, 6) === "$skip=") {
            result0 = "$skip=";
            pos += 6;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"$skip=\"");
            }
          }
          if (result0 !== null) {
            result1 = parse_INT();
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, a) {return {'$skip': ~~a }; })(pos0, result0[1]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          if (result0 === null) {
            pos0 = pos;
            pos1 = pos;
            if (input.substr(pos, 6) === "$skip=") {
              result0 = "$skip=";
              pos += 6;
            } else {
              result0 = null;
              if (reportFailures === 0) {
                matchFailed("\"$skip=\"");
              }
            }
            if (result0 !== null) {
              result1 = [];
              if (input.length > pos) {
                result2 = input.charAt(pos);
                pos++;
              } else {
                result2 = null;
                if (reportFailures === 0) {
                  matchFailed("any character");
                }
              }
              while (result2 !== null) {
                result1.push(result2);
                if (input.length > pos) {
                  result2 = input.charAt(pos);
                  pos++;
                } else {
                  result2 = null;
                  if (reportFailures === 0) {
                    matchFailed("any character");
                  }
                }
              }
              if (result1 !== null) {
                result0 = [result0, result1];
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
            if (result0 !== null) {
              result0 = (function(offset) { return {"error": 'invalid $skip parameter'}; })(pos0);
            }
            if (result0 === null) {
              pos = pos0;
            }
          }
          return result0;
        }
        
        function parse_format() {
          var result0, result1, result2;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          if (input.substr(pos, 8) === "$format=") {
            result0 = "$format=";
            pos += 8;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"$format=\"");
            }
          }
          if (result0 !== null) {
            if (input.length > pos) {
              result2 = input.charAt(pos);
              pos++;
            } else {
              result2 = null;
              if (reportFailures === 0) {
                matchFailed("any character");
              }
            }
            if (result2 !== null) {
              result1 = [];
              while (result2 !== null) {
                result1.push(result2);
                if (input.length > pos) {
                  result2 = input.charAt(pos);
                  pos++;
                } else {
                  result2 = null;
                  if (reportFailures === 0) {
                    matchFailed("any character");
                  }
                }
              }
            } else {
              result1 = null;
            }
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, v) { return {'$format': v.join('') }; })(pos0, result0[1]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          if (result0 === null) {
            pos0 = pos;
            pos1 = pos;
            if (input.substr(pos, 8) === "$format=") {
              result0 = "$format=";
              pos += 8;
            } else {
              result0 = null;
              if (reportFailures === 0) {
                matchFailed("\"$format=\"");
              }
            }
            if (result0 !== null) {
              result1 = [];
              if (input.length > pos) {
                result2 = input.charAt(pos);
                pos++;
              } else {
                result2 = null;
                if (reportFailures === 0) {
                  matchFailed("any character");
                }
              }
              while (result2 !== null) {
                result1.push(result2);
                if (input.length > pos) {
                  result2 = input.charAt(pos);
                  pos++;
                } else {
                  result2 = null;
                  if (reportFailures === 0) {
                    matchFailed("any character");
                  }
                }
              }
              if (result1 !== null) {
                result0 = [result0, result1];
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
            if (result0 !== null) {
              result0 = (function(offset) { return {"error": 'invalid $format parameter'}; })(pos0);
            }
            if (result0 === null) {
              pos = pos0;
            }
          }
          return result0;
        }
        
        function parse_inlinecount() {
          var result0, result1, result2;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          if (input.substr(pos, 13) === "$inlinecount=") {
            result0 = "$inlinecount=";
            pos += 13;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"$inlinecount=\"");
            }
          }
          if (result0 !== null) {
            if (input.substr(pos, 8) === "allpages") {
              result1 = "allpages";
              pos += 8;
            } else {
              result1 = null;
              if (reportFailures === 0) {
                matchFailed("\"allpages\"");
              }
            }
            if (result1 === null) {
              if (input.substr(pos, 4) === "none") {
                result1 = "none";
                pos += 4;
              } else {
                result1 = null;
                if (reportFailures === 0) {
                  matchFailed("\"none\"");
                }
              }
            }
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, v) { return {'$inlinecount': v }; })(pos0, result0[1]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          if (result0 === null) {
            pos0 = pos;
            pos1 = pos;
            if (input.substr(pos, 13) === "$inlinecount=") {
              result0 = "$inlinecount=";
              pos += 13;
            } else {
              result0 = null;
              if (reportFailures === 0) {
                matchFailed("\"$inlinecount=\"");
              }
            }
            if (result0 !== null) {
              result1 = [];
              if (input.length > pos) {
                result2 = input.charAt(pos);
                pos++;
              } else {
                result2 = null;
                if (reportFailures === 0) {
                  matchFailed("any character");
                }
              }
              while (result2 !== null) {
                result1.push(result2);
                if (input.length > pos) {
                  result2 = input.charAt(pos);
                  pos++;
                } else {
                  result2 = null;
                  if (reportFailures === 0) {
                    matchFailed("any character");
                  }
                }
              }
              if (result1 !== null) {
                result0 = [result0, result1];
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
            if (result0 !== null) {
              result0 = (function(offset) { return {"error": 'invalid $inlinecount parameter'}; })(pos0);
            }
            if (result0 === null) {
              pos = pos0;
            }
          }
          return result0;
        }
        
        function parse_orderby() {
          var result0, result1, result2;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          if (input.substr(pos, 9) === "$orderby=") {
            result0 = "$orderby=";
            pos += 9;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"$orderby=\"");
            }
          }
          if (result0 !== null) {
            result1 = parse_orderbyList();
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, list) {
                                              return { "$orderby": list }; })(pos0, result0[1]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          if (result0 === null) {
            pos0 = pos;
            pos1 = pos;
            if (input.substr(pos, 9) === "$orderby=") {
              result0 = "$orderby=";
              pos += 9;
            } else {
              result0 = null;
              if (reportFailures === 0) {
                matchFailed("\"$orderby=\"");
              }
            }
            if (result0 !== null) {
              result1 = [];
              if (input.length > pos) {
                result2 = input.charAt(pos);
                pos++;
              } else {
                result2 = null;
                if (reportFailures === 0) {
                  matchFailed("any character");
                }
              }
              while (result2 !== null) {
                result1.push(result2);
                if (input.length > pos) {
                  result2 = input.charAt(pos);
                  pos++;
                } else {
                  result2 = null;
                  if (reportFailures === 0) {
                    matchFailed("any character");
                  }
                }
              }
              if (result1 !== null) {
                result0 = [result0, result1];
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
            if (result0 !== null) {
              result0 = (function(offset) { return {"error": 'invalid $orderby parameter'}; })(pos0);
            }
            if (result0 === null) {
              pos = pos0;
            }
          }
          return result0;
        }
        
        function parse_orderbyList() {
          var result0, result1, result2, result3;
          var pos0, pos1, pos2, pos3, pos4;
          
          pos0 = pos;
          pos1 = pos;
          pos2 = pos;
          pos3 = pos;
          result0 = parse_identifier();
          if (result0 !== null) {
            pos4 = pos;
            result1 = parse_WSP();
            if (result1 !== null) {
              if (input.substr(pos, 3) === "asc") {
                result2 = "asc";
                pos += 3;
              } else {
                result2 = null;
                if (reportFailures === 0) {
                  matchFailed("\"asc\"");
                }
              }
              if (result2 === null) {
                if (input.substr(pos, 4) === "desc") {
                  result2 = "desc";
                  pos += 4;
                } else {
                  result2 = null;
                  if (reportFailures === 0) {
                    matchFailed("\"desc\"");
                  }
                }
              }
              if (result2 !== null) {
                result1 = [result1, result2];
              } else {
                result1 = null;
                pos = pos4;
              }
            } else {
              result1 = null;
              pos = pos4;
            }
            result1 = result1 !== null ? result1 : "";
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos3;
            }
          } else {
            result0 = null;
            pos = pos3;
          }
          if (result0 !== null) {
            result0 = (function(offset, id, ord) {
                                              var result = {};
                                              result[id] = ord[1] || 'asc';
                                              return result;
                                          })(pos2, result0[0], result0[1]);
          }
          if (result0 === null) {
            pos = pos2;
          }
          if (result0 !== null) {
            pos2 = pos;
            pos3 = pos;
            if (input.charCodeAt(pos) === 44) {
              result1 = ",";
              pos++;
            } else {
              result1 = null;
              if (reportFailures === 0) {
                matchFailed("\",\"");
              }
            }
            if (result1 !== null) {
              result2 = parse_WSP();
              result2 = result2 !== null ? result2 : "";
              if (result2 !== null) {
                result3 = parse_orderbyList();
                if (result3 !== null) {
                  result1 = [result1, result2, result3];
                } else {
                  result1 = null;
                  pos = pos3;
                }
              } else {
                result1 = null;
                pos = pos3;
              }
            } else {
              result1 = null;
              pos = pos3;
            }
            if (result1 !== null) {
              result1 = (function(offset, l) {return l;})(pos2, result1[2]);
            }
            if (result1 === null) {
              pos = pos2;
            }
            result1 = result1 !== null ? result1 : "";
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, i, list) {
          
                                              if (list === "") list = [];
                                              if (Array.isArray(list[0])) {
                                                  list = list[0];
                                              }
                                              list.unshift(i);
                                              return list;
                                          })(pos0, result0[0], result0[1]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          return result0;
        }
        
        function parse_select() {
          var result0, result1, result2;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          if (input.substr(pos, 8) === "$select=") {
            result0 = "$select=";
            pos += 8;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"$select=\"");
            }
          }
          if (result0 !== null) {
            result1 = parse_selectList();
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, list) { return { "$select":list }; })(pos0, result0[1]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          if (result0 === null) {
            pos0 = pos;
            pos1 = pos;
            if (input.substr(pos, 8) === "$select=") {
              result0 = "$select=";
              pos += 8;
            } else {
              result0 = null;
              if (reportFailures === 0) {
                matchFailed("\"$select=\"");
              }
            }
            if (result0 !== null) {
              result1 = [];
              if (input.length > pos) {
                result2 = input.charAt(pos);
                pos++;
              } else {
                result2 = null;
                if (reportFailures === 0) {
                  matchFailed("any character");
                }
              }
              while (result2 !== null) {
                result1.push(result2);
                if (input.length > pos) {
                  result2 = input.charAt(pos);
                  pos++;
                } else {
                  result2 = null;
                  if (reportFailures === 0) {
                    matchFailed("any character");
                  }
                }
              }
              if (result1 !== null) {
                result0 = [result0, result1];
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
            if (result0 !== null) {
              result0 = (function(offset) { return {"error": 'invalid $select parameter'}; })(pos0);
            }
            if (result0 === null) {
              pos = pos0;
            }
          }
          return result0;
        }
        
        function parse_identifierPathParts() {
          var result0, result1, result2;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          if (input.charCodeAt(pos) === 47) {
            result0 = "/";
            pos++;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"/\"");
            }
          }
          if (result0 !== null) {
            result1 = parse_identifierPart();
            if (result1 !== null) {
              result2 = parse_identifierPathParts();
              result2 = result2 !== null ? result2 : "";
              if (result2 !== null) {
                result0 = [result0, result1, result2];
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, i, list) {
                                              if (Array.isArray(list[0])) {
                                                  list = list[0];
                                              }
                                              return "/" + i + list;
                                          })(pos0, result0[1], result0[2]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          return result0;
        }
        
        function parse_identifierPath() {
          var result0, result1;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          result0 = parse_identifier();
          if (result0 !== null) {
            result1 = parse_identifierPathParts();
            result1 = result1 !== null ? result1 : "";
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, a, b) { return a + b; })(pos0, result0[0], result0[1]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          return result0;
        }
        
        function parse_selectList() {
          var result0, result1, result2, result3;
          var pos0, pos1, pos2, pos3;
          
          pos0 = pos;
          pos1 = pos;
          pos2 = pos;
          pos3 = pos;
          result0 = parse_identifierPath();
          if (result0 !== null) {
            if (input.substr(pos, 2) === ".*") {
              result1 = ".*";
              pos += 2;
            } else {
              result1 = null;
              if (reportFailures === 0) {
                matchFailed("\".*\"");
              }
            }
            result1 = result1 !== null ? result1 : "";
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos3;
            }
          } else {
            result0 = null;
            pos = pos3;
          }
          if (result0 !== null) {
            result0 = (function(offset, a, b) {return a + b;})(pos2, result0[0], result0[1]);
          }
          if (result0 === null) {
            pos = pos2;
          }
          if (result0 === null) {
            if (input.charCodeAt(pos) === 42) {
              result0 = "*";
              pos++;
            } else {
              result0 = null;
              if (reportFailures === 0) {
                matchFailed("\"*\"");
              }
            }
          }
          if (result0 !== null) {
            pos2 = pos;
            pos3 = pos;
            if (input.charCodeAt(pos) === 44) {
              result1 = ",";
              pos++;
            } else {
              result1 = null;
              if (reportFailures === 0) {
                matchFailed("\",\"");
              }
            }
            if (result1 !== null) {
              result2 = parse_WSP();
              result2 = result2 !== null ? result2 : "";
              if (result2 !== null) {
                result3 = parse_selectList();
                if (result3 !== null) {
                  result1 = [result1, result2, result3];
                } else {
                  result1 = null;
                  pos = pos3;
                }
              } else {
                result1 = null;
                pos = pos3;
              }
            } else {
              result1 = null;
              pos = pos3;
            }
            if (result1 !== null) {
              result1 = (function(offset, l) {return l;})(pos2, result1[2]);
            }
            if (result1 === null) {
              pos = pos2;
            }
            result1 = result1 !== null ? result1 : "";
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, i, list) {
                                              if (list === "") list = [];
                                              if (Array.isArray(list[0])) {
                                                  list = list[0];
                                              }
                                              list.unshift(i);
                                              return list;
                                          })(pos0, result0[0], result0[1]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          return result0;
        }
        
        function parse_filter() {
          var result0, result1, result2;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          if (input.substr(pos, 8) === "$filter=") {
            result0 = "$filter=";
            pos += 8;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"$filter=\"");
            }
          }
          if (result0 !== null) {
            result1 = parse_filterExpr();
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, list) {
                                              return {
                                                  "$filter": list
                                              };
                                          })(pos0, result0[1]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          if (result0 === null) {
            pos0 = pos;
            pos1 = pos;
            if (input.substr(pos, 8) === "$filter=") {
              result0 = "$filter=";
              pos += 8;
            } else {
              result0 = null;
              if (reportFailures === 0) {
                matchFailed("\"$filter=\"");
              }
            }
            if (result0 !== null) {
              result1 = [];
              if (input.length > pos) {
                result2 = input.charAt(pos);
                pos++;
              } else {
                result2 = null;
                if (reportFailures === 0) {
                  matchFailed("any character");
                }
              }
              while (result2 !== null) {
                result1.push(result2);
                if (input.length > pos) {
                  result2 = input.charAt(pos);
                  pos++;
                } else {
                  result2 = null;
                  if (reportFailures === 0) {
                    matchFailed("any character");
                  }
                }
              }
              if (result1 !== null) {
                result0 = [result0, result1];
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
            if (result0 !== null) {
              result0 = (function(offset) { return {"error": 'invalid $filter parameter'}; })(pos0);
            }
            if (result0 === null) {
              pos = pos0;
            }
          }
          return result0;
        }
        
        function parse_filterExpr() {
          var result0, result1, result2, result3, result4;
          var pos0, pos1, pos2, pos3;
          
          pos0 = pos;
          pos1 = pos;
          pos2 = pos;
          pos3 = pos;
          if (input.charCodeAt(pos) === 40) {
            result0 = "(";
            pos++;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"(\"");
            }
          }
          if (result0 !== null) {
            result1 = parse_WSP();
            result1 = result1 !== null ? result1 : "";
            if (result1 !== null) {
              result2 = parse_filterExpr();
              if (result2 !== null) {
                result3 = parse_WSP();
                result3 = result3 !== null ? result3 : "";
                if (result3 !== null) {
                  if (input.charCodeAt(pos) === 41) {
                    result4 = ")";
                    pos++;
                  } else {
                    result4 = null;
                    if (reportFailures === 0) {
                      matchFailed("\")\"");
                    }
                  }
                  if (result4 !== null) {
                    result0 = [result0, result1, result2, result3, result4];
                  } else {
                    result0 = null;
                    pos = pos3;
                  }
                } else {
                  result0 = null;
                  pos = pos3;
                }
              } else {
                result0 = null;
                pos = pos3;
              }
            } else {
              result0 = null;
              pos = pos3;
            }
          } else {
            result0 = null;
            pos = pos3;
          }
          if (result0 !== null) {
            result0 = (function(offset, filter) {return filter})(pos2, result0[2]);
          }
          if (result0 === null) {
            pos = pos2;
          }
          if (result0 !== null) {
            pos2 = pos;
            pos3 = pos;
            result1 = parse_WSP();
            if (result1 !== null) {
              if (input.substr(pos, 3) === "and") {
                result2 = "and";
                pos += 3;
              } else {
                result2 = null;
                if (reportFailures === 0) {
                  matchFailed("\"and\"");
                }
              }
              if (result2 === null) {
                if (input.substr(pos, 2) === "or") {
                  result2 = "or";
                  pos += 2;
                } else {
                  result2 = null;
                  if (reportFailures === 0) {
                    matchFailed("\"or\"");
                  }
                }
              }
              if (result2 !== null) {
                result3 = parse_WSP();
                if (result3 !== null) {
                  result4 = parse_filterExpr();
                  if (result4 !== null) {
                    result1 = [result1, result2, result3, result4];
                  } else {
                    result1 = null;
                    pos = pos3;
                  }
                } else {
                  result1 = null;
                  pos = pos3;
                }
              } else {
                result1 = null;
                pos = pos3;
              }
            } else {
              result1 = null;
              pos = pos3;
            }
            if (result1 !== null) {
              result1 = (function(offset, type, value) {
                                                return { type: type, value: value}
                                          })(pos2, result1[1], result1[3]);
            }
            if (result1 === null) {
              pos = pos2;
            }
            result1 = result1 !== null ? result1 : "";
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, left, right) {
                                          return filterExprHelper(left, right);
                                        })(pos0, result0[0], result0[1]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          if (result0 === null) {
            pos0 = pos;
            pos1 = pos;
            result0 = parse_cond();
            if (result0 !== null) {
              pos2 = pos;
              pos3 = pos;
              result1 = parse_WSP();
              if (result1 !== null) {
                if (input.substr(pos, 3) === "and") {
                  result2 = "and";
                  pos += 3;
                } else {
                  result2 = null;
                  if (reportFailures === 0) {
                    matchFailed("\"and\"");
                  }
                }
                if (result2 === null) {
                  if (input.substr(pos, 2) === "or") {
                    result2 = "or";
                    pos += 2;
                  } else {
                    result2 = null;
                    if (reportFailures === 0) {
                      matchFailed("\"or\"");
                    }
                  }
                }
                if (result2 !== null) {
                  result3 = parse_WSP();
                  if (result3 !== null) {
                    result4 = parse_filterExpr();
                    if (result4 !== null) {
                      result1 = [result1, result2, result3, result4];
                    } else {
                      result1 = null;
                      pos = pos3;
                    }
                  } else {
                    result1 = null;
                    pos = pos3;
                  }
                } else {
                  result1 = null;
                  pos = pos3;
                }
              } else {
                result1 = null;
                pos = pos3;
              }
              if (result1 !== null) {
                result1 = (function(offset, type, value) {
                                                  return { type: type, value: value}
                                            })(pos2, result1[1], result1[3]);
              }
              if (result1 === null) {
                pos = pos2;
              }
              result1 = result1 !== null ? result1 : "";
              if (result1 !== null) {
                result0 = [result0, result1];
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
            if (result0 !== null) {
              result0 = (function(offset, left, right) {
                                            return filterExprHelper(left, right);
                                          })(pos0, result0[0], result0[1]);
            }
            if (result0 === null) {
              pos = pos0;
            }
          }
          return result0;
        }
        
        function parse_booleanFunctions2Args() {
          var result0;
          
          if (input.substr(pos, 11) === "substringof") {
            result0 = "substringof";
            pos += 11;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"substringof\"");
            }
          }
          if (result0 === null) {
            if (input.substr(pos, 8) === "endswith") {
              result0 = "endswith";
              pos += 8;
            } else {
              result0 = null;
              if (reportFailures === 0) {
                matchFailed("\"endswith\"");
              }
            }
            if (result0 === null) {
              if (input.substr(pos, 10) === "startswith") {
                result0 = "startswith";
                pos += 10;
              } else {
                result0 = null;
                if (reportFailures === 0) {
                  matchFailed("\"startswith\"");
                }
              }
              if (result0 === null) {
                if (input.substr(pos, 4) === "IsOf") {
                  result0 = "IsOf";
                  pos += 4;
                } else {
                  result0 = null;
                  if (reportFailures === 0) {
                    matchFailed("\"IsOf\"");
                  }
                }
              }
            }
          }
          return result0;
        }
        
        function parse_booleanFunc() {
          var result0, result1, result2, result3, result4, result5, result6;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          result0 = parse_booleanFunctions2Args();
          if (result0 !== null) {
            if (input.charCodeAt(pos) === 40) {
              result1 = "(";
              pos++;
            } else {
              result1 = null;
              if (reportFailures === 0) {
                matchFailed("\"(\"");
              }
            }
            if (result1 !== null) {
              result2 = parse_part();
              if (result2 !== null) {
                if (input.charCodeAt(pos) === 44) {
                  result3 = ",";
                  pos++;
                } else {
                  result3 = null;
                  if (reportFailures === 0) {
                    matchFailed("\",\"");
                  }
                }
                if (result3 !== null) {
                  result4 = parse_WSP();
                  result4 = result4 !== null ? result4 : "";
                  if (result4 !== null) {
                    result5 = parse_part();
                    if (result5 !== null) {
                      if (input.charCodeAt(pos) === 41) {
                        result6 = ")";
                        pos++;
                      } else {
                        result6 = null;
                        if (reportFailures === 0) {
                          matchFailed("\")\"");
                        }
                      }
                      if (result6 !== null) {
                        result0 = [result0, result1, result2, result3, result4, result5, result6];
                      } else {
                        result0 = null;
                        pos = pos1;
                      }
                    } else {
                      result0 = null;
                      pos = pos1;
                    }
                  } else {
                    result0 = null;
                    pos = pos1;
                  }
                } else {
                  result0 = null;
                  pos = pos1;
                }
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, f, arg0, arg1) {
                                              return {
                                                  type: "functioncall",
                                                  func: f,
                                                  args: [arg0, arg1]
                                              }
                                          })(pos0, result0[0], result0[2], result0[5]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          if (result0 === null) {
            pos0 = pos;
            pos1 = pos;
            if (input.substr(pos, 5) === "IsOf(") {
              result0 = "IsOf(";
              pos += 5;
            } else {
              result0 = null;
              if (reportFailures === 0) {
                matchFailed("\"IsOf(\"");
              }
            }
            if (result0 !== null) {
              result1 = parse_part();
              if (result1 !== null) {
                if (input.charCodeAt(pos) === 41) {
                  result2 = ")";
                  pos++;
                } else {
                  result2 = null;
                  if (reportFailures === 0) {
                    matchFailed("\")\"");
                  }
                }
                if (result2 !== null) {
                  result0 = [result0, result1, result2];
                } else {
                  result0 = null;
                  pos = pos1;
                }
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
            if (result0 !== null) {
              result0 = (function(offset, arg0) {
                                                return {
                                                    type: "functioncall",
                                                    func: "IsOf",
                                                    args: [arg0]
                                                }
                                            })(pos0, result0[1]);
            }
            if (result0 === null) {
              pos = pos0;
            }
          }
          return result0;
        }
        
        function parse_otherFunctions1Arg() {
          var result0;
          
          if (input.substr(pos, 7) === "tolower") {
            result0 = "tolower";
            pos += 7;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"tolower\"");
            }
          }
          if (result0 === null) {
            if (input.substr(pos, 7) === "toupper") {
              result0 = "toupper";
              pos += 7;
            } else {
              result0 = null;
              if (reportFailures === 0) {
                matchFailed("\"toupper\"");
              }
            }
            if (result0 === null) {
              if (input.substr(pos, 4) === "trim") {
                result0 = "trim";
                pos += 4;
              } else {
                result0 = null;
                if (reportFailures === 0) {
                  matchFailed("\"trim\"");
                }
              }
              if (result0 === null) {
                if (input.substr(pos, 6) === "length") {
                  result0 = "length";
                  pos += 6;
                } else {
                  result0 = null;
                  if (reportFailures === 0) {
                    matchFailed("\"length\"");
                  }
                }
                if (result0 === null) {
                  if (input.substr(pos, 4) === "year") {
                    result0 = "year";
                    pos += 4;
                  } else {
                    result0 = null;
                    if (reportFailures === 0) {
                      matchFailed("\"year\"");
                    }
                  }
                  if (result0 === null) {
                    if (input.substr(pos, 5) === "month") {
                      result0 = "month";
                      pos += 5;
                    } else {
                      result0 = null;
                      if (reportFailures === 0) {
                        matchFailed("\"month\"");
                      }
                    }
                    if (result0 === null) {
                      if (input.substr(pos, 3) === "day") {
                        result0 = "day";
                        pos += 3;
                      } else {
                        result0 = null;
                        if (reportFailures === 0) {
                          matchFailed("\"day\"");
                        }
                      }
                      if (result0 === null) {
                        if (input.substr(pos, 4) === "hour") {
                          result0 = "hour";
                          pos += 4;
                        } else {
                          result0 = null;
                          if (reportFailures === 0) {
                            matchFailed("\"hour\"");
                          }
                        }
                        if (result0 === null) {
                          if (input.substr(pos, 6) === "minute") {
                            result0 = "minute";
                            pos += 6;
                          } else {
                            result0 = null;
                            if (reportFailures === 0) {
                              matchFailed("\"minute\"");
                            }
                          }
                          if (result0 === null) {
                            if (input.substr(pos, 6) === "second") {
                              result0 = "second";
                              pos += 6;
                            } else {
                              result0 = null;
                              if (reportFailures === 0) {
                                matchFailed("\"second\"");
                              }
                            }
                            if (result0 === null) {
                              if (input.substr(pos, 5) === "round") {
                                result0 = "round";
                                pos += 5;
                              } else {
                                result0 = null;
                                if (reportFailures === 0) {
                                  matchFailed("\"round\"");
                                }
                              }
                              if (result0 === null) {
                                if (input.substr(pos, 5) === "floor") {
                                  result0 = "floor";
                                  pos += 5;
                                } else {
                                  result0 = null;
                                  if (reportFailures === 0) {
                                    matchFailed("\"floor\"");
                                  }
                                }
                                if (result0 === null) {
                                  if (input.substr(pos, 7) === "ceiling") {
                                    result0 = "ceiling";
                                    pos += 7;
                                  } else {
                                    result0 = null;
                                    if (reportFailures === 0) {
                                      matchFailed("\"ceiling\"");
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
          return result0;
        }
        
        function parse_otherFunc1() {
          var result0, result1, result2, result3;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          result0 = parse_otherFunctions1Arg();
          if (result0 !== null) {
            if (input.charCodeAt(pos) === 40) {
              result1 = "(";
              pos++;
            } else {
              result1 = null;
              if (reportFailures === 0) {
                matchFailed("\"(\"");
              }
            }
            if (result1 !== null) {
              result2 = parse_part();
              if (result2 !== null) {
                if (input.charCodeAt(pos) === 41) {
                  result3 = ")";
                  pos++;
                } else {
                  result3 = null;
                  if (reportFailures === 0) {
                    matchFailed("\")\"");
                  }
                }
                if (result3 !== null) {
                  result0 = [result0, result1, result2, result3];
                } else {
                  result0 = null;
                  pos = pos1;
                }
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, f, arg0) {
                                            return {
                                                type: "functioncall",
                                                func: f,
                                                args: [arg0]
                                            }
                                        })(pos0, result0[0], result0[2]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          return result0;
        }
        
        function parse_otherFunctions2Arg() {
          var result0;
          
          if (input.substr(pos, 7) === "indexof") {
            result0 = "indexof";
            pos += 7;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"indexof\"");
            }
          }
          if (result0 === null) {
            if (input.substr(pos, 6) === "concat") {
              result0 = "concat";
              pos += 6;
            } else {
              result0 = null;
              if (reportFailures === 0) {
                matchFailed("\"concat\"");
              }
            }
            if (result0 === null) {
              if (input.substr(pos, 9) === "substring") {
                result0 = "substring";
                pos += 9;
              } else {
                result0 = null;
                if (reportFailures === 0) {
                  matchFailed("\"substring\"");
                }
              }
              if (result0 === null) {
                if (input.substr(pos, 7) === "replace") {
                  result0 = "replace";
                  pos += 7;
                } else {
                  result0 = null;
                  if (reportFailures === 0) {
                    matchFailed("\"replace\"");
                  }
                }
              }
            }
          }
          return result0;
        }
        
        function parse_otherFunc2() {
          var result0, result1, result2, result3, result4, result5, result6, result7, result8, result9;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          result0 = parse_otherFunctions2Arg();
          if (result0 !== null) {
            if (input.charCodeAt(pos) === 40) {
              result1 = "(";
              pos++;
            } else {
              result1 = null;
              if (reportFailures === 0) {
                matchFailed("\"(\"");
              }
            }
            if (result1 !== null) {
              result2 = parse_part();
              if (result2 !== null) {
                if (input.charCodeAt(pos) === 44) {
                  result3 = ",";
                  pos++;
                } else {
                  result3 = null;
                  if (reportFailures === 0) {
                    matchFailed("\",\"");
                  }
                }
                if (result3 !== null) {
                  result4 = parse_WSP();
                  result4 = result4 !== null ? result4 : "";
                  if (result4 !== null) {
                    result5 = parse_part();
                    if (result5 !== null) {
                      if (input.charCodeAt(pos) === 41) {
                        result6 = ")";
                        pos++;
                      } else {
                        result6 = null;
                        if (reportFailures === 0) {
                          matchFailed("\")\"");
                        }
                      }
                      if (result6 !== null) {
                        result0 = [result0, result1, result2, result3, result4, result5, result6];
                      } else {
                        result0 = null;
                        pos = pos1;
                      }
                    } else {
                      result0 = null;
                      pos = pos1;
                    }
                  } else {
                    result0 = null;
                    pos = pos1;
                  }
                } else {
                  result0 = null;
                  pos = pos1;
                }
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, f, arg0, arg1) {
                                            return {
                                                type: "functioncall",
                                                func: f,
                                                args: [arg0, arg1]
                                            }
                                        })(pos0, result0[0], result0[2], result0[5]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          if (result0 === null) {
            pos0 = pos;
            pos1 = pos;
            if (input.substr(pos, 9) === "substring") {
              result0 = "substring";
              pos += 9;
            } else {
              result0 = null;
              if (reportFailures === 0) {
                matchFailed("\"substring\"");
              }
            }
            if (result0 !== null) {
              if (input.charCodeAt(pos) === 40) {
                result1 = "(";
                pos++;
              } else {
                result1 = null;
                if (reportFailures === 0) {
                  matchFailed("\"(\"");
                }
              }
              if (result1 !== null) {
                result2 = parse_part();
                if (result2 !== null) {
                  if (input.charCodeAt(pos) === 44) {
                    result3 = ",";
                    pos++;
                  } else {
                    result3 = null;
                    if (reportFailures === 0) {
                      matchFailed("\",\"");
                    }
                  }
                  if (result3 !== null) {
                    result4 = parse_WSP();
                    result4 = result4 !== null ? result4 : "";
                    if (result4 !== null) {
                      result5 = parse_part();
                      if (result5 !== null) {
                        if (input.charCodeAt(pos) === 44) {
                          result6 = ",";
                          pos++;
                        } else {
                          result6 = null;
                          if (reportFailures === 0) {
                            matchFailed("\",\"");
                          }
                        }
                        if (result6 !== null) {
                          result7 = parse_WSP();
                          result7 = result7 !== null ? result7 : "";
                          if (result7 !== null) {
                            result8 = parse_part();
                            if (result8 !== null) {
                              if (input.charCodeAt(pos) === 41) {
                                result9 = ")";
                                pos++;
                              } else {
                                result9 = null;
                                if (reportFailures === 0) {
                                  matchFailed("\")\"");
                                }
                              }
                              if (result9 !== null) {
                                result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8, result9];
                              } else {
                                result0 = null;
                                pos = pos1;
                              }
                            } else {
                              result0 = null;
                              pos = pos1;
                            }
                          } else {
                            result0 = null;
                            pos = pos1;
                          }
                        } else {
                          result0 = null;
                          pos = pos1;
                        }
                      } else {
                        result0 = null;
                        pos = pos1;
                      }
                    } else {
                      result0 = null;
                      pos = pos1;
                    }
                  } else {
                    result0 = null;
                    pos = pos1;
                  }
                } else {
                  result0 = null;
                  pos = pos1;
                }
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
            if (result0 !== null) {
              result0 = (function(offset, arg0, arg1, arg2) {
                                              return {
                                                  type: "functioncall",
                                                  func: "substring",
                                                  args: [arg0, arg1, arg2]
                                              }
                                          })(pos0, result0[2], result0[5], result0[8]);
            }
            if (result0 === null) {
              pos = pos0;
            }
            if (result0 === null) {
              pos0 = pos;
              pos1 = pos;
              if (input.substr(pos, 7) === "replace") {
                result0 = "replace";
                pos += 7;
              } else {
                result0 = null;
                if (reportFailures === 0) {
                  matchFailed("\"replace\"");
                }
              }
              if (result0 !== null) {
                if (input.charCodeAt(pos) === 40) {
                  result1 = "(";
                  pos++;
                } else {
                  result1 = null;
                  if (reportFailures === 0) {
                    matchFailed("\"(\"");
                  }
                }
                if (result1 !== null) {
                  result2 = parse_part();
                  if (result2 !== null) {
                    if (input.charCodeAt(pos) === 44) {
                      result3 = ",";
                      pos++;
                    } else {
                      result3 = null;
                      if (reportFailures === 0) {
                        matchFailed("\",\"");
                      }
                    }
                    if (result3 !== null) {
                      result4 = parse_WSP();
                      result4 = result4 !== null ? result4 : "";
                      if (result4 !== null) {
                        result5 = parse_part();
                        if (result5 !== null) {
                          if (input.charCodeAt(pos) === 44) {
                            result6 = ",";
                            pos++;
                          } else {
                            result6 = null;
                            if (reportFailures === 0) {
                              matchFailed("\",\"");
                            }
                          }
                          if (result6 !== null) {
                            result7 = parse_WSP();
                            result7 = result7 !== null ? result7 : "";
                            if (result7 !== null) {
                              result8 = parse_part();
                              if (result8 !== null) {
                                if (input.charCodeAt(pos) === 41) {
                                  result9 = ")";
                                  pos++;
                                } else {
                                  result9 = null;
                                  if (reportFailures === 0) {
                                    matchFailed("\")\"");
                                  }
                                }
                                if (result9 !== null) {
                                  result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8, result9];
                                } else {
                                  result0 = null;
                                  pos = pos1;
                                }
                              } else {
                                result0 = null;
                                pos = pos1;
                              }
                            } else {
                              result0 = null;
                              pos = pos1;
                            }
                          } else {
                            result0 = null;
                            pos = pos1;
                          }
                        } else {
                          result0 = null;
                          pos = pos1;
                        }
                      } else {
                        result0 = null;
                        pos = pos1;
                      }
                    } else {
                      result0 = null;
                      pos = pos1;
                    }
                  } else {
                    result0 = null;
                    pos = pos1;
                  }
                } else {
                  result0 = null;
                  pos = pos1;
                }
              } else {
                result0 = null;
                pos = pos1;
              }
              if (result0 !== null) {
                result0 = (function(offset, arg0, arg1, arg2) {
                                                return {
                                                    type: "functioncall",
                                                    func: "replace",
                                                    args: [arg0, arg1, arg2]
                                                }
                                            })(pos0, result0[2], result0[5], result0[8]);
              }
              if (result0 === null) {
                pos = pos0;
              }
            }
          }
          return result0;
        }
        
        function parse_cond() {
          var result0, result1, result2, result3, result4;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          result0 = parse_part();
          if (result0 !== null) {
            result1 = parse_WSP();
            if (result1 !== null) {
              result2 = parse_op();
              if (result2 !== null) {
                result3 = parse_WSP();
                if (result3 !== null) {
                  result4 = parse_part();
                  if (result4 !== null) {
                    result0 = [result0, result1, result2, result3, result4];
                  } else {
                    result0 = null;
                    pos = pos1;
                  }
                } else {
                  result0 = null;
                  pos = pos1;
                }
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, a, op, b) {
                                              return {
                                                  type: op,
                                                  left: a,
                                                  right: b
                                              };
                                          })(pos0, result0[0], result0[2], result0[4]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          if (result0 === null) {
            result0 = parse_booleanFunc();
          }
          return result0;
        }
        
        function parse_part() {
          var result0;
          var pos0;
          
          result0 = parse_booleanFunc();
          if (result0 === null) {
            result0 = parse_otherFunc2();
            if (result0 === null) {
              result0 = parse_otherFunc1();
              if (result0 === null) {
                pos0 = pos;
                result0 = parse_primitiveLiteral();
                if (result0 !== null) {
                  result0 = (function(offset, l) {
                                                    return {
                                                        type: 'literal',
                                                        value: l
                                                    };
                                                })(pos0, result0);
                }
                if (result0 === null) {
                  pos = pos0;
                }
                if (result0 === null) {
                  pos0 = pos;
                  result0 = parse_identifierPath();
                  if (result0 !== null) {
                    result0 = (function(offset, u) {
                                                      return {
                                                          type: 'property', name: u
                                                      };
                                                  })(pos0, result0);
                  }
                  if (result0 === null) {
                    pos = pos0;
                  }
                }
              }
            }
          }
          return result0;
        }
        
        function parse_op() {
          var result0;
          
          if (input.substr(pos, 2) === "eq") {
            result0 = "eq";
            pos += 2;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"eq\"");
            }
          }
          if (result0 === null) {
            if (input.substr(pos, 2) === "ne") {
              result0 = "ne";
              pos += 2;
            } else {
              result0 = null;
              if (reportFailures === 0) {
                matchFailed("\"ne\"");
              }
            }
            if (result0 === null) {
              if (input.substr(pos, 2) === "lt") {
                result0 = "lt";
                pos += 2;
              } else {
                result0 = null;
                if (reportFailures === 0) {
                  matchFailed("\"lt\"");
                }
              }
              if (result0 === null) {
                if (input.substr(pos, 2) === "le") {
                  result0 = "le";
                  pos += 2;
                } else {
                  result0 = null;
                  if (reportFailures === 0) {
                    matchFailed("\"le\"");
                  }
                }
                if (result0 === null) {
                  if (input.substr(pos, 2) === "gt") {
                    result0 = "gt";
                    pos += 2;
                  } else {
                    result0 = null;
                    if (reportFailures === 0) {
                      matchFailed("\"gt\"");
                    }
                  }
                  if (result0 === null) {
                    if (input.substr(pos, 2) === "ge") {
                      result0 = "ge";
                      pos += 2;
                    } else {
                      result0 = null;
                      if (reportFailures === 0) {
                        matchFailed("\"ge\"");
                      }
                    }
                    if (result0 === null) {
                      if (input.substr(pos, 3) === "add") {
                        result0 = "add";
                        pos += 3;
                      } else {
                        result0 = null;
                        if (reportFailures === 0) {
                          matchFailed("\"add\"");
                        }
                      }
                      if (result0 === null) {
                        if (input.substr(pos, 3) === "sub") {
                          result0 = "sub";
                          pos += 3;
                        } else {
                          result0 = null;
                          if (reportFailures === 0) {
                            matchFailed("\"sub\"");
                          }
                        }
                        if (result0 === null) {
                          if (input.substr(pos, 3) === "mul") {
                            result0 = "mul";
                            pos += 3;
                          } else {
                            result0 = null;
                            if (reportFailures === 0) {
                              matchFailed("\"mul\"");
                            }
                          }
                          if (result0 === null) {
                            if (input.substr(pos, 3) === "div") {
                              result0 = "div";
                              pos += 3;
                            } else {
                              result0 = null;
                              if (reportFailures === 0) {
                                matchFailed("\"div\"");
                              }
                            }
                            if (result0 === null) {
                              if (input.substr(pos, 3) === "mod") {
                                result0 = "mod";
                                pos += 3;
                              } else {
                                result0 = null;
                                if (reportFailures === 0) {
                                  matchFailed("\"mod\"");
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
          return result0;
        }
        
        function parse_unsupported() {
          var result0, result1, result2;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          if (input.charCodeAt(pos) === 36) {
            result0 = "$";
            pos++;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"$\"");
            }
          }
          if (result0 !== null) {
            result1 = [];
            if (input.length > pos) {
              result2 = input.charAt(pos);
              pos++;
            } else {
              result2 = null;
              if (reportFailures === 0) {
                matchFailed("any character");
              }
            }
            while (result2 !== null) {
              result1.push(result2);
              if (input.length > pos) {
                result2 = input.charAt(pos);
                pos++;
              } else {
                result2 = null;
                if (reportFailures === 0) {
                  matchFailed("any character");
                }
              }
            }
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, er) { return { error: "unsupported method: " + er }; })(pos0, result0[1]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          return result0;
        }
        
        function parse_expList() {
          var result0, result1, result2;
          var pos0, pos1;
          
          pos0 = pos;
          pos1 = pos;
          result0 = parse_exp();
          if (result0 !== null) {
            if (input.charCodeAt(pos) === 38) {
              result1 = "&";
              pos++;
            } else {
              result1 = null;
              if (reportFailures === 0) {
                matchFailed("\"&\"");
              }
            }
            if (result1 !== null) {
              result2 = parse_expList();
              if (result2 !== null) {
                result0 = [result0, result1, result2];
              } else {
                result0 = null;
                pos = pos1;
              }
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, e, el) { return [e].concat(el); })(pos0, result0[0], result0[2]);
          }
          if (result0 === null) {
            pos = pos0;
          }
          if (result0 === null) {
            pos0 = pos;
            result0 = parse_exp();
            if (result0 !== null) {
              result0 = (function(offset, e) { return [e]; })(pos0, result0);
            }
            if (result0 === null) {
              pos = pos0;
            }
          }
          return result0;
        }
        
        function parse_exp() {
          var result0;
          
          result0 = parse_expand();
          if (result0 === null) {
            result0 = parse_filter();
            if (result0 === null) {
              result0 = parse_orderby();
              if (result0 === null) {
                result0 = parse_skip();
                if (result0 === null) {
                  result0 = parse_top();
                  if (result0 === null) {
                    result0 = parse_format();
                    if (result0 === null) {
                      result0 = parse_inlinecount();
                      if (result0 === null) {
                        result0 = parse_select();
                        if (result0 === null) {
                          result0 = parse_callback();
                          if (result0 === null) {
                            result0 = parse_unsupported();
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
          return result0;
        }
        
        function parse_query() {
          var result0;
          var pos0;
          
          pos0 = pos;
          result0 = parse_expList();
          if (result0 !== null) {
            result0 = (function(offset, list) {
                                              //turn the array into an object like:
                                              // { $top: 5, $skip: 10 }
                                              var result = {};
                                              list = list || [];
                                              for(var i in list){
          
                                                  if (list[i] !== "") {
                                                      var paramName = Object.keys(list[i])[0]; //ie: $top
                                                      result[paramName] = list[i][paramName];
                                                  }
                                              }
                                              return result;
                                          })(pos0, result0);
          }
          if (result0 === null) {
            pos = pos0;
          }
          return result0;
        }
        
        
        function cleanupExpected(expected) {
          expected.sort();
          
          var lastExpected = null;
          var cleanExpected = [];
          for (var i = 0; i < expected.length; i++) {
            if (expected[i] !== lastExpected) {
              cleanExpected.push(expected[i]);
              lastExpected = expected[i];
            }
          }
          return cleanExpected;
        }
        
        function computeErrorPosition() {
          /*
           * The first idea was to use |String.split| to break the input up to the
           * error position along newlines and derive the line and column from
           * there. However IE's |split| implementation is so broken that it was
           * enough to prevent it.
           */
          
          var line = 1;
          var column = 1;
          var seenCR = false;
          
          for (var i = 0; i < Math.max(pos, rightmostFailuresPos); i++) {
            var ch = input.charAt(i);
            if (ch === "\n") {
              if (!seenCR) { line++; }
              column = 1;
              seenCR = false;
            } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") {
              line++;
              column = 1;
              seenCR = true;
            } else {
              column++;
              seenCR = false;
            }
          }
          
          return { line: line, column: column };
        }
        
        
          function filterExprHelper(left, right){
            if (right) {
                return {
                    type: right.type,
                    left: left,
                    right: right.value
                }
            } else {
                return left;
            }
          }
        
        
        var result = parseFunctions[startRule]();
        
        /*
         * The parser is now in one of the following three states:
         *
         * 1. The parser successfully parsed the whole input.
         *
         *    - |result !== null|
         *    - |pos === input.length|
         *    - |rightmostFailuresExpected| may or may not contain something
         *
         * 2. The parser successfully parsed only a part of the input.
         *
         *    - |result !== null|
         *    - |pos < input.length|
         *    - |rightmostFailuresExpected| may or may not contain something
         *
         * 3. The parser did not successfully parse any part of the input.
         *
         *   - |result === null|
         *   - |pos === 0|
         *   - |rightmostFailuresExpected| contains at least one failure
         *
         * All code following this comment (including called functions) must
         * handle these states.
         */
        if (result === null || pos !== input.length) {
          var offset = Math.max(pos, rightmostFailuresPos);
          var found = offset < input.length ? input.charAt(offset) : null;
          var errorPosition = computeErrorPosition();
          
          throw new this.SyntaxError(
            cleanupExpected(rightmostFailuresExpected),
            found,
            offset,
            errorPosition.line,
            errorPosition.column
          );
        }
        
        return result;
      },
      
      /* Returns the parser source code. */
      toSource: function() { return this._source; }
    };
    
    /* Thrown when a parser encounters a syntax error. */
    
    result.SyntaxError = function(expected, found, offset, line, column) {
      function buildMessage(expected, found) {
        var expectedHumanized, foundHumanized;
        
        switch (expected.length) {
          case 0:
            expectedHumanized = "end of input";
            break;
          case 1:
            expectedHumanized = expected[0];
            break;
          default:
            expectedHumanized = expected.slice(0, expected.length - 1).join(", ")
              + " or "
              + expected[expected.length - 1];
        }
        
        foundHumanized = found ? quote(found) : "end of input";
        
        return "Expected " + expectedHumanized + " but " + foundHumanized + " found.";
      }
      
      this.name = "SyntaxError";
      this.expected = expected;
      this.found = found;
      this.message = buildMessage(expected, found);
      this.offset = offset;
      this.line = line;
      this.column = column;
    };
    
    result.SyntaxError.prototype = Error.prototype;
    
    return result;
  })();
  
  /* global ODataArrayFilter:true */
  /* global ODataParser */
  ODataArrayFilter = (function() {
    "use strict";
  
    /* istanbul ignore next */
    Object.toType = (function toType(global) {
      return function(obj) {
        if (obj === global) {
          return "global";
        }
        return ({}).toString.call(obj).match(/\s([a-z|A-Z]+)/)[1].toLowerCase();
      };
    })(this);
  
    function _arrayUniqueConcat(a1, a2) {
      for (var i = a2.length - 1; i >= 0; i--) {
        if (a1.indexOf(a2[i]) === -1) {
          a1.push(a2[i]);
        }
      }
      return a1;
    }
  
    function _parseFilter(filterString) {
      return ODataParser.parse(filterString);
    }
  
    function _simpleCompare(val1, val2, comparator) {
      if (Object.toType(val2) === 'date') {
        return comparator(new Date(val1).getTime(), val2.getTime());
      }
      return comparator(val1, val2);
    }
  
    var evaluators = {
      eqEvaluator: function(val1, val2) {
        if (val1 === null) {
          if (typeof val2 === 'string' && val2.toLowerCase() === 'null') {
            return true;
          } else {
            return false;
          }
        }
        return _simpleCompare(val1,val2,function(v1,v2){return v1===v2;});
      },
      neEvaluator: function(val1, val2) {
        return evaluators.eqEvaluator(val1, val2) === false;
      },
      ltEvaluator: function(val1, val2) {
        if (val1 === null){return false;}
        return _simpleCompare(val1,val2,function(v1,v2){return v1<v2;});
      },
      leEvaluator: function(val1, val2) {
        if (val1 === null){return false;}
        return _simpleCompare(val1,val2,function(v1,v2){return v1<=v2;});
      },
      gtEvaluator: function(val1, val2) {
        if (val1 === null){return false;}
        return _simpleCompare(val1,val2,function(v1,v2){return v1>v2;});
      },
      geEvaluator: function(val1, val2) {
        if (val1 === null){return false;}
        return _simpleCompare(val1,val2,function(v1,v2){return v1>=v2;});
      }
    };
  
    function _getFieldName(filter) {
      if (filter.type) {
        if (filter.type === 'property') {
          return filter.name;
        } else if (filter.type === 'functioncall') {
          switch (filter.func) {
            case 'tolower':
            case 'toupper':
              return _getFieldName(filter.args[0]);
            case 'substringof':
              return _getFieldName(filter.args[1]);
          }
        }
      }
    }
  
    function _getFieldValue(filter, val) {
      if (val !== null && filter.type && filter.type === 'functioncall') {
        switch (filter.func) {
          case 'tolower':
            return val.toLowerCase();
          case 'toupper':
            return val.toUpperCase();
          case 'substringof':
            val = _getFieldValue(filter.args[1], val);
            return val.indexOf(filter.args[0].value) >= 0;
        }
      }
      return val;
    }
  
    function _getValueAtObjectPath(path, obj) {
      var val = obj;
      path.split('/').forEach(function(prop) {
        val = val[prop];
      });
      return val;
    }
  
    function _processLeftRight(filter, arr) {
      switch (filter.type) {
        case 'eq':
        case 'ne':
        case 'lt':
        case 'le':
        case 'gt':
        case 'ge':
          var prop = _getFieldName(filter.left);
          var value = (Array.isArray(filter.right.value)) ? filter.right.value[0]  : filter.right.value; //not sure what the array is all about yet
          return arr.filter(function(obj) {
            var propVal = _getValueAtObjectPath(prop, obj);
            propVal = _getFieldValue(filter.left, propVal);
            return evaluators[filter.type + 'Evaluator'](propVal, value);
          });
        case 'or':
          return _arrayUniqueConcat(_processLeftRight(filter.left, arr), _processLeftRight(filter.right, arr));
        case 'and':
          return _processLeftRight(filter.right, _processLeftRight(filter.left, arr));
      }
    }
  
    function _filterArray(filters, arr) {
      if (filters.$filter) {
        arr = _processLeftRight(filters.$filter, arr);
      }
      if (filters.$orderby) {
        //only expecting one so far
        var orderby = filters.$orderby[0];
        var orderField, orderDir;
        for (var prop in orderby) {
          orderField = prop;
          orderDir = orderby[prop];
        }
        arr.sort(function(a, b) {
          if (a[orderField] === undefined || a[orderField] === null ||
            b[orderField] === undefined || b[orderField] === null) {
            return -1;
          }
          if (orderDir === 'asc') {
            return a[orderField].toString().toLowerCase() <= b[orderField].toString().toLowerCase() ? -1 : 1;
          } else {
            return a[orderField].toString().toLowerCase() >= b[orderField].toString().toLowerCase() ? -1 : 1;
          }
        });
      }
      var totalCount = arr.length;
      var top = filters.$top || -1;
      var skip = filters.$skip || 0;
      if (top > -1) {
        arr = arr.slice(skip, top + skip);
      } else if (skip > 0) {
        arr = arr.slice(skip);
      }
      return {data:arr,totalCount:totalCount};
    }
  
    function ODataArrayFilter() {
      var self = this;
  
      self.parse = function(filterString) {
        return _parseFilter(filterString);
      };
  
      self.filter = function(filters, arr) {
        return _filterArray(filters, arr);
      };
  
      self.parseAndFilter = function(filterString, arr) {
        return self.filter(self.parse(filterString), arr);
      };
    }
  
    return new ODataArrayFilter();
  })();
  