module.exports = (function(){
  /* Generated by PEG.js 0.6.2 (http://pegjs.majda.cz/). */
  
  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 = {
        "Alpha": parse_Alpha,
        "Array": parse_Array,
        "ArrayBody": parse_ArrayBody,
        "ArrayEntry": parse_ArrayEntry,
        "Assignment": parse_Assignment,
        "AssignmentList": parse_AssignmentList,
        "Char": parse_Char,
        "CommentedArrayEntry": parse_CommentedArrayEntry,
        "CommentedAssignment": parse_CommentedAssignment,
        "CommentedIdentifier": parse_CommentedIdentifier,
        "CommentedValue": parse_CommentedValue,
        "DecimalValue": parse_DecimalValue,
        "DelimitedSection": parse_DelimitedSection,
        "DelimitedSectionBegin": parse_DelimitedSectionBegin,
        "DelimitedSectionEnd": parse_DelimitedSectionEnd,
        "Digit": parse_Digit,
        "DoubleQuote": parse_DoubleQuote,
        "EmptyArray": parse_EmptyArray,
        "EmptyBody": parse_EmptyBody,
        "EscapedQuote": parse_EscapedQuote,
        "Identifier": parse_Identifier,
        "InlineComment": parse_InlineComment,
        "InlineCommentClose": parse_InlineCommentClose,
        "InlineCommentOpen": parse_InlineCommentOpen,
        "IntegerValue": parse_IntegerValue,
        "LineTerminator": parse_LineTerminator,
        "LiteralChar": parse_LiteralChar,
        "LiteralString": parse_LiteralString,
        "NewLine": parse_NewLine,
        "NonLine": parse_NonLine,
        "NonQuote": parse_NonQuote,
        "NonTerminator": parse_NonTerminator,
        "NumberValue": parse_NumberValue,
        "Object": parse_Object,
        "OneLineString": parse_OneLineString,
        "Project": parse_Project,
        "QuotedBody": parse_QuotedBody,
        "QuotedString": parse_QuotedString,
        "SimpleArrayEntry": parse_SimpleArrayEntry,
        "SimpleAssignment": parse_SimpleAssignment,
        "SingleLineComment": parse_SingleLineComment,
        "StringValue": parse_StringValue,
        "Value": parse_Value,
        "_": parse__,
        "whitespace": parse_whitespace
      };
      
      if (startRule !== undefined) {
        if (parseFunctions[startRule] === undefined) {
          throw new Error("Invalid rule name: " + quote(startRule) + ".");
        }
      } else {
        startRule = "Project";
      }
      
      var pos = 0;
      var reportMatchFailures = true;
      var rightmostMatchFailuresPos = 0;
      var rightmostMatchFailuresExpected = [];
      var cache = {};
      
      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);
        
        if (charCode <= 0xFF) {
          var escapeChar = 'x';
          var length = 2;
        } else {
          var escapeChar = 'u';
          var length = 4;
        }
        
        return '\\' + escapeChar + padLeft(charCode.toString(16).toUpperCase(), '0', length);
      }
      
      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.
         */
        return '"' + s
          .replace(/\\/g, '\\\\')            // backslash
          .replace(/"/g, '\\"')              // closing quote character
          .replace(/\r/g, '\\r')             // carriage return
          .replace(/\n/g, '\\n')             // line feed
          .replace(/[\x80-\uFFFF]/g, escape) // non-ASCII characters
          + '"';
      }
      
      function matchFailed(failure) {
        if (pos < rightmostMatchFailuresPos) {
          return;
        }
        
        if (pos > rightmostMatchFailuresPos) {
          rightmostMatchFailuresPos = pos;
          rightmostMatchFailuresExpected = [];
        }
        
        rightmostMatchFailuresExpected.push(failure);
      }
      
      function parse_Project() {
        var cacheKey = 'Project@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos0 = pos;
        var savedPos1 = pos;
        var result10 = parse_SingleLineComment();
        var result3 = result10 !== null ? result10 : '';
        if (result3 !== null) {
          var result9 = parse_InlineComment();
          var result4 = result9 !== null ? result9 : '';
          if (result4 !== null) {
            var result5 = parse__();
            if (result5 !== null) {
              var result6 = parse_Object();
              if (result6 !== null) {
                var result7 = parse_NewLine();
                if (result7 !== null) {
                  var result8 = parse__();
                  if (result8 !== null) {
                    var result1 = [result3, result4, result5, result6, result7, result8];
                  } else {
                    var result1 = null;
                    pos = savedPos1;
                  }
                } else {
                  var result1 = null;
                  pos = savedPos1;
                }
              } else {
                var result1 = null;
                pos = savedPos1;
              }
            } else {
              var result1 = null;
              pos = savedPos1;
            }
          } else {
            var result1 = null;
            pos = savedPos1;
          }
        } else {
          var result1 = null;
          pos = savedPos1;
        }
        var result2 = result1 !== null
          ? (function(headComment, obj) {
                  var proj = Object.create(null)
                  proj.project = obj
          
                  if (headComment) {
                      proj.headComment = headComment
                  }
          
                  return proj;
              })(result1[0], result1[3])
          : null;
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result0 = null;
          pos = savedPos0;
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_Object() {
        var cacheKey = 'Object@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos0 = pos;
        var savedPos1 = pos;
        if (input.substr(pos, 1) === "{") {
          var result3 = "{";
          pos += 1;
        } else {
          var result3 = null;
          if (reportMatchFailures) {
            matchFailed("\"{\"");
          }
        }
        if (result3 !== null) {
          var result7 = parse_AssignmentList();
          if (result7 !== null) {
            var result4 = result7;
          } else {
            var result6 = parse_EmptyBody();
            if (result6 !== null) {
              var result4 = result6;
            } else {
              var result4 = null;;
            };
          }
          if (result4 !== null) {
            if (input.substr(pos, 1) === "}") {
              var result5 = "}";
              pos += 1;
            } else {
              var result5 = null;
              if (reportMatchFailures) {
                matchFailed("\"}\"");
              }
            }
            if (result5 !== null) {
              var result1 = [result3, result4, result5];
            } else {
              var result1 = null;
              pos = savedPos1;
            }
          } else {
            var result1 = null;
            pos = savedPos1;
          }
        } else {
          var result1 = null;
          pos = savedPos1;
        }
        var result2 = result1 !== null
          ? (function(obj) { return obj })(result1[1])
          : null;
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result0 = null;
          pos = savedPos0;
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_EmptyBody() {
        var cacheKey = 'EmptyBody@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos0 = pos;
        var result1 = parse__();
        var result2 = result1 !== null
          ? (function() { return Object.create(null) })()
          : null;
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result0 = null;
          pos = savedPos0;
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_AssignmentList() {
        var cacheKey = 'AssignmentList@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos2 = pos;
        var savedPos3 = pos;
        var result12 = parse__();
        if (result12 !== null) {
          var result13 = parse_Assignment();
          if (result13 !== null) {
            var result14 = parse__();
            if (result14 !== null) {
              var result15 = [];
              var result17 = parse_AssignmentList();
              while (result17 !== null) {
                result15.push(result17);
                var result17 = parse_AssignmentList();
              }
              if (result15 !== null) {
                var result16 = parse__();
                if (result16 !== null) {
                  var result10 = [result12, result13, result14, result15, result16];
                } else {
                  var result10 = null;
                  pos = savedPos3;
                }
              } else {
                var result10 = null;
                pos = savedPos3;
              }
            } else {
              var result10 = null;
              pos = savedPos3;
            }
          } else {
            var result10 = null;
            pos = savedPos3;
          }
        } else {
          var result10 = null;
          pos = savedPos3;
        }
        var result11 = result10 !== null
          ? (function(head, tail) { 
                if (tail) return merge(head,tail)
                else return head
              })(result10[1], result10[3])
          : null;
        if (result11 !== null) {
          var result9 = result11;
        } else {
          var result9 = null;
          pos = savedPos2;
        }
        if (result9 !== null) {
          var result0 = result9;
        } else {
          var savedPos0 = pos;
          var savedPos1 = pos;
          var result4 = parse__();
          if (result4 !== null) {
            var result5 = parse_DelimitedSection();
            if (result5 !== null) {
              var result6 = parse__();
              if (result6 !== null) {
                var result7 = [];
                var result8 = parse_AssignmentList();
                while (result8 !== null) {
                  result7.push(result8);
                  var result8 = parse_AssignmentList();
                }
                if (result7 !== null) {
                  var result2 = [result4, result5, result6, result7];
                } else {
                  var result2 = null;
                  pos = savedPos1;
                }
              } else {
                var result2 = null;
                pos = savedPos1;
              }
            } else {
              var result2 = null;
              pos = savedPos1;
            }
          } else {
            var result2 = null;
            pos = savedPos1;
          }
          var result3 = result2 !== null
            ? (function(head, tail) {
                  if (tail) return merge(head,tail)
                  else return head
                })(result2[1], result2[3])
            : null;
          if (result3 !== null) {
            var result1 = result3;
          } else {
            var result1 = null;
            pos = savedPos0;
          }
          if (result1 !== null) {
            var result0 = result1;
          } else {
            var result0 = null;;
          };
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_Assignment() {
        var cacheKey = 'Assignment@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var result2 = parse_SimpleAssignment();
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result1 = parse_CommentedAssignment();
          if (result1 !== null) {
            var result0 = result1;
          } else {
            var result0 = null;;
          };
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_SimpleAssignment() {
        var cacheKey = 'SimpleAssignment@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos0 = pos;
        var savedPos1 = pos;
        var result3 = parse_Identifier();
        if (result3 !== null) {
          var result4 = parse__();
          if (result4 !== null) {
            if (input.substr(pos, 1) === "=") {
              var result5 = "=";
              pos += 1;
            } else {
              var result5 = null;
              if (reportMatchFailures) {
                matchFailed("\"=\"");
              }
            }
            if (result5 !== null) {
              var result6 = parse__();
              if (result6 !== null) {
                var result7 = parse_Value();
                if (result7 !== null) {
                  if (input.substr(pos, 1) === ";") {
                    var result8 = ";";
                    pos += 1;
                  } else {
                    var result8 = null;
                    if (reportMatchFailures) {
                      matchFailed("\";\"");
                    }
                  }
                  if (result8 !== null) {
                    var result1 = [result3, result4, result5, result6, result7, result8];
                  } else {
                    var result1 = null;
                    pos = savedPos1;
                  }
                } else {
                  var result1 = null;
                  pos = savedPos1;
                }
              } else {
                var result1 = null;
                pos = savedPos1;
              }
            } else {
              var result1 = null;
              pos = savedPos1;
            }
          } else {
            var result1 = null;
            pos = savedPos1;
          }
        } else {
          var result1 = null;
          pos = savedPos1;
        }
        var result2 = result1 !== null
          ? (function(id, val) { 
                var result = Object.create(null);
                result[id] = val
                return result
              })(result1[0], result1[4])
          : null;
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result0 = null;
          pos = savedPos0;
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_CommentedAssignment() {
        var cacheKey = 'CommentedAssignment@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos2 = pos;
        var savedPos3 = pos;
        var result13 = parse_CommentedIdentifier();
        if (result13 !== null) {
          var result14 = parse__();
          if (result14 !== null) {
            if (input.substr(pos, 1) === "=") {
              var result15 = "=";
              pos += 1;
            } else {
              var result15 = null;
              if (reportMatchFailures) {
                matchFailed("\"=\"");
              }
            }
            if (result15 !== null) {
              var result16 = parse__();
              if (result16 !== null) {
                var result17 = parse_Value();
                if (result17 !== null) {
                  if (input.substr(pos, 1) === ";") {
                    var result18 = ";";
                    pos += 1;
                  } else {
                    var result18 = null;
                    if (reportMatchFailures) {
                      matchFailed("\";\"");
                    }
                  }
                  if (result18 !== null) {
                    var result11 = [result13, result14, result15, result16, result17, result18];
                  } else {
                    var result11 = null;
                    pos = savedPos3;
                  }
                } else {
                  var result11 = null;
                  pos = savedPos3;
                }
              } else {
                var result11 = null;
                pos = savedPos3;
              }
            } else {
              var result11 = null;
              pos = savedPos3;
            }
          } else {
            var result11 = null;
            pos = savedPos3;
          }
        } else {
          var result11 = null;
          pos = savedPos3;
        }
        var result12 = result11 !== null
          ? (function(commentedId, val) {
                  var result = Object.create(null),
                      commentKey = commentedId.id + '_comment';
          
                  result[commentedId.id] = val;
                  result[commentKey] = commentedId[commentKey];
                  return result;
          
              })(result11[0], result11[4])
          : null;
        if (result12 !== null) {
          var result10 = result12;
        } else {
          var result10 = null;
          pos = savedPos2;
        }
        if (result10 !== null) {
          var result0 = result10;
        } else {
          var savedPos0 = pos;
          var savedPos1 = pos;
          var result4 = parse_Identifier();
          if (result4 !== null) {
            var result5 = parse__();
            if (result5 !== null) {
              if (input.substr(pos, 1) === "=") {
                var result6 = "=";
                pos += 1;
              } else {
                var result6 = null;
                if (reportMatchFailures) {
                  matchFailed("\"=\"");
                }
              }
              if (result6 !== null) {
                var result7 = parse__();
                if (result7 !== null) {
                  var result8 = parse_CommentedValue();
                  if (result8 !== null) {
                    if (input.substr(pos, 1) === ";") {
                      var result9 = ";";
                      pos += 1;
                    } else {
                      var result9 = null;
                      if (reportMatchFailures) {
                        matchFailed("\";\"");
                      }
                    }
                    if (result9 !== null) {
                      var result2 = [result4, result5, result6, result7, result8, result9];
                    } else {
                      var result2 = null;
                      pos = savedPos1;
                    }
                  } else {
                    var result2 = null;
                    pos = savedPos1;
                  }
                } else {
                  var result2 = null;
                  pos = savedPos1;
                }
              } else {
                var result2 = null;
                pos = savedPos1;
              }
            } else {
              var result2 = null;
              pos = savedPos1;
            }
          } else {
            var result2 = null;
            pos = savedPos1;
          }
          var result3 = result2 !== null
            ? (function(id, commentedVal) {
                    var result = Object.create(null);
                    result[id] = commentedVal.value;
                    result[id + "_comment"] = commentedVal.comment;
                    return result;
                })(result2[0], result2[4])
            : null;
          if (result3 !== null) {
            var result1 = result3;
          } else {
            var result1 = null;
            pos = savedPos0;
          }
          if (result1 !== null) {
            var result0 = result1;
          } else {
            var result0 = null;;
          };
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_CommentedIdentifier() {
        var cacheKey = 'CommentedIdentifier@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos0 = pos;
        var savedPos1 = pos;
        var result3 = parse_Identifier();
        if (result3 !== null) {
          var result4 = parse__();
          if (result4 !== null) {
            var result5 = parse_InlineComment();
            if (result5 !== null) {
              var result1 = [result3, result4, result5];
            } else {
              var result1 = null;
              pos = savedPos1;
            }
          } else {
            var result1 = null;
            pos = savedPos1;
          }
        } else {
          var result1 = null;
          pos = savedPos1;
        }
        var result2 = result1 !== null
          ? (function(id, comment) {
                  var result = Object.create(null);
                  result.id = id;
                  result[id + "_comment"] = comment.trim();
                  return result
              })(result1[0], result1[2])
          : null;
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result0 = null;
          pos = savedPos0;
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_CommentedValue() {
        var cacheKey = 'CommentedValue@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos0 = pos;
        var savedPos1 = pos;
        var result3 = parse_Value();
        if (result3 !== null) {
          var result4 = parse__();
          if (result4 !== null) {
            var result5 = parse_InlineComment();
            if (result5 !== null) {
              var result1 = [result3, result4, result5];
            } else {
              var result1 = null;
              pos = savedPos1;
            }
          } else {
            var result1 = null;
            pos = savedPos1;
          }
        } else {
          var result1 = null;
          pos = savedPos1;
        }
        var result2 = result1 !== null
          ? (function(literal, comment) {
                  var result = Object.create(null)
                  result.comment = comment.trim();
                  result.value = literal.trim();
                  return result;
              })(result1[0], result1[2])
          : null;
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result0 = null;
          pos = savedPos0;
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_InlineComment() {
        var cacheKey = 'InlineComment@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos0 = pos;
        var savedPos1 = pos;
        var result3 = parse_InlineCommentOpen();
        if (result3 !== null) {
          if (input.substr(pos).match(/^[^*]/) !== null) {
            var result6 = input.charAt(pos);
            pos++;
          } else {
            var result6 = null;
            if (reportMatchFailures) {
              matchFailed("[^*]");
            }
          }
          if (result6 !== null) {
            var result4 = [];
            while (result6 !== null) {
              result4.push(result6);
              if (input.substr(pos).match(/^[^*]/) !== null) {
                var result6 = input.charAt(pos);
                pos++;
              } else {
                var result6 = null;
                if (reportMatchFailures) {
                  matchFailed("[^*]");
                }
              }
            }
          } else {
            var result4 = null;
          }
          if (result4 !== null) {
            var result5 = parse_InlineCommentClose();
            if (result5 !== null) {
              var result1 = [result3, result4, result5];
            } else {
              var result1 = null;
              pos = savedPos1;
            }
          } else {
            var result1 = null;
            pos = savedPos1;
          }
        } else {
          var result1 = null;
          pos = savedPos1;
        }
        var result2 = result1 !== null
          ? (function(body) { return body.join('') })(result1[1])
          : null;
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result0 = null;
          pos = savedPos0;
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_InlineCommentOpen() {
        var cacheKey = 'InlineCommentOpen@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        if (input.substr(pos, 2) === "/*") {
          var result0 = "/*";
          pos += 2;
        } else {
          var result0 = null;
          if (reportMatchFailures) {
            matchFailed("\"/*\"");
          }
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_InlineCommentClose() {
        var cacheKey = 'InlineCommentClose@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        if (input.substr(pos, 2) === "*/") {
          var result0 = "*/";
          pos += 2;
        } else {
          var result0 = null;
          if (reportMatchFailures) {
            matchFailed("\"*/\"");
          }
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_DelimitedSection() {
        var cacheKey = 'DelimitedSection@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos0 = pos;
        var savedPos1 = pos;
        var result3 = parse_DelimitedSectionBegin();
        if (result3 !== null) {
          var result4 = parse__();
          if (result4 !== null) {
            var result9 = parse_AssignmentList();
            if (result9 !== null) {
              var result5 = result9;
            } else {
              var result8 = parse_EmptyBody();
              if (result8 !== null) {
                var result5 = result8;
              } else {
                var result5 = null;;
              };
            }
            if (result5 !== null) {
              var result6 = parse__();
              if (result6 !== null) {
                var result7 = parse_DelimitedSectionEnd();
                if (result7 !== null) {
                  var result1 = [result3, result4, result5, result6, result7];
                } else {
                  var result1 = null;
                  pos = savedPos1;
                }
              } else {
                var result1 = null;
                pos = savedPos1;
              }
            } else {
              var result1 = null;
              pos = savedPos1;
            }
          } else {
            var result1 = null;
            pos = savedPos1;
          }
        } else {
          var result1 = null;
          pos = savedPos1;
        }
        var result2 = result1 !== null
          ? (function(begin, fields) {
                  var section = Object.create(null);
                  section[begin.name] = fields
          
                  return section
              })(result1[0], result1[2])
          : null;
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result0 = null;
          pos = savedPos0;
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_DelimitedSectionBegin() {
        var cacheKey = 'DelimitedSectionBegin@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos0 = pos;
        var savedPos1 = pos;
        if (input.substr(pos, 9) === "/* Begin ") {
          var result3 = "/* Begin ";
          pos += 9;
        } else {
          var result3 = null;
          if (reportMatchFailures) {
            matchFailed("\"/* Begin \"");
          }
        }
        if (result3 !== null) {
          var result4 = parse_Identifier();
          if (result4 !== null) {
            if (input.substr(pos, 11) === " section */") {
              var result5 = " section */";
              pos += 11;
            } else {
              var result5 = null;
              if (reportMatchFailures) {
                matchFailed("\" section */\"");
              }
            }
            if (result5 !== null) {
              var result6 = parse_NewLine();
              if (result6 !== null) {
                var result1 = [result3, result4, result5, result6];
              } else {
                var result1 = null;
                pos = savedPos1;
              }
            } else {
              var result1 = null;
              pos = savedPos1;
            }
          } else {
            var result1 = null;
            pos = savedPos1;
          }
        } else {
          var result1 = null;
          pos = savedPos1;
        }
        var result2 = result1 !== null
          ? (function(sectionName) { return { name: sectionName } })(result1[1])
          : null;
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result0 = null;
          pos = savedPos0;
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_DelimitedSectionEnd() {
        var cacheKey = 'DelimitedSectionEnd@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos0 = pos;
        var savedPos1 = pos;
        if (input.substr(pos, 7) === "/* End ") {
          var result3 = "/* End ";
          pos += 7;
        } else {
          var result3 = null;
          if (reportMatchFailures) {
            matchFailed("\"/* End \"");
          }
        }
        if (result3 !== null) {
          var result4 = parse_Identifier();
          if (result4 !== null) {
            if (input.substr(pos, 11) === " section */") {
              var result5 = " section */";
              pos += 11;
            } else {
              var result5 = null;
              if (reportMatchFailures) {
                matchFailed("\" section */\"");
              }
            }
            if (result5 !== null) {
              var result6 = parse_NewLine();
              if (result6 !== null) {
                var result1 = [result3, result4, result5, result6];
              } else {
                var result1 = null;
                pos = savedPos1;
              }
            } else {
              var result1 = null;
              pos = savedPos1;
            }
          } else {
            var result1 = null;
            pos = savedPos1;
          }
        } else {
          var result1 = null;
          pos = savedPos1;
        }
        var result2 = result1 !== null
          ? (function(sectionName) { return { name: sectionName } })(result1[1])
          : null;
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result0 = null;
          pos = savedPos0;
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_Array() {
        var cacheKey = 'Array@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos0 = pos;
        var savedPos1 = pos;
        if (input.substr(pos, 1) === "(") {
          var result3 = "(";
          pos += 1;
        } else {
          var result3 = null;
          if (reportMatchFailures) {
            matchFailed("\"(\"");
          }
        }
        if (result3 !== null) {
          var result7 = parse_ArrayBody();
          if (result7 !== null) {
            var result4 = result7;
          } else {
            var result6 = parse_EmptyArray();
            if (result6 !== null) {
              var result4 = result6;
            } else {
              var result4 = null;;
            };
          }
          if (result4 !== null) {
            if (input.substr(pos, 1) === ")") {
              var result5 = ")";
              pos += 1;
            } else {
              var result5 = null;
              if (reportMatchFailures) {
                matchFailed("\")\"");
              }
            }
            if (result5 !== null) {
              var result1 = [result3, result4, result5];
            } else {
              var result1 = null;
              pos = savedPos1;
            }
          } else {
            var result1 = null;
            pos = savedPos1;
          }
        } else {
          var result1 = null;
          pos = savedPos1;
        }
        var result2 = result1 !== null
          ? (function(arr) { return arr })(result1[1])
          : null;
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result0 = null;
          pos = savedPos0;
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_EmptyArray() {
        var cacheKey = 'EmptyArray@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos0 = pos;
        var result1 = parse__();
        var result2 = result1 !== null
          ? (function() { return [] })()
          : null;
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result0 = null;
          pos = savedPos0;
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_ArrayBody() {
        var cacheKey = 'ArrayBody@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos0 = pos;
        var savedPos1 = pos;
        var result3 = parse__();
        if (result3 !== null) {
          var result4 = parse_ArrayEntry();
          if (result4 !== null) {
            var result5 = parse__();
            if (result5 !== null) {
              var result8 = parse_ArrayBody();
              var result6 = result8 !== null ? result8 : '';
              if (result6 !== null) {
                var result7 = parse__();
                if (result7 !== null) {
                  var result1 = [result3, result4, result5, result6, result7];
                } else {
                  var result1 = null;
                  pos = savedPos1;
                }
              } else {
                var result1 = null;
                pos = savedPos1;
              }
            } else {
              var result1 = null;
              pos = savedPos1;
            }
          } else {
            var result1 = null;
            pos = savedPos1;
          }
        } else {
          var result1 = null;
          pos = savedPos1;
        }
        var result2 = result1 !== null
          ? (function(head, tail) {
                  if (tail) {
                      tail.unshift(head);
                      return tail;
                  } else {
                      return [head];
                  }
              })(result1[1], result1[3])
          : null;
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result0 = null;
          pos = savedPos0;
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_ArrayEntry() {
        var cacheKey = 'ArrayEntry@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var result2 = parse_SimpleArrayEntry();
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result1 = parse_CommentedArrayEntry();
          if (result1 !== null) {
            var result0 = result1;
          } else {
            var result0 = null;;
          };
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_SimpleArrayEntry() {
        var cacheKey = 'SimpleArrayEntry@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos0 = pos;
        var savedPos1 = pos;
        var result3 = parse_Value();
        if (result3 !== null) {
          if (input.substr(pos, 1) === ",") {
            var result4 = ",";
            pos += 1;
          } else {
            var result4 = null;
            if (reportMatchFailures) {
              matchFailed("\",\"");
            }
          }
          if (result4 !== null) {
            var result1 = [result3, result4];
          } else {
            var result1 = null;
            pos = savedPos1;
          }
        } else {
          var result1 = null;
          pos = savedPos1;
        }
        var result2 = result1 !== null
          ? (function(val) { return val })(result1[0])
          : null;
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result0 = null;
          pos = savedPos0;
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_CommentedArrayEntry() {
        var cacheKey = 'CommentedArrayEntry@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos0 = pos;
        var savedPos1 = pos;
        var result3 = parse_Value();
        if (result3 !== null) {
          var result4 = parse__();
          if (result4 !== null) {
            var result5 = parse_InlineComment();
            if (result5 !== null) {
              if (input.substr(pos, 1) === ",") {
                var result6 = ",";
                pos += 1;
              } else {
                var result6 = null;
                if (reportMatchFailures) {
                  matchFailed("\",\"");
                }
              }
              if (result6 !== null) {
                var result1 = [result3, result4, result5, result6];
              } else {
                var result1 = null;
                pos = savedPos1;
              }
            } else {
              var result1 = null;
              pos = savedPos1;
            }
          } else {
            var result1 = null;
            pos = savedPos1;
          }
        } else {
          var result1 = null;
          pos = savedPos1;
        }
        var result2 = result1 !== null
          ? (function(val, comment) {
                  var result = Object.create(null);
                  result.value = val.trim();
                  result.comment = comment.trim();
                  return result;
              })(result1[0], result1[2])
          : null;
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result0 = null;
          pos = savedPos0;
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_Identifier() {
        var cacheKey = 'Identifier@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos0 = pos;
        if (input.substr(pos).match(/^[A-Za-z0-9_.]/) !== null) {
          var result5 = input.charAt(pos);
          pos++;
        } else {
          var result5 = null;
          if (reportMatchFailures) {
            matchFailed("[A-Za-z0-9_.]");
          }
        }
        if (result5 !== null) {
          var result3 = [];
          while (result5 !== null) {
            result3.push(result5);
            if (input.substr(pos).match(/^[A-Za-z0-9_.]/) !== null) {
              var result5 = input.charAt(pos);
              pos++;
            } else {
              var result5 = null;
              if (reportMatchFailures) {
                matchFailed("[A-Za-z0-9_.]");
              }
            }
          }
        } else {
          var result3 = null;
        }
        var result4 = result3 !== null
          ? (function(id) { return id.join('') })(result3)
          : null;
        if (result4 !== null) {
          var result2 = result4;
        } else {
          var result2 = null;
          pos = savedPos0;
        }
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result1 = parse_QuotedString();
          if (result1 !== null) {
            var result0 = result1;
          } else {
            var result0 = null;;
          };
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_Value() {
        var cacheKey = 'Value@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var result4 = parse_Object();
        if (result4 !== null) {
          var result0 = result4;
        } else {
          var result3 = parse_Array();
          if (result3 !== null) {
            var result0 = result3;
          } else {
            var result2 = parse_NumberValue();
            if (result2 !== null) {
              var result0 = result2;
            } else {
              var result1 = parse_StringValue();
              if (result1 !== null) {
                var result0 = result1;
              } else {
                var result0 = null;;
              };
            };
          };
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_NumberValue() {
        var cacheKey = 'NumberValue@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var result2 = parse_DecimalValue();
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result1 = parse_IntegerValue();
          if (result1 !== null) {
            var result0 = result1;
          } else {
            var result0 = null;;
          };
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_DecimalValue() {
        var cacheKey = 'DecimalValue@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos0 = pos;
        var savedPos1 = pos;
        var result3 = parse_IntegerValue();
        if (result3 !== null) {
          if (input.substr(pos, 1) === ".") {
            var result4 = ".";
            pos += 1;
          } else {
            var result4 = null;
            if (reportMatchFailures) {
              matchFailed("\".\"");
            }
          }
          if (result4 !== null) {
            var result5 = parse_IntegerValue();
            if (result5 !== null) {
              var result1 = [result3, result4, result5];
            } else {
              var result1 = null;
              pos = savedPos1;
            }
          } else {
            var result1 = null;
            pos = savedPos1;
          }
        } else {
          var result1 = null;
          pos = savedPos1;
        }
        var result2 = result1 !== null
          ? (function(decimal) { 
                  // store decimals as strings
                  // as JS doesn't differentiate bw strings and numbers
                  return decimal.join('')
              })(result1)
          : null;
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result0 = null;
          pos = savedPos0;
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_IntegerValue() {
        var cacheKey = 'IntegerValue@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos0 = pos;
        var savedPos1 = pos;
        var savedPos3 = pos;
        var savedReportMatchFailuresVar1 = reportMatchFailures;
        reportMatchFailures = false;
        var result8 = parse_Alpha();
        reportMatchFailures = savedReportMatchFailuresVar1;
        if (result8 === null) {
          var result3 = '';
        } else {
          var result3 = null;
          pos = savedPos3;
        }
        if (result3 !== null) {
          var result7 = parse_Digit();
          if (result7 !== null) {
            var result4 = [];
            while (result7 !== null) {
              result4.push(result7);
              var result7 = parse_Digit();
            }
          } else {
            var result4 = null;
          }
          if (result4 !== null) {
            var savedPos2 = pos;
            var savedReportMatchFailuresVar0 = reportMatchFailures;
            reportMatchFailures = false;
            var result6 = parse_NonTerminator();
            reportMatchFailures = savedReportMatchFailuresVar0;
            if (result6 === null) {
              var result5 = '';
            } else {
              var result5 = null;
              pos = savedPos2;
            }
            if (result5 !== null) {
              var result1 = [result3, result4, result5];
            } else {
              var result1 = null;
              pos = savedPos1;
            }
          } else {
            var result1 = null;
            pos = savedPos1;
          }
        } else {
          var result1 = null;
          pos = savedPos1;
        }
        var result2 = result1 !== null
          ? (function(number) { return parseInt(number.join(''), 10) })(result1[1])
          : null;
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result0 = null;
          pos = savedPos0;
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_StringValue() {
        var cacheKey = 'StringValue@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var result2 = parse_QuotedString();
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result1 = parse_LiteralString();
          if (result1 !== null) {
            var result0 = result1;
          } else {
            var result0 = null;;
          };
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_QuotedString() {
        var cacheKey = 'QuotedString@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos0 = pos;
        var savedPos1 = pos;
        var result3 = parse_DoubleQuote();
        if (result3 !== null) {
          var result4 = parse_QuotedBody();
          if (result4 !== null) {
            var result5 = parse_DoubleQuote();
            if (result5 !== null) {
              var result1 = [result3, result4, result5];
            } else {
              var result1 = null;
              pos = savedPos1;
            }
          } else {
            var result1 = null;
            pos = savedPos1;
          }
        } else {
          var result1 = null;
          pos = savedPos1;
        }
        var result2 = result1 !== null
          ? (function(str) { return '"' + str + '"' })(result1[1])
          : null;
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result0 = null;
          pos = savedPos0;
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_QuotedBody() {
        var cacheKey = 'QuotedBody@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos0 = pos;
        var result3 = parse_NonQuote();
        if (result3 !== null) {
          var result1 = [];
          while (result3 !== null) {
            result1.push(result3);
            var result3 = parse_NonQuote();
          }
        } else {
          var result1 = null;
        }
        var result2 = result1 !== null
          ? (function(str) { return str.join('') })(result1)
          : null;
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result0 = null;
          pos = savedPos0;
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_NonQuote() {
        var cacheKey = 'NonQuote@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var result7 = parse_EscapedQuote();
        if (result7 !== null) {
          var result0 = result7;
        } else {
          var savedPos0 = pos;
          var savedPos1 = pos;
          var savedPos2 = pos;
          var savedReportMatchFailuresVar0 = reportMatchFailures;
          reportMatchFailures = false;
          var result6 = parse_DoubleQuote();
          reportMatchFailures = savedReportMatchFailuresVar0;
          if (result6 === null) {
            var result4 = '';
          } else {
            var result4 = null;
            pos = savedPos2;
          }
          if (result4 !== null) {
            if (input.length > pos) {
              var result5 = input.charAt(pos);
              pos++;
            } else {
              var result5 = null;
              if (reportMatchFailures) {
                matchFailed('any character');
              }
            }
            if (result5 !== null) {
              var result2 = [result4, result5];
            } else {
              var result2 = null;
              pos = savedPos1;
            }
          } else {
            var result2 = null;
            pos = savedPos1;
          }
          var result3 = result2 !== null
            ? (function(char) { return char })(result2[1])
            : null;
          if (result3 !== null) {
            var result1 = result3;
          } else {
            var result1 = null;
            pos = savedPos0;
          }
          if (result1 !== null) {
            var result0 = result1;
          } else {
            var result0 = null;;
          };
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_EscapedQuote() {
        var cacheKey = 'EscapedQuote@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos0 = pos;
        var savedPos1 = pos;
        if (input.substr(pos, 1) === "\\") {
          var result3 = "\\";
          pos += 1;
        } else {
          var result3 = null;
          if (reportMatchFailures) {
            matchFailed("\"\\\\\"");
          }
        }
        if (result3 !== null) {
          var result4 = parse_DoubleQuote();
          if (result4 !== null) {
            var result1 = [result3, result4];
          } else {
            var result1 = null;
            pos = savedPos1;
          }
        } else {
          var result1 = null;
          pos = savedPos1;
        }
        var result2 = result1 !== null
          ? (function() { return '\\"' })()
          : null;
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result0 = null;
          pos = savedPos0;
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_LiteralString() {
        var cacheKey = 'LiteralString@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos0 = pos;
        var result3 = parse_LiteralChar();
        if (result3 !== null) {
          var result1 = [];
          while (result3 !== null) {
            result1.push(result3);
            var result3 = parse_LiteralChar();
          }
        } else {
          var result1 = null;
        }
        var result2 = result1 !== null
          ? (function(literal) { return literal.join('') })(result1)
          : null;
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result0 = null;
          pos = savedPos0;
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_LiteralChar() {
        var cacheKey = 'LiteralChar@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos0 = pos;
        var savedPos1 = pos;
        var savedPos3 = pos;
        var savedReportMatchFailuresVar1 = reportMatchFailures;
        reportMatchFailures = false;
        var result7 = parse_InlineCommentOpen();
        reportMatchFailures = savedReportMatchFailuresVar1;
        if (result7 === null) {
          var result3 = '';
        } else {
          var result3 = null;
          pos = savedPos3;
        }
        if (result3 !== null) {
          var savedPos2 = pos;
          var savedReportMatchFailuresVar0 = reportMatchFailures;
          reportMatchFailures = false;
          var result6 = parse_LineTerminator();
          reportMatchFailures = savedReportMatchFailuresVar0;
          if (result6 === null) {
            var result4 = '';
          } else {
            var result4 = null;
            pos = savedPos2;
          }
          if (result4 !== null) {
            var result5 = parse_NonTerminator();
            if (result5 !== null) {
              var result1 = [result3, result4, result5];
            } else {
              var result1 = null;
              pos = savedPos1;
            }
          } else {
            var result1 = null;
            pos = savedPos1;
          }
        } else {
          var result1 = null;
          pos = savedPos1;
        }
        var result2 = result1 !== null
          ? (function(char) { return char })(result1[2])
          : null;
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result0 = null;
          pos = savedPos0;
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_NonTerminator() {
        var cacheKey = 'NonTerminator@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        if (input.substr(pos).match(/^[^;,\n]/) !== null) {
          var result0 = input.charAt(pos);
          pos++;
        } else {
          var result0 = null;
          if (reportMatchFailures) {
            matchFailed("[^;,\\n]");
          }
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_SingleLineComment() {
        var cacheKey = 'SingleLineComment@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos0 = pos;
        var savedPos1 = pos;
        if (input.substr(pos, 2) === "//") {
          var result3 = "//";
          pos += 2;
        } else {
          var result3 = null;
          if (reportMatchFailures) {
            matchFailed("\"//\"");
          }
        }
        if (result3 !== null) {
          var result4 = parse__();
          if (result4 !== null) {
            var result5 = parse_OneLineString();
            if (result5 !== null) {
              var result6 = parse_NewLine();
              if (result6 !== null) {
                var result1 = [result3, result4, result5, result6];
              } else {
                var result1 = null;
                pos = savedPos1;
              }
            } else {
              var result1 = null;
              pos = savedPos1;
            }
          } else {
            var result1 = null;
            pos = savedPos1;
          }
        } else {
          var result1 = null;
          pos = savedPos1;
        }
        var result2 = result1 !== null
          ? (function(contents) { return contents })(result1[2])
          : null;
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result0 = null;
          pos = savedPos0;
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_OneLineString() {
        var cacheKey = 'OneLineString@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos0 = pos;
        var result1 = [];
        var result3 = parse_NonLine();
        while (result3 !== null) {
          result1.push(result3);
          var result3 = parse_NonLine();
        }
        var result2 = result1 !== null
          ? (function(contents) { return contents.join('') })(result1)
          : null;
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result0 = null;
          pos = savedPos0;
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_Digit() {
        var cacheKey = 'Digit@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        if (input.substr(pos).match(/^[0-9]/) !== null) {
          var result0 = input.charAt(pos);
          pos++;
        } else {
          var result0 = null;
          if (reportMatchFailures) {
            matchFailed("[0-9]");
          }
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_Alpha() {
        var cacheKey = 'Alpha@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        if (input.substr(pos).match(/^[A-Za-z]/) !== null) {
          var result0 = input.charAt(pos);
          pos++;
        } else {
          var result0 = null;
          if (reportMatchFailures) {
            matchFailed("[A-Za-z]");
          }
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_DoubleQuote() {
        var cacheKey = 'DoubleQuote@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        if (input.substr(pos, 1) === "\"") {
          var result0 = "\"";
          pos += 1;
        } else {
          var result0 = null;
          if (reportMatchFailures) {
            matchFailed("\"\\\"\"");
          }
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse__() {
        var cacheKey = '_@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        var savedReportMatchFailures = reportMatchFailures;
        reportMatchFailures = false;
        var result0 = [];
        var result1 = parse_whitespace();
        while (result1 !== null) {
          result0.push(result1);
          var result1 = parse_whitespace();
        }
        reportMatchFailures = savedReportMatchFailures;
        if (reportMatchFailures && result0 === null) {
          matchFailed("whitespace");
        }
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_whitespace() {
        var cacheKey = 'whitespace@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var result2 = parse_NewLine();
        if (result2 !== null) {
          var result0 = result2;
        } else {
          if (input.substr(pos).match(/^[	 ]/) !== null) {
            var result1 = input.charAt(pos);
            pos++;
          } else {
            var result1 = null;
            if (reportMatchFailures) {
              matchFailed("[	 ]");
            }
          }
          if (result1 !== null) {
            var result0 = result1;
          } else {
            var result0 = null;;
          };
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_NonLine() {
        var cacheKey = 'NonLine@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var savedPos0 = pos;
        var savedPos1 = pos;
        var savedPos2 = pos;
        var savedReportMatchFailuresVar0 = reportMatchFailures;
        reportMatchFailures = false;
        var result5 = parse_NewLine();
        reportMatchFailures = savedReportMatchFailuresVar0;
        if (result5 === null) {
          var result3 = '';
        } else {
          var result3 = null;
          pos = savedPos2;
        }
        if (result3 !== null) {
          var result4 = parse_Char();
          if (result4 !== null) {
            var result1 = [result3, result4];
          } else {
            var result1 = null;
            pos = savedPos1;
          }
        } else {
          var result1 = null;
          pos = savedPos1;
        }
        var result2 = result1 !== null
          ? (function(char) { return char })(result1[1])
          : null;
        if (result2 !== null) {
          var result0 = result2;
        } else {
          var result0 = null;
          pos = savedPos0;
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_LineTerminator() {
        var cacheKey = 'LineTerminator@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        var result2 = parse_NewLine();
        if (result2 !== null) {
          var result0 = result2;
        } else {
          if (input.substr(pos, 1) === ";") {
            var result1 = ";";
            pos += 1;
          } else {
            var result1 = null;
            if (reportMatchFailures) {
              matchFailed("\";\"");
            }
          }
          if (result1 !== null) {
            var result0 = result1;
          } else {
            var result0 = null;;
          };
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_NewLine() {
        var cacheKey = 'NewLine@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        if (input.substr(pos).match(/^[\n\r]/) !== null) {
          var result0 = input.charAt(pos);
          pos++;
        } else {
          var result0 = null;
          if (reportMatchFailures) {
            matchFailed("[\\n\\r]");
          }
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function parse_Char() {
        var cacheKey = 'Char@' + pos;
        var cachedResult = cache[cacheKey];
        if (cachedResult) {
          pos = cachedResult.nextPos;
          return cachedResult.result;
        }
        
        
        if (input.length > pos) {
          var result0 = input.charAt(pos);
          pos++;
        } else {
          var result0 = null;
          if (reportMatchFailures) {
            matchFailed('any character');
          }
        }
        
        
        
        cache[cacheKey] = {
          nextPos: pos,
          result:  result0
        };
        return result0;
      }
      
      function buildErrorMessage() {
        function buildExpected(failuresExpected) {
          failuresExpected.sort();
          
          var lastFailure = null;
          var failuresExpectedUnique = [];
          for (var i = 0; i < failuresExpected.length; i++) {
            if (failuresExpected[i] !== lastFailure) {
              failuresExpectedUnique.push(failuresExpected[i]);
              lastFailure = failuresExpected[i];
            }
          }
          
          switch (failuresExpectedUnique.length) {
            case 0:
              return 'end of input';
            case 1:
              return failuresExpectedUnique[0];
            default:
              return failuresExpectedUnique.slice(0, failuresExpectedUnique.length - 1).join(', ')
                + ' or '
                + failuresExpectedUnique[failuresExpectedUnique.length - 1];
          }
        }
        
        var expected = buildExpected(rightmostMatchFailuresExpected);
        var actualPos = Math.max(pos, rightmostMatchFailuresPos);
        var actual = actualPos < input.length
          ? quote(input.charAt(actualPos))
          : 'end of input';
        
        return 'Expected ' + expected + ' but ' + actual + ' found.';
      }
      
      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 <  rightmostMatchFailuresPos; 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 merge(hash, secondHash) {
      
            secondHash = secondHash[0]
      
            for(var i in secondHash)
      
                hash[i] = secondHash[i]
      
    
      
            return hash;
      
        }
      
    
      
      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|
       *    - |rightmostMatchFailuresExpected| may or may not contain something
       *
       * 2. The parser successfully parsed only a part of the input.
       *
       *    - |result !== null|
       *    - |pos < input.length|
       *    - |rightmostMatchFailuresExpected| may or may not contain something
       *
       * 3. The parser did not successfully parse any part of the input.
       *
       *   - |result === null|
       *   - |pos === 0|
       *   - |rightmostMatchFailuresExpected| contains at least one failure
       *
       * All code following this comment (including called functions) must
       * handle these states.
       */
      if (result === null || pos !== input.length) {
        var errorPosition = computeErrorPosition();
        throw new this.SyntaxError(
          buildErrorMessage(),
          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(message, line, column) {
    this.name = 'SyntaxError';
    this.message = message;
    this.line = line;
    this.column = column;
  };
  
  result.SyntaxError.prototype = Error.prototype;
  
  return result;
})();
