module.exports = (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 = {
        "statements": parse_statements,
        "statement": parse_statement,
        "nestedStatement": parse_nestedStatement,
        "nestedStatements": parse_nestedStatements,
        "ccss": parse_ccss,
        "ccssStartChar": parse_ccssStartChar,
        "ccssOp": parse_ccssOp,
        "ContextualCCSSLine": parse_ContextualCCSSLine,
        "cssLine": parse_cssLine,
        "vfl": parse_vfl,
        "gtl": parse_gtl,
        "cssBlock": parse_cssBlock,
        "Ruleset": parse_Ruleset,
        "Directive": parse_Directive,
        "DirectiveName": parse_DirectiveName,
        "BlockedStatements": parse_BlockedStatements,
        "SelectorList": parse_SelectorList,
        "SelectorListEnd": parse_SelectorListEnd,
        "Selector": parse_Selector,
        "comment": parse_comment,
        "_": parse__,
        "__": parse___,
        "space": parse_space,
        "anychar": parse_anychar,
        "multitoend": parse_multitoend,
        "anytoend": parse_anytoend,
        "TextToColon": parse_TextToColon,
        "TextToSemicolon": parse_TextToSemicolon,
        "_terminators": parse__terminators,
        "LineTerminator": parse_LineTerminator
      };
      
      if (startRule !== undefined) {
        if (parseFunctions[startRule] === undefined) {
          throw new Error("Invalid rule name: " + quote(startRule) + ".");
        }
      } else {
        startRule = "statements";
      }
      
      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_statements() {
        var result0, result1, result2, result3;
        var pos0, pos1;
        
        pos0 = pos;
        pos1 = pos;
        result0 = [];
        result1 = parse_LineTerminator();
        while (result1 !== null) {
          result0.push(result1);
          result1 = parse_LineTerminator();
        }
        if (result0 !== null) {
          result2 = parse_statement();
          if (result2 !== null) {
            result1 = [];
            while (result2 !== null) {
              result1.push(result2);
              result2 = parse_statement();
            }
          } else {
            result1 = null;
          }
          if (result1 !== null) {
            result2 = [];
            result3 = parse_LineTerminator();
            while (result3 !== null) {
              result2.push(result3);
              result3 = parse_LineTerminator();
            }
            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, s) {return s})(pos0, result0[1]);
        }
        if (result0 === null) {
          pos = pos0;
        }
        if (result0 === null) {
          result0 = parse__();
        }
        return result0;
      }
      
      function parse_statement() {
        var result0;
        
        reportFailures++;
        result0 = parse_Ruleset();
        if (result0 === null) {
          result0 = parse_ccss();
          if (result0 === null) {
            result0 = parse_Directive();
            if (result0 === null) {
              result0 = parse_cssLine();
            }
          }
        }
        reportFailures--;
        if (reportFailures === 0 && result0 === null) {
          matchFailed("Statement");
        }
        return result0;
      }
      
      function parse_nestedStatement() {
        var result0;
        
        reportFailures++;
        result0 = parse_Ruleset();
        if (result0 === null) {
          result0 = parse_ccss();
          if (result0 === null) {
            result0 = parse_Directive();
            if (result0 === null) {
              result0 = parse_ContextualCCSSLine();
              if (result0 === null) {
                result0 = parse_cssLine();
              }
            }
          }
        }
        reportFailures--;
        if (reportFailures === 0 && result0 === null) {
          matchFailed("Nested Statement");
        }
        return result0;
      }
      
      function parse_nestedStatements() {
        var result0, result1, result2, result3;
        var pos0, pos1;
        
        pos0 = pos;
        pos1 = pos;
        result0 = [];
        result1 = parse_LineTerminator();
        while (result1 !== null) {
          result0.push(result1);
          result1 = parse_LineTerminator();
        }
        if (result0 !== null) {
          result1 = [];
          result2 = parse_nestedStatement();
          while (result2 !== null) {
            result1.push(result2);
            result2 = parse_nestedStatement();
          }
          if (result1 !== null) {
            result2 = [];
            result3 = parse_LineTerminator();
            while (result3 !== null) {
              result2.push(result3);
              result3 = parse_LineTerminator();
            }
            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, s) {return s})(pos0, result0[1]);
        }
        if (result0 === null) {
          pos = pos0;
        }
        if (result0 === null) {
          result0 = parse__();
        }
        return result0;
      }
      
      function parse_ccss() {
        var result0, result1, result2, result3, result4, result5, result6, result7, result8;
        var pos0, pos1;
        
        reportFailures++;
        pos0 = pos;
        pos1 = pos;
        result0 = parse__();
        if (result0 !== null) {
          result2 = parse_ccssStartChar();
          if (result2 !== null) {
            result1 = [];
            while (result2 !== null) {
              result1.push(result2);
              result2 = parse_ccssStartChar();
            }
          } else {
            result1 = null;
          }
          if (result1 !== null) {
            result2 = parse__();
            if (result2 !== null) {
              result3 = parse_ccssOp();
              if (result3 !== null) {
                result4 = parse_anytoend();
                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, ccss) { 
            return {type:'constraint', cssText: p.stringify(ccss)}; 
          })(pos0, result0);
        }
        if (result0 === null) {
          pos = pos0;
        }
        if (result0 === null) {
          pos0 = pos;
          pos1 = pos;
          result0 = parse__();
          if (result0 !== null) {
            if (input.charCodeAt(pos) === 64) {
              result1 = "@";
              pos++;
            } else {
              result1 = null;
              if (reportFailures === 0) {
                matchFailed("\"@\"");
              }
            }
            if (result1 !== null) {
              if (input.substr(pos, 5) === "-gss-") {
                result2 = "-gss-";
                pos += 5;
              } else {
                result2 = null;
                if (reportFailures === 0) {
                  matchFailed("\"-gss-\"");
                }
              }
              result2 = result2 !== null ? result2 : "";
              if (result2 !== null) {
                if (input.substr(pos, 4) === "stay") {
                  result3 = "stay";
                  pos += 4;
                } else {
                  result3 = null;
                  if (reportFailures === 0) {
                    matchFailed("\"stay\"");
                  }
                }
                if (result3 !== null) {
                  result4 = parse_anytoend();
                  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, stay) { 
              return {type:'constraint', cssText: p.stringify(stay)}; 
            })(pos0, result0);
          }
          if (result0 === null) {
            pos = pos0;
          }
          if (result0 === null) {
            pos0 = pos;
            pos1 = pos;
            result0 = parse__();
            if (result0 !== null) {
              if (input.charCodeAt(pos) === 64) {
                result1 = "@";
                pos++;
              } else {
                result1 = null;
                if (reportFailures === 0) {
                  matchFailed("\"@\"");
                }
              }
              if (result1 !== null) {
                if (input.substr(pos, 5) === "-gss-") {
                  result2 = "-gss-";
                  pos += 5;
                } else {
                  result2 = null;
                  if (reportFailures === 0) {
                    matchFailed("\"-gss-\"");
                  }
                }
                result2 = result2 !== null ? result2 : "";
                if (result2 !== null) {
                  if (input.substr(pos, 5) === "chain") {
                    result3 = "chain";
                    pos += 5;
                  } else {
                    result3 = null;
                    if (reportFailures === 0) {
                      matchFailed("\"chain\"");
                    }
                  }
                  if (result3 !== null) {
                    result4 = parse_anytoend();
                    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, chain) { 
                return {type:'constraint', cssText: p.stringify(chain)}; 
              })(pos0, result0);
            }
            if (result0 === null) {
              pos = pos0;
            }
            if (result0 === null) {
              pos0 = pos;
              pos1 = pos;
              result0 = parse__();
              if (result0 !== null) {
                if (input.charCodeAt(pos) === 64) {
                  result1 = "@";
                  pos++;
                } else {
                  result1 = null;
                  if (reportFailures === 0) {
                    matchFailed("\"@\"");
                  }
                }
                if (result1 !== null) {
                  if (input.substr(pos, 5) === "-gss-") {
                    result2 = "-gss-";
                    pos += 5;
                  } else {
                    result2 = null;
                    if (reportFailures === 0) {
                      matchFailed("\"-gss-\"");
                    }
                  }
                  result2 = result2 !== null ? result2 : "";
                  if (result2 !== null) {
                    if (input.substr(pos, 8) === "for-each") {
                      result3 = "for-each";
                      pos += 8;
                    } else {
                      result3 = null;
                      if (reportFailures === 0) {
                        matchFailed("\"for-each\"");
                      }
                    }
                    if (result3 === null) {
                      if (input.substr(pos, 7) === "for-all") {
                        result3 = "for-all";
                        pos += 7;
                      } else {
                        result3 = null;
                        if (reportFailures === 0) {
                          matchFailed("\"for-all\"");
                        }
                      }
                    }
                    if (result3 !== null) {
                      if (/^[^`]/.test(input.charAt(pos))) {
                        result5 = input.charAt(pos);
                        pos++;
                      } else {
                        result5 = null;
                        if (reportFailures === 0) {
                          matchFailed("[^`]");
                        }
                      }
                      if (result5 !== null) {
                        result4 = [];
                        while (result5 !== null) {
                          result4.push(result5);
                          if (/^[^`]/.test(input.charAt(pos))) {
                            result5 = input.charAt(pos);
                            pos++;
                          } else {
                            result5 = null;
                            if (reportFailures === 0) {
                              matchFailed("[^`]");
                            }
                          }
                        }
                      } else {
                        result4 = null;
                      }
                      if (result4 !== null) {
                        if (input.substr(pos, 3) === "```") {
                          result5 = "```";
                          pos += 3;
                        } else {
                          result5 = null;
                          if (reportFailures === 0) {
                            matchFailed("\"```\"");
                          }
                        }
                        if (result5 !== null) {
                          if (/^[^`]/.test(input.charAt(pos))) {
                            result7 = input.charAt(pos);
                            pos++;
                          } else {
                            result7 = null;
                            if (reportFailures === 0) {
                              matchFailed("[^`]");
                            }
                          }
                          if (result7 !== null) {
                            result6 = [];
                            while (result7 !== null) {
                              result6.push(result7);
                              if (/^[^`]/.test(input.charAt(pos))) {
                                result7 = input.charAt(pos);
                                pos++;
                              } else {
                                result7 = null;
                                if (reportFailures === 0) {
                                  matchFailed("[^`]");
                                }
                              }
                            }
                          } else {
                            result6 = null;
                          }
                          if (result6 !== null) {
                            if (input.substr(pos, 3) === "```") {
                              result7 = "```";
                              pos += 3;
                            } else {
                              result7 = null;
                              if (reportFailures === 0) {
                                matchFailed("\"```\"");
                              }
                            }
                            if (result7 !== null) {
                              result8 = parse_anytoend();
                              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, forlooper) { 
                  return {type:'constraint', cssText: p.stringify(forlooper)}; 
                })(pos0, result0);
              }
              if (result0 === null) {
                pos = pos0;
              }
            }
          }
        }
        reportFailures--;
        if (reportFailures === 0 && result0 === null) {
          matchFailed("CCSS");
        }
        return result0;
      }
      
      function parse_ccssStartChar() {
        var result0;
        
        if (/^[a-zA-Z0-9_#.[\]\-""' *+\/$^~%\\()~]/.test(input.charAt(pos))) {
          result0 = input.charAt(pos);
          pos++;
        } else {
          result0 = null;
          if (reportFailures === 0) {
            matchFailed("[a-zA-Z0-9_#.[\\]\\-\"\"' *+\\/$^~%\\\\()~]");
          }
        }
        if (result0 === null) {
          if (input.substr(pos, 2) === "::") {
            result0 = "::";
            pos += 2;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"::\"");
            }
          }
        }
        return result0;
      }
      
      function parse_ccssOp() {
        var result0;
        
        if (input.substr(pos, 2) === ">=") {
          result0 = ">=";
          pos += 2;
        } else {
          result0 = null;
          if (reportFailures === 0) {
            matchFailed("\">=\"");
          }
        }
        if (result0 === null) {
          if (input.substr(pos, 2) === "==") {
            result0 = "==";
            pos += 2;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"==\"");
            }
          }
          if (result0 === null) {
            if (input.substr(pos, 2) === "<=") {
              result0 = "<=";
              pos += 2;
            } else {
              result0 = null;
              if (reportFailures === 0) {
                matchFailed("\"<=\"");
              }
            }
            if (result0 === null) {
              if (input.substr(pos, 2) === "=>") {
                result0 = "=>";
                pos += 2;
              } else {
                result0 = null;
                if (reportFailures === 0) {
                  matchFailed("\"=>\"");
                }
              }
              if (result0 === null) {
                if (input.substr(pos, 2) === "=<") {
                  result0 = "=<";
                  pos += 2;
                } else {
                  result0 = null;
                  if (reportFailures === 0) {
                    matchFailed("\"=<\"");
                  }
                }
              }
            }
          }
        }
        return result0;
      }
      
      function parse_ContextualCCSSLine() {
        var result0, result1, result2, result3, result4, result5, result6;
        var pos0, pos1;
        
        reportFailures++;
        pos0 = pos;
        pos1 = pos;
        result0 = parse__();
        if (result0 !== null) {
          if (/^[a-zA-Z0-9\-_$]/.test(input.charAt(pos))) {
            result2 = input.charAt(pos);
            pos++;
          } else {
            result2 = null;
            if (reportFailures === 0) {
              matchFailed("[a-zA-Z0-9\\-_$]");
            }
          }
          if (result2 !== null) {
            result1 = [];
            while (result2 !== null) {
              result1.push(result2);
              if (/^[a-zA-Z0-9\-_$]/.test(input.charAt(pos))) {
                result2 = input.charAt(pos);
                pos++;
              } else {
                result2 = null;
                if (reportFailures === 0) {
                  matchFailed("[a-zA-Z0-9\\-_$]");
                }
              }
            }
          } else {
            result1 = null;
          }
          if (result1 !== null) {
            result2 = parse__();
            if (result2 !== null) {
              if (input.charCodeAt(pos) === 58) {
                result3 = ":";
                pos++;
              } else {
                result3 = null;
                if (reportFailures === 0) {
                  matchFailed("\":\"");
                }
              }
              if (result3 !== null) {
                result4 = parse__();
                if (result4 !== null) {
                  result5 = parse_ccssOp();
                  if (result5 !== null) {
                    result6 = parse_anytoend();
                    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, prop, op, tail) {
              return {type:'constraint', cssText: "::["+p.trim(prop)+"]"+" "+op+" "+p.stringify(tail)};
            })(pos0, result0[1], result0[5], result0[6]);
        }
        if (result0 === null) {
          pos = pos0;
        }
        reportFailures--;
        if (reportFailures === 0 && result0 === null) {
          matchFailed("Contextual CCSS Statement");
        }
        return result0;
      }
      
      function parse_cssLine() {
        var result0, result1, result2;
        var pos0, pos1;
        
        reportFailures++;
        pos0 = pos;
        pos1 = pos;
        result0 = parse__();
        if (result0 !== null) {
          result1 = parse_TextToColon();
          if (result1 !== null) {
            result2 = parse_TextToSemicolon();
            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, key, val) { return {type:'style', key:key, val:val}; })(pos0, result0[1], result0[2]);
        }
        if (result0 === null) {
          pos = pos0;
        }
        reportFailures--;
        if (reportFailures === 0 && result0 === null) {
          matchFailed("CSS Line");
        }
        return result0;
      }
      
      function parse_vfl() {
        var result0, result1, result2, result3;
        var pos0, pos1;
        
        pos0 = pos;
        pos1 = pos;
        result0 = parse__();
        if (result0 !== null) {
          if (input.substr(pos, 6) === "@-gss-") {
            result1 = "@-gss-";
            pos += 6;
          } else {
            result1 = null;
            if (reportFailures === 0) {
              matchFailed("\"@-gss-\"");
            }
          }
          if (result1 === null) {
            if (input.charCodeAt(pos) === 64) {
              result1 = "@";
              pos++;
            } else {
              result1 = null;
              if (reportFailures === 0) {
                matchFailed("\"@\"");
              }
            }
          }
          if (result1 !== null) {
            if (input.substr(pos, 10) === "horizontal") {
              result2 = "horizontal";
              pos += 10;
            } else {
              result2 = null;
              if (reportFailures === 0) {
                matchFailed("\"horizontal\"");
              }
            }
            if (result2 === null) {
              if (input.substr(pos, 8) === "vertical") {
                result2 = "vertical";
                pos += 8;
              } else {
                result2 = null;
                if (reportFailures === 0) {
                  matchFailed("\"vertical\"");
                }
              }
              if (result2 === null) {
                if (input.charCodeAt(pos) === 104) {
                  result2 = "h";
                  pos++;
                } else {
                  result2 = null;
                  if (reportFailures === 0) {
                    matchFailed("\"h\"");
                  }
                }
                if (result2 === null) {
                  if (input.charCodeAt(pos) === 118) {
                    result2 = "v";
                    pos++;
                  } else {
                    result2 = null;
                    if (reportFailures === 0) {
                      matchFailed("\"v\"");
                    }
                  }
                }
              }
            }
            if (result2 !== null) {
              result3 = parse_anytoend();
              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, vfl) { return ['vfl', parser.stringify(vfl)]; })(pos0, result0);
        }
        if (result0 === null) {
          pos = pos0;
        }
        return result0;
      }
      
      function parse_gtl() {
        var result0, result1, result2, result3;
        var pos0, pos1;
        
        pos0 = pos;
        pos1 = pos;
        result0 = parse__();
        if (result0 !== null) {
          if (input.substr(pos, 6) === "@-gss-") {
            result1 = "@-gss-";
            pos += 6;
          } else {
            result1 = null;
            if (reportFailures === 0) {
              matchFailed("\"@-gss-\"");
            }
          }
          if (result1 !== null) {
            if (input.substr(pos, 6) === "layout") {
              result2 = "layout";
              pos += 6;
            } else {
              result2 = null;
              if (reportFailures === 0) {
                matchFailed("\"layout\"");
              }
            }
            if (result2 === null) {
              if (input.substr(pos, 8) === "template") {
                result2 = "template";
                pos += 8;
              } else {
                result2 = null;
                if (reportFailures === 0) {
                  matchFailed("\"template\"");
                }
              }
            }
            if (result2 !== null) {
              result3 = parse_multitoend();
              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, gtl) { return ['gtl', parser.stringify(gtl)]; })(pos0, result0);
        }
        if (result0 === null) {
          pos = pos0;
        }
        return result0;
      }
      
      function parse_cssBlock() {
        var result0, result1;
        var pos0, pos1;
        
        pos0 = pos;
        pos1 = pos;
        result1 = parse_anychar();
        if (result1 !== null) {
          result0 = [];
          while (result1 !== null) {
            result0.push(result1);
            result1 = parse_anychar();
          }
        } else {
          result0 = null;
        }
        if (result0 !== null) {
          result1 = parse_multitoend();
          if (result1 !== null) {
            result0 = [result0, result1];
          } else {
            result0 = null;
            pos = pos1;
          }
        } else {
          result0 = null;
          pos = pos1;
        }
        if (result0 !== null) {
          result0 = (function(offset, block) { return ['css', parser.stringify(block)]; })(pos0, result0);
        }
        if (result0 === null) {
          pos = pos0;
        }
        return result0;
      }
      
      function parse_Ruleset() {
        var result0, result1, result2;
        var pos0, pos1;
        
        reportFailures++;
        pos0 = pos;
        pos1 = pos;
        result0 = parse__();
        if (result0 !== null) {
          result1 = parse_SelectorList();
          if (result1 !== null) {
            result2 = parse_BlockedStatements();
            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, sel, s) {
            return {type:'ruleset',selectors:sel,rules:s};
          })(pos0, result0[1], result0[2]);
        }
        if (result0 === null) {
          pos = pos0;
        }
        reportFailures--;
        if (reportFailures === 0 && result0 === null) {
          matchFailed("Ruleset");
        }
        return result0;
      }
      
      function parse_Directive() {
        var result0, result1, result2;
        var pos0, pos1;
        
        reportFailures++;
        pos0 = pos;
        pos1 = pos;
        result0 = parse_DirectiveName();
        if (result0 !== null) {
          result1 = [];
          if (/^[^@{};]/.test(input.charAt(pos))) {
            result2 = input.charAt(pos);
            pos++;
          } else {
            result2 = null;
            if (reportFailures === 0) {
              matchFailed("[^@{};]");
            }
          }
          while (result2 !== null) {
            result1.push(result2);
            if (/^[^@{};]/.test(input.charAt(pos))) {
              result2 = input.charAt(pos);
              pos++;
            } else {
              result2 = null;
              if (reportFailures === 0) {
                matchFailed("[^@{};]");
              }
            }
          }
          if (result1 !== null) {
            result2 = parse_BlockedStatements();
            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, name, terms, s) {
            var o;
            o = {type:'directive',name:p.trim(name),terms:p.trim(terms)};
            if (!!s) {o.rules = s;}
            return o;
          })(pos0, result0[0], result0[1], result0[2]);
        }
        if (result0 === null) {
          pos = pos0;
        }
        if (result0 === null) {
          pos0 = pos;
          pos1 = pos;
          result0 = parse_DirectiveName();
          if (result0 !== null) {
            result1 = parse_TextToSemicolon();
            if (result1 !== null) {
              result0 = [result0, result1];
            } else {
              result0 = null;
              pos = pos1;
            }
          } else {
            result0 = null;
            pos = pos1;
          }
          if (result0 !== null) {
            result0 = (function(offset, name, terms) {
              var o;
              o = {type:'directive',name:p.trim(name),terms:p.trim(terms)};    
              return o;
            })(pos0, result0[0], result0[1]);
          }
          if (result0 === null) {
            pos = pos0;
          }
        }
        reportFailures--;
        if (reportFailures === 0 && result0 === null) {
          matchFailed("Directive");
        }
        return result0;
      }
      
      function parse_DirectiveName() {
        var result0, result1, result2, result3;
        var pos0, pos1;
        
        reportFailures++;
        pos0 = pos;
        pos1 = pos;
        result0 = parse__();
        if (result0 !== null) {
          if (input.charCodeAt(pos) === 64) {
            result1 = "@";
            pos++;
          } else {
            result1 = null;
            if (reportFailures === 0) {
              matchFailed("\"@\"");
            }
          }
          if (result1 !== null) {
            if (/^[a-zA-Z0-9\-_$]/.test(input.charAt(pos))) {
              result3 = input.charAt(pos);
              pos++;
            } else {
              result3 = null;
              if (reportFailures === 0) {
                matchFailed("[a-zA-Z0-9\\-_$]");
              }
            }
            if (result3 !== null) {
              result2 = [];
              while (result3 !== null) {
                result2.push(result3);
                if (/^[a-zA-Z0-9\-_$]/.test(input.charAt(pos))) {
                  result3 = input.charAt(pos);
                  pos++;
                } else {
                  result3 = null;
                  if (reportFailures === 0) {
                    matchFailed("[a-zA-Z0-9\\-_$]");
                  }
                }
              }
            } else {
              result2 = null;
            }
            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, name) {return p.trim(name);})(pos0, result0[2]);
        }
        if (result0 === null) {
          pos = pos0;
        }
        reportFailures--;
        if (reportFailures === 0 && result0 === null) {
          matchFailed("Directive Name");
        }
        return result0;
      }
      
      function parse_BlockedStatements() {
        var result0, result1, result2, result3, result4, result5, result6, result7, result8;
        var pos0, pos1;
        
        reportFailures++;
        pos0 = pos;
        pos1 = pos;
        result0 = parse__();
        if (result0 !== null) {
          if (input.charCodeAt(pos) === 123) {
            result1 = "{";
            pos++;
          } else {
            result1 = null;
            if (reportFailures === 0) {
              matchFailed("\"{\"");
            }
          }
          if (result1 !== null) {
            result2 = parse__();
            if (result2 !== null) {
              result3 = parse_nestedStatements();
              if (result3 !== null) {
                result4 = parse__();
                if (result4 !== null) {
                  if (input.charCodeAt(pos) === 125) {
                    result5 = "}";
                    pos++;
                  } else {
                    result5 = null;
                    if (reportFailures === 0) {
                      matchFailed("\"}\"");
                    }
                  }
                  if (result5 !== null) {
                    result6 = parse__();
                    if (result6 !== null) {
                      result7 = [];
                      result8 = parse_LineTerminator();
                      while (result8 !== null) {
                        result7.push(result8);
                        result8 = parse_LineTerminator();
                      }
                      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, s) {return s;})(pos0, result0[3]);
        }
        if (result0 === null) {
          pos = pos0;
        }
        reportFailures--;
        if (reportFailures === 0 && result0 === null) {
          matchFailed("Statement Blocks");
        }
        return result0;
      }
      
      function parse_SelectorList() {
        var result0, result1, result2;
        var pos0, pos1;
        
        reportFailures++;
        pos0 = pos;
        pos1 = pos;
        result0 = parse_Selector();
        if (result0 !== null) {
          result1 = [];
          result2 = parse_SelectorListEnd();
          while (result2 !== null) {
            result1.push(result2);
            result2 = parse_SelectorListEnd();
          }
          if (result1 !== null) {
            result0 = [result0, result1];
          } else {
            result0 = null;
            pos = pos1;
          }
        } else {
          result0 = null;
          pos = pos1;
        }
        if (result0 !== null) {
          result0 = (function(offset, sel, sels) {return [sel].concat(sels)})(pos0, result0[0], result0[1]);
        }
        if (result0 === null) {
          pos = pos0;
        }
        reportFailures--;
        if (reportFailures === 0 && result0 === null) {
          matchFailed("SelectorList");
        }
        return result0;
      }
      
      function parse_SelectorListEnd() {
        var result0, result1, result2;
        var pos0, pos1;
        
        pos0 = pos;
        pos1 = pos;
        result0 = parse__();
        if (result0 !== null) {
          if (input.charCodeAt(pos) === 44) {
            result1 = ",";
            pos++;
          } else {
            result1 = null;
            if (reportFailures === 0) {
              matchFailed("\",\"");
            }
          }
          if (result1 !== null) {
            result2 = parse_Selector();
            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, sel) {return sel})(pos0, result0[2]);
        }
        if (result0 === null) {
          pos = pos0;
        }
        return result0;
      }
      
      function parse_Selector() {
        var result0, result1, result2;
        var pos0, pos1;
        
        reportFailures++;
        pos0 = pos;
        pos1 = pos;
        result0 = parse__();
        if (result0 !== null) {
          if (/^[^@{},;]/.test(input.charAt(pos))) {
            result2 = input.charAt(pos);
            pos++;
          } else {
            result2 = null;
            if (reportFailures === 0) {
              matchFailed("[^@{},;]");
            }
          }
          if (result2 !== null) {
            result1 = [];
            while (result2 !== null) {
              result1.push(result2);
              if (/^[^@{},;]/.test(input.charAt(pos))) {
                result2 = input.charAt(pos);
                pos++;
              } else {
                result2 = null;
                if (reportFailures === 0) {
                  matchFailed("[^@{},;]");
                }
              }
            }
          } else {
            result1 = null;
          }
          if (result1 !== null) {
            result2 = parse__();
            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, sel) {return sel.join("").trim()})(pos0, result0[1]);
        }
        if (result0 === null) {
          pos = pos0;
        }
        reportFailures--;
        if (reportFailures === 0 && result0 === null) {
          matchFailed("Selector");
        }
        return result0;
      }
      
      function parse_comment() {
        var result0, result1, result2, result3, result4, result5, result6, result7, result8;
        var pos0, pos1, pos2;
        
        reportFailures++;
        pos0 = pos;
        pos1 = pos;
        result0 = parse__();
        if (result0 !== null) {
          if (input.substr(pos, 2) === "/*") {
            result1 = "/*";
            pos += 2;
          } else {
            result1 = null;
            if (reportFailures === 0) {
              matchFailed("\"/*\"");
            }
          }
          if (result1 !== null) {
            result2 = [];
            if (/^[^*]/.test(input.charAt(pos))) {
              result3 = input.charAt(pos);
              pos++;
            } else {
              result3 = null;
              if (reportFailures === 0) {
                matchFailed("[^*]");
              }
            }
            while (result3 !== null) {
              result2.push(result3);
              if (/^[^*]/.test(input.charAt(pos))) {
                result3 = input.charAt(pos);
                pos++;
              } else {
                result3 = null;
                if (reportFailures === 0) {
                  matchFailed("[^*]");
                }
              }
            }
            if (result2 !== null) {
              if (input.charCodeAt(pos) === 42) {
                result4 = "*";
                pos++;
              } else {
                result4 = null;
                if (reportFailures === 0) {
                  matchFailed("\"*\"");
                }
              }
              if (result4 !== null) {
                result3 = [];
                while (result4 !== null) {
                  result3.push(result4);
                  if (input.charCodeAt(pos) === 42) {
                    result4 = "*";
                    pos++;
                  } else {
                    result4 = null;
                    if (reportFailures === 0) {
                      matchFailed("\"*\"");
                    }
                  }
                }
              } else {
                result3 = null;
              }
              if (result3 !== null) {
                result4 = [];
                pos2 = pos;
                if (/^[^\/*]/.test(input.charAt(pos))) {
                  result5 = input.charAt(pos);
                  pos++;
                } else {
                  result5 = null;
                  if (reportFailures === 0) {
                    matchFailed("[^\\/*]");
                  }
                }
                if (result5 !== null) {
                  result6 = [];
                  if (/^[^*]/.test(input.charAt(pos))) {
                    result7 = input.charAt(pos);
                    pos++;
                  } else {
                    result7 = null;
                    if (reportFailures === 0) {
                      matchFailed("[^*]");
                    }
                  }
                  while (result7 !== null) {
                    result6.push(result7);
                    if (/^[^*]/.test(input.charAt(pos))) {
                      result7 = input.charAt(pos);
                      pos++;
                    } else {
                      result7 = null;
                      if (reportFailures === 0) {
                        matchFailed("[^*]");
                      }
                    }
                  }
                  if (result6 !== null) {
                    if (input.charCodeAt(pos) === 42) {
                      result8 = "*";
                      pos++;
                    } else {
                      result8 = null;
                      if (reportFailures === 0) {
                        matchFailed("\"*\"");
                      }
                    }
                    if (result8 !== null) {
                      result7 = [];
                      while (result8 !== null) {
                        result7.push(result8);
                        if (input.charCodeAt(pos) === 42) {
                          result8 = "*";
                          pos++;
                        } else {
                          result8 = null;
                          if (reportFailures === 0) {
                            matchFailed("\"*\"");
                          }
                        }
                      }
                    } else {
                      result7 = null;
                    }
                    if (result7 !== null) {
                      result5 = [result5, result6, result7];
                    } else {
                      result5 = null;
                      pos = pos2;
                    }
                  } else {
                    result5 = null;
                    pos = pos2;
                  }
                } else {
                  result5 = null;
                  pos = pos2;
                }
                while (result5 !== null) {
                  result4.push(result5);
                  pos2 = pos;
                  if (/^[^\/*]/.test(input.charAt(pos))) {
                    result5 = input.charAt(pos);
                    pos++;
                  } else {
                    result5 = null;
                    if (reportFailures === 0) {
                      matchFailed("[^\\/*]");
                    }
                  }
                  if (result5 !== null) {
                    result6 = [];
                    if (/^[^*]/.test(input.charAt(pos))) {
                      result7 = input.charAt(pos);
                      pos++;
                    } else {
                      result7 = null;
                      if (reportFailures === 0) {
                        matchFailed("[^*]");
                      }
                    }
                    while (result7 !== null) {
                      result6.push(result7);
                      if (/^[^*]/.test(input.charAt(pos))) {
                        result7 = input.charAt(pos);
                        pos++;
                      } else {
                        result7 = null;
                        if (reportFailures === 0) {
                          matchFailed("[^*]");
                        }
                      }
                    }
                    if (result6 !== null) {
                      if (input.charCodeAt(pos) === 42) {
                        result8 = "*";
                        pos++;
                      } else {
                        result8 = null;
                        if (reportFailures === 0) {
                          matchFailed("\"*\"");
                        }
                      }
                      if (result8 !== null) {
                        result7 = [];
                        while (result8 !== null) {
                          result7.push(result8);
                          if (input.charCodeAt(pos) === 42) {
                            result8 = "*";
                            pos++;
                          } else {
                            result8 = null;
                            if (reportFailures === 0) {
                              matchFailed("\"*\"");
                            }
                          }
                        }
                      } else {
                        result7 = null;
                      }
                      if (result7 !== null) {
                        result5 = [result5, result6, result7];
                      } else {
                        result5 = null;
                        pos = pos2;
                      }
                    } else {
                      result5 = null;
                      pos = pos2;
                    }
                  } else {
                    result5 = null;
                    pos = pos2;
                  }
                }
                if (result4 !== null) {
                  if (input.charCodeAt(pos) === 47) {
                    result5 = "/";
                    pos++;
                  } else {
                    result5 = null;
                    if (reportFailures === 0) {
                      matchFailed("\"/\"");
                    }
                  }
                  if (result5 !== null) {
                    result6 = parse__();
                    if (result6 !== null) {
                      result7 = [];
                      result8 = parse_LineTerminator();
                      while (result8 !== null) {
                        result7.push(result8);
                        result8 = parse_LineTerminator();
                      }
                      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) {return ""})(pos0);
        }
        if (result0 === null) {
          pos = pos0;
        }
        reportFailures--;
        if (reportFailures === 0 && result0 === null) {
          matchFailed("Comment");
        }
        return result0;
      }
      
      function parse__() {
        var result0, result1;
        
        result0 = [];
        result1 = parse_space();
        while (result1 !== null) {
          result0.push(result1);
          result1 = parse_space();
        }
        return result0;
      }
      
      function parse___() {
        var result0, result1;
        
        result1 = parse_space();
        if (result1 !== null) {
          result0 = [];
          while (result1 !== null) {
            result0.push(result1);
            result1 = parse_space();
          }
        } else {
          result0 = null;
        }
        return result0;
      }
      
      function parse_space() {
        var result0;
        
        reportFailures++;
        if (input.charCodeAt(pos) === 32) {
          result0 = " ";
          pos++;
        } else {
          result0 = null;
          if (reportFailures === 0) {
            matchFailed("\" \"");
          }
        }
        if (result0 === null) {
          if (/^[\t]/.test(input.charAt(pos))) {
            result0 = input.charAt(pos);
            pos++;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("[\\t]");
            }
          }
          if (result0 === null) {
            if (/^[\xA0]/.test(input.charAt(pos))) {
              result0 = input.charAt(pos);
              pos++;
            } else {
              result0 = null;
              if (reportFailures === 0) {
                matchFailed("[\\xA0]");
              }
            }
          }
        }
        reportFailures--;
        if (reportFailures === 0 && result0 === null) {
          matchFailed("Space");
        }
        return result0;
      }
      
      function parse_anychar() {
        var result0;
        
        if (/^[a-zA-Z0-9 .,#:+?!^=()_\-$*\/\\""']/.test(input.charAt(pos))) {
          result0 = input.charAt(pos);
          pos++;
        } else {
          result0 = null;
          if (reportFailures === 0) {
            matchFailed("[a-zA-Z0-9 .,#:+?!^=()_\\-$*\\/\\\\\"\"']");
          }
        }
        return result0;
      }
      
      function parse_multitoend() {
        var result0, result1, result2, result3, result4;
        var pos0;
        
        reportFailures++;
        pos0 = pos;
        result0 = [];
        if (/^[^}]/.test(input.charAt(pos))) {
          result1 = input.charAt(pos);
          pos++;
        } else {
          result1 = null;
          if (reportFailures === 0) {
            matchFailed("[^}]");
          }
        }
        while (result1 !== null) {
          result0.push(result1);
          if (/^[^}]/.test(input.charAt(pos))) {
            result1 = input.charAt(pos);
            pos++;
          } else {
            result1 = null;
            if (reportFailures === 0) {
              matchFailed("[^}]");
            }
          }
        }
        if (result0 !== null) {
          if (input.charCodeAt(pos) === 125) {
            result1 = "}";
            pos++;
          } else {
            result1 = null;
            if (reportFailures === 0) {
              matchFailed("\"}\"");
            }
          }
          if (result1 !== null) {
            result2 = parse__();
            if (result2 !== null) {
              result3 = [];
              result4 = parse_LineTerminator();
              while (result4 !== null) {
                result3.push(result4);
                result4 = parse_LineTerminator();
              }
              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;
        }
        reportFailures--;
        if (reportFailures === 0 && result0 === null) {
          matchFailed("multitoend");
        }
        return result0;
      }
      
      function parse_anytoend() {
        var result0, result1, result2, result3, result4;
        var pos0;
        
        reportFailures++;
        pos0 = pos;
        result0 = [];
        if (/^[^;]/.test(input.charAt(pos))) {
          result1 = input.charAt(pos);
          pos++;
        } else {
          result1 = null;
          if (reportFailures === 0) {
            matchFailed("[^;]");
          }
        }
        while (result1 !== null) {
          result0.push(result1);
          if (/^[^;]/.test(input.charAt(pos))) {
            result1 = input.charAt(pos);
            pos++;
          } else {
            result1 = null;
            if (reportFailures === 0) {
              matchFailed("[^;]");
            }
          }
        }
        if (result0 !== null) {
          if (input.charCodeAt(pos) === 59) {
            result1 = ";";
            pos++;
          } else {
            result1 = null;
            if (reportFailures === 0) {
              matchFailed("\";\"");
            }
          }
          if (result1 !== null) {
            result2 = parse__();
            if (result2 !== null) {
              result3 = [];
              result4 = parse_LineTerminator();
              while (result4 !== null) {
                result3.push(result4);
                result4 = parse_LineTerminator();
              }
              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;
        }
        reportFailures--;
        if (reportFailures === 0 && result0 === null) {
          matchFailed("anytoend");
        }
        return result0;
      }
      
      function parse_TextToColon() {
        var result0, result1, result2, result3, result4;
        var pos0, pos1;
        
        reportFailures++;
        pos0 = pos;
        pos1 = pos;
        if (/^[^:{}]/.test(input.charAt(pos))) {
          result1 = input.charAt(pos);
          pos++;
        } else {
          result1 = null;
          if (reportFailures === 0) {
            matchFailed("[^:{}]");
          }
        }
        if (result1 !== null) {
          result0 = [];
          while (result1 !== null) {
            result0.push(result1);
            if (/^[^:{}]/.test(input.charAt(pos))) {
              result1 = input.charAt(pos);
              pos++;
            } else {
              result1 = null;
              if (reportFailures === 0) {
                matchFailed("[^:{}]");
              }
            }
          }
        } else {
          result0 = null;
        }
        if (result0 !== null) {
          if (input.charCodeAt(pos) === 58) {
            result1 = ":";
            pos++;
          } else {
            result1 = null;
            if (reportFailures === 0) {
              matchFailed("\":\"");
            }
          }
          if (result1 !== null) {
            result2 = parse__();
            if (result2 !== null) {
              result3 = [];
              result4 = parse_LineTerminator();
              while (result4 !== null) {
                result3.push(result4);
                result4 = parse_LineTerminator();
              }
              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, text) {return p.stringify(text)})(pos0, result0[0]);
        }
        if (result0 === null) {
          pos = pos0;
        }
        reportFailures--;
        if (reportFailures === 0 && result0 === null) {
          matchFailed("TextToColon");
        }
        return result0;
      }
      
      function parse_TextToSemicolon() {
        var result0, result1, result2, result3, result4;
        var pos0, pos1;
        
        reportFailures++;
        pos0 = pos;
        pos1 = pos;
        if (/^[^;{}]/.test(input.charAt(pos))) {
          result1 = input.charAt(pos);
          pos++;
        } else {
          result1 = null;
          if (reportFailures === 0) {
            matchFailed("[^;{}]");
          }
        }
        if (result1 !== null) {
          result0 = [];
          while (result1 !== null) {
            result0.push(result1);
            if (/^[^;{}]/.test(input.charAt(pos))) {
              result1 = input.charAt(pos);
              pos++;
            } else {
              result1 = null;
              if (reportFailures === 0) {
                matchFailed("[^;{}]");
              }
            }
          }
        } else {
          result0 = null;
        }
        if (result0 !== null) {
          if (input.charCodeAt(pos) === 59) {
            result1 = ";";
            pos++;
          } else {
            result1 = null;
            if (reportFailures === 0) {
              matchFailed("\";\"");
            }
          }
          if (result1 !== null) {
            result2 = parse__();
            if (result2 !== null) {
              result3 = [];
              result4 = parse_LineTerminator();
              while (result4 !== null) {
                result3.push(result4);
                result4 = parse_LineTerminator();
              }
              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, text) {return p.stringify(text)})(pos0, result0[0]);
        }
        if (result0 === null) {
          pos = pos0;
        }
        reportFailures--;
        if (reportFailures === 0 && result0 === null) {
          matchFailed("TextToSemicolon");
        }
        return result0;
      }
      
      function parse__terminators() {
        var result0, result1, result2;
        var pos0;
        
        pos0 = pos;
        result0 = parse__();
        if (result0 !== null) {
          result1 = [];
          result2 = parse_LineTerminator();
          while (result2 !== null) {
            result1.push(result2);
            result2 = parse_LineTerminator();
          }
          if (result1 !== null) {
            result0 = [result0, result1];
          } else {
            result0 = null;
            pos = pos0;
          }
        } else {
          result0 = null;
          pos = pos0;
        }
        return result0;
      }
      
      function parse_LineTerminator() {
        var result0, result1;
        var pos0;
        
        reportFailures++;
        pos0 = pos;
        if (/^[\n\r\u2028\u2029]/.test(input.charAt(pos))) {
          result0 = input.charAt(pos);
          pos++;
        } else {
          result0 = null;
          if (reportFailures === 0) {
            matchFailed("[\\n\\r\\u2028\\u2029]");
          }
        }
        if (result0 === null) {
          if (input.substr(pos, 2) === "\r\n") {
            result0 = "\r\n";
            pos += 2;
          } else {
            result0 = null;
            if (reportFailures === 0) {
              matchFailed("\"\\r\\n\"");
            }
          }
        }
        if (result0 !== null) {
          result1 = parse__();
          if (result1 !== null) {
            result0 = [result0, result1];
          } else {
            result0 = null;
            pos = pos0;
          }
        } else {
          result0 = null;
          pos = pos0;
        }
        if (result0 === null) {
          result0 = parse_comment();
        }
        reportFailures--;
        if (reportFailures === 0 && result0 === null) {
          matchFailed("LineTerminator");
        }
        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 };
      }
      
      
        var p, parser, flatten, idPrefix; 
        p = parser = this;
      
        String.prototype.trim = String.prototype.trim || function trim() { return this.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); };
      
        flatten = parser.flatten = function (array, isShallow) {
          var index = -1,
            length = array ? array.length : 0,
            result = [];
      
          while (++index < length) {
            var value = array[index];
      
            if (value instanceof Array) {
              Array.prototype.push.apply(result, isShallow ? value : flatten(value));
            }
            else {
              result.push(value);
            }
          }
          return result;
        }
      
        p.results = [];
      
        p.stringify = function (array) {
          return flatten(array).join("").trim();
        };
      
        p.trim = function (x) {
          if (typeof x === "string") {return x.trim();}
          if (x instanceof Array) {return x.join("").trim();}
          return ""
        };
        
        parser.error = function (m,l,c) {
          if (!!l && !!c) {
            m = m + " {line:" + l + ", col:" + c + "}";
          }
          console.error(m);
          return m;
        };
      
      
      
      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;
})();