import '../../../globals.js';
/*
 * NOTE: Generated from svgPath.pegjs using PEG.js, with added kite namespace and require.js compatibility.
 * See svgPath.pegjs for more documentation, or run 'grunt generate-svg-path-parser' to regenerate.
 */

import kite from '../kite.js';

/*
 * 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 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 )
         + '"';
}

const 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 ) {
    const parseFunctions = {
      svgPath: parse_svgPath,
      movetoDrawtoCommandGroups: parse_movetoDrawtoCommandGroups,
      movetoDrawtoCommandGroup: parse_movetoDrawtoCommandGroup,
      drawtoCommands: parse_drawtoCommands,
      drawtoCommand: parse_drawtoCommand,
      moveto: parse_moveto,
      movetoArgumentSequence: parse_movetoArgumentSequence,
      closepath: parse_closepath,
      lineto: parse_lineto,
      linetoArgumentSequence: parse_linetoArgumentSequence,
      horizontalLineto: parse_horizontalLineto,
      horizontalLinetoArgumentSequence: parse_horizontalLinetoArgumentSequence,
      verticalLineto: parse_verticalLineto,
      verticalLinetoArgumentSequence: parse_verticalLinetoArgumentSequence,
      curveto: parse_curveto,
      curvetoArgumentSequence: parse_curvetoArgumentSequence,
      curvetoArgument: parse_curvetoArgument,
      smoothCurveto: parse_smoothCurveto,
      smoothCurvetoArgumentSequence: parse_smoothCurvetoArgumentSequence,
      smoothCurvetoArgument: parse_smoothCurvetoArgument,
      quadraticBezierCurveto: parse_quadraticBezierCurveto,
      quadraticBezierCurvetoArgumentSequence: parse_quadraticBezierCurvetoArgumentSequence,
      quadraticBezierCurvetoArgument: parse_quadraticBezierCurvetoArgument,
      smoothQuadraticBezierCurveto: parse_smoothQuadraticBezierCurveto,
      smoothQuadraticBezierCurvetoArgumentSequence: parse_smoothQuadraticBezierCurvetoArgumentSequence,
      ellipticalArc: parse_ellipticalArc,
      ellipticalArcArgumentSequence: parse_ellipticalArcArgumentSequence,
      ellipticalArcArgument: parse_ellipticalArcArgument,
      coordinatePair: parse_coordinatePair,
      nonnegativeNumber: parse_nonnegativeNumber,
      number: parse_number,
      flag: parse_flag,
      commaWsp: parse_commaWsp,
      comma: parse_comma,
      floatingPointConstant: parse_floatingPointConstant,
      fractionalConstant: parse_fractionalConstant,
      exponent: parse_exponent,
      sign: parse_sign,
      digitSequence: parse_digitSequence,
      digit: parse_digit,
      wsp: parse_wsp
    };

    if ( startRule !== undefined ) {
      if ( parseFunctions[ startRule ] === undefined ) {
        throw new Error( 'Invalid rule name: ' + quote( startRule ) + '.' );
      }
    }
    else {
      startRule = 'svgPath';
    }

    let pos = 0;
    const reportFailures = 0;
    let rightmostFailuresPos = 0;
    let rightmostFailuresExpected = [];

    function padLeft( input, padding, length ) {
      let result = input;

      const padLength = length - input.length;
      for ( let i = 0; i < padLength; i++ ) {
        result = padding + result;
      }

      return result;
    }

    function escape( ch ) {
      const charCode = ch.charCodeAt( 0 );
      let escapeChar;
      let 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_svgPath() {
      let result0;
      let result1;
      let result2;
      let
        result3;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      result0 = [];
      result1 = parse_wsp();
      while ( result1 !== null ) {
        result0.push( result1 );
        result1 = parse_wsp();
      }
      if ( result0 !== null ) {
        result1 = parse_movetoDrawtoCommandGroups();
        result1 = result1 !== null ? result1 : '';
        if ( result1 !== null ) {
          result2 = [];
          result3 = parse_wsp();
          while ( result3 !== null ) {
            result2.push( result3 );
            result3 = parse_wsp();
          }
          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, path ) { return path ? path : []; } )( pos0, result0[ 1 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      return result0;
    }

    function parse_movetoDrawtoCommandGroups() {
      let result0;
      let result1;
      let
        result2;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      result0 = parse_movetoDrawtoCommandGroup();
      if ( result0 !== null ) {
        result1 = [];
        result2 = parse_wsp();
        while ( result2 !== null ) {
          result1.push( result2 );
          result2 = parse_wsp();
        }
        if ( result1 !== null ) {
          result2 = parse_movetoDrawtoCommandGroups();
          if ( result2 !== null ) {
            result0 = [ result0, result1, result2 ];
          }
          else {
            result0 = null;
            pos = pos1;
          }
        }
        else {
          result0 = null;
          pos = pos1;
        }
      }
      else {
        result0 = null;
        pos = pos1;
      }
      if ( result0 !== null ) {
        result0 = ( function( offset, a, b ) { return a.concat( b ); } )( pos0, result0[ 0 ], result0[ 2 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      if ( result0 === null ) {
        pos0 = pos;
        result0 = parse_movetoDrawtoCommandGroup();
        if ( result0 !== null ) {
          result0 = ( function( offset, a ) { return a; } )( pos0, result0 );
        }
        if ( result0 === null ) {
          pos = pos0;
        }
      }
      return result0;
    }

    function parse_movetoDrawtoCommandGroup() {
      let result0;
      let result1;
      let
        result2;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      result0 = parse_moveto();
      if ( result0 !== null ) {
        result1 = [];
        result2 = parse_wsp();
        while ( result2 !== null ) {
          result1.push( result2 );
          result2 = parse_wsp();
        }
        if ( result1 !== null ) {
          result2 = parse_drawtoCommands();
          result2 = result2 !== null ? result2 : '';
          if ( result2 !== null ) {
            result0 = [ result0, result1, result2 ];
          }
          else {
            result0 = null;
            pos = pos1;
          }
        }
        else {
          result0 = null;
          pos = pos1;
        }
      }
      else {
        result0 = null;
        pos = pos1;
      }
      if ( result0 !== null ) {
        result0 = ( function( offset, m, c ) { return c.length ? m.concat( c ) : m; } )( pos0, result0[ 0 ], result0[ 2 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      return result0;
    }

    function parse_drawtoCommands() {
      let result0;
      let result1;
      let
        result2;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      result0 = parse_drawtoCommand();
      if ( result0 !== null ) {
        result1 = [];
        result2 = parse_wsp();
        while ( result2 !== null ) {
          result1.push( result2 );
          result2 = parse_wsp();
        }
        if ( result1 !== null ) {
          result2 = parse_drawtoCommands();
          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, cmd, cmds ) { return cmd.concat( cmds ); } )( pos0, result0[ 0 ], result0[ 2 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      if ( result0 === null ) {
        pos0 = pos;
        result0 = parse_drawtoCommand();
        if ( result0 !== null ) {
          result0 = ( function( offset, cmd ) { return cmd; } )( pos0, result0 );
        }
        if ( result0 === null ) {
          pos = pos0;
        }
      }
      return result0;
    }

    function parse_drawtoCommand() {
      let result0;

      result0 = parse_closepath();
      if ( result0 === null ) {
        result0 = parse_lineto();
        if ( result0 === null ) {
          result0 = parse_horizontalLineto();
          if ( result0 === null ) {
            result0 = parse_verticalLineto();
            if ( result0 === null ) {
              result0 = parse_curveto();
              if ( result0 === null ) {
                result0 = parse_smoothCurveto();
                if ( result0 === null ) {
                  result0 = parse_quadraticBezierCurveto();
                  if ( result0 === null ) {
                    result0 = parse_smoothQuadraticBezierCurveto();
                    if ( result0 === null ) {
                      result0 = parse_ellipticalArc();
                    }
                  }
                }
              }
            }
          }
        }
      }
      return result0;
    }

    function parse_moveto() {
      let result0;
      let result1;
      let
        result2;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      if ( input.charCodeAt( pos ) === 77 ) {
        result0 = 'M';
        pos++;
      }
      else {
        result0 = null;
        if ( reportFailures === 0 ) {
          matchFailed( '"M"' );
        }
      }
      if ( result0 !== null ) {
        result1 = [];
        result2 = parse_wsp();
        while ( result2 !== null ) {
          result1.push( result2 );
          result2 = parse_wsp();
        }
        if ( result1 !== null ) {
          result2 = parse_movetoArgumentSequence();
          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, args ) { return createMoveTo( args, false ); } )( pos0, result0[ 2 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      if ( result0 === null ) {
        pos0 = pos;
        pos1 = pos;
        if ( input.charCodeAt( pos ) === 109 ) {
          result0 = 'm';
          pos++;
        }
        else {
          result0 = null;
          if ( reportFailures === 0 ) {
            matchFailed( '"m"' );
          }
        }
        if ( result0 !== null ) {
          result1 = [];
          result2 = parse_wsp();
          while ( result2 !== null ) {
            result1.push( result2 );
            result2 = parse_wsp();
          }
          if ( result1 !== null ) {
            result2 = parse_movetoArgumentSequence();
            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, args ) { return createMoveTo( args, true ); } )( pos0, result0[ 2 ] );
        }
        if ( result0 === null ) {
          pos = pos0;
        }
      }
      return result0;
    }

    function parse_movetoArgumentSequence() {
      let result0;
      let result1;
      let
        result2;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      result0 = parse_coordinatePair();
      if ( result0 !== null ) {
        result1 = parse_commaWsp();
        result1 = result1 !== null ? result1 : '';
        if ( result1 !== null ) {
          result2 = parse_linetoArgumentSequence();
          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, pair, list ) { return [ pair ].concat( list ); } )( pos0, result0[ 0 ], result0[ 2 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      if ( result0 === null ) {
        pos0 = pos;
        result0 = parse_coordinatePair();
        if ( result0 !== null ) {
          result0 = ( function( offset, pair ) { return [ pair ]; } )( pos0, result0 );
        }
        if ( result0 === null ) {
          pos = pos0;
        }
      }
      return result0;
    }

    function parse_closepath() {
      let result0;
      let pos0;

      pos0 = pos;
      if ( input.charCodeAt( pos ) === 90 ) {
        result0 = 'Z';
        pos++;
      }
      else {
        result0 = null;
        if ( reportFailures === 0 ) {
          matchFailed( '"Z"' );
        }
      }
      if ( result0 === null ) {
        if ( input.charCodeAt( pos ) === 122 ) {
          result0 = 'z';
          pos++;
        }
        else {
          result0 = null;
          if ( reportFailures === 0 ) {
            matchFailed( '"z"' );
          }
        }
      }
      if ( result0 !== null ) {
        result0 = ( function( offset, command ) { return { cmd: 'close' }; } )( pos0, result0 );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      return result0;
    }

    function parse_lineto() {
      let result0;
      let result1;
      let
        result2;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      if ( input.charCodeAt( pos ) === 76 ) {
        result0 = 'L';
        pos++;
      }
      else {
        result0 = null;
        if ( reportFailures === 0 ) {
          matchFailed( '"L"' );
        }
      }
      if ( result0 !== null ) {
        result1 = [];
        result2 = parse_wsp();
        while ( result2 !== null ) {
          result1.push( result2 );
          result2 = parse_wsp();
        }
        if ( result1 !== null ) {
          result2 = parse_linetoArgumentSequence();
          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, args ) {
          return args.map( arg => {
            return {
              cmd: 'lineTo',
              args: [ arg.x, arg.y ]
            };
          } );
        } )( pos0, result0[ 2 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      if ( result0 === null ) {
        pos0 = pos;
        pos1 = pos;
        if ( input.charCodeAt( pos ) === 108 ) {
          result0 = 'l';
          pos++;
        }
        else {
          result0 = null;
          if ( reportFailures === 0 ) {
            matchFailed( '"l"' );
          }
        }
        if ( result0 !== null ) {
          result1 = [];
          result2 = parse_wsp();
          while ( result2 !== null ) {
            result1.push( result2 );
            result2 = parse_wsp();
          }
          if ( result1 !== null ) {
            result2 = parse_linetoArgumentSequence();
            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, args ) {
            return args.map( arg => {
              return {
                cmd: 'lineToRelative',
                args: [ arg.x, arg.y ]
              };
            } );
          } )( pos0, result0[ 2 ] );
        }
        if ( result0 === null ) {
          pos = pos0;
        }
      }
      return result0;
    }

    function parse_linetoArgumentSequence() {
      let result0;
      let result1;
      let
        result2;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      result0 = parse_coordinatePair();
      if ( result0 !== null ) {
        result1 = parse_commaWsp();
        result1 = result1 !== null ? result1 : '';
        if ( result1 !== null ) {
          result2 = parse_linetoArgumentSequence();
          if ( result2 !== null ) {
            result0 = [ result0, result1, result2 ];
          }
          else {
            result0 = null;
            pos = pos1;
          }
        }
        else {
          result0 = null;
          pos = pos1;
        }
      }
      else {
        result0 = null;
        pos = pos1;
      }
      if ( result0 !== null ) {
        result0 = ( function( offset, a, b ) { return [ a ].concat( b ); } )( pos0, result0[ 0 ], result0[ 2 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      if ( result0 === null ) {
        pos0 = pos;
        result0 = parse_coordinatePair();
        if ( result0 !== null ) {
          result0 = ( function( offset, a ) { return [ a ]; } )( pos0, result0 );
        }
        if ( result0 === null ) {
          pos = pos0;
        }
      }
      return result0;
    }

    function parse_horizontalLineto() {
      let result0;
      let result1;
      let
        result2;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      if ( input.charCodeAt( pos ) === 72 ) {
        result0 = 'H';
        pos++;
      }
      else {
        result0 = null;
        if ( reportFailures === 0 ) {
          matchFailed( '"H"' );
        }
      }
      if ( result0 !== null ) {
        result1 = [];
        result2 = parse_wsp();
        while ( result2 !== null ) {
          result1.push( result2 );
          result2 = parse_wsp();
        }
        if ( result1 !== null ) {
          result2 = parse_horizontalLinetoArgumentSequence();
          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, args ) {
          return args.map( arg => {
            return {
              cmd: 'horizontalLineTo',
              args: [ arg ]
            };
          } );
        } )( pos0, result0[ 2 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      if ( result0 === null ) {
        pos0 = pos;
        pos1 = pos;
        if ( input.charCodeAt( pos ) === 104 ) {
          result0 = 'h';
          pos++;
        }
        else {
          result0 = null;
          if ( reportFailures === 0 ) {
            matchFailed( '"h"' );
          }
        }
        if ( result0 !== null ) {
          result1 = [];
          result2 = parse_wsp();
          while ( result2 !== null ) {
            result1.push( result2 );
            result2 = parse_wsp();
          }
          if ( result1 !== null ) {
            result2 = parse_horizontalLinetoArgumentSequence();
            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, args ) {
            return args.map( arg => {
              return {
                cmd: 'horizontalLineToRelative',
                args: [ arg ]
              };
            } );
          } )( pos0, result0[ 2 ] );
        }
        if ( result0 === null ) {
          pos = pos0;
        }
      }
      return result0;
    }

    function parse_horizontalLinetoArgumentSequence() {
      let result0;
      let result1;
      let
        result2;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      result0 = parse_number();
      if ( result0 !== null ) {
        result1 = parse_commaWsp();
        result1 = result1 !== null ? result1 : '';
        if ( result1 !== null ) {
          result2 = parse_horizontalLinetoArgumentSequence();
          if ( result2 !== null ) {
            result0 = [ result0, result1, result2 ];
          }
          else {
            result0 = null;
            pos = pos1;
          }
        }
        else {
          result0 = null;
          pos = pos1;
        }
      }
      else {
        result0 = null;
        pos = pos1;
      }
      if ( result0 !== null ) {
        result0 = ( function( offset, a, b ) { return [ a ].concat( b ); } )( pos0, result0[ 0 ], result0[ 2 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      if ( result0 === null ) {
        pos0 = pos;
        result0 = parse_number();
        if ( result0 !== null ) {
          result0 = ( function( offset, a ) { return [ a ]; } )( pos0, result0 );
        }
        if ( result0 === null ) {
          pos = pos0;
        }
      }
      return result0;
    }

    function parse_verticalLineto() {
      let result0;
      let result1;
      let
        result2;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      if ( input.charCodeAt( pos ) === 86 ) {
        result0 = 'V';
        pos++;
      }
      else {
        result0 = null;
        if ( reportFailures === 0 ) {
          matchFailed( '"V"' );
        }
      }
      if ( result0 !== null ) {
        result1 = [];
        result2 = parse_wsp();
        while ( result2 !== null ) {
          result1.push( result2 );
          result2 = parse_wsp();
        }
        if ( result1 !== null ) {
          result2 = parse_verticalLinetoArgumentSequence();
          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, args ) {
          return args.map( arg => {
            return {
              cmd: 'verticalLineTo',
              args: [ arg ]
            };
          } );
        } )( pos0, result0[ 2 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      if ( result0 === null ) {
        pos0 = pos;
        pos1 = pos;
        if ( input.charCodeAt( pos ) === 118 ) {
          result0 = 'v';
          pos++;
        }
        else {
          result0 = null;
          if ( reportFailures === 0 ) {
            matchFailed( '"v"' );
          }
        }
        if ( result0 !== null ) {
          result1 = [];
          result2 = parse_wsp();
          while ( result2 !== null ) {
            result1.push( result2 );
            result2 = parse_wsp();
          }
          if ( result1 !== null ) {
            result2 = parse_verticalLinetoArgumentSequence();
            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, args ) {
            return args.map( arg => {
              return {
                cmd: 'verticalLineToRelative',
                args: [ arg ]
              };
            } );
          } )( pos0, result0[ 2 ] );
        }
        if ( result0 === null ) {
          pos = pos0;
        }
      }
      return result0;
    }

    function parse_verticalLinetoArgumentSequence() {
      let result0;
      let result1;
      let
        result2;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      result0 = parse_number();
      if ( result0 !== null ) {
        result1 = parse_commaWsp();
        result1 = result1 !== null ? result1 : '';
        if ( result1 !== null ) {
          result2 = parse_verticalLinetoArgumentSequence();
          if ( result2 !== null ) {
            result0 = [ result0, result1, result2 ];
          }
          else {
            result0 = null;
            pos = pos1;
          }
        }
        else {
          result0 = null;
          pos = pos1;
        }
      }
      else {
        result0 = null;
        pos = pos1;
      }
      if ( result0 !== null ) {
        result0 = ( function( offset, a, b ) { return [ a ].concat( b ); } )( pos0, result0[ 0 ], result0[ 2 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      if ( result0 === null ) {
        pos0 = pos;
        result0 = parse_number();
        if ( result0 !== null ) {
          result0 = ( function( offset, a ) { return [ a ]; } )( pos0, result0 );
        }
        if ( result0 === null ) {
          pos = pos0;
        }
      }
      return result0;
    }

    function parse_curveto() {
      let result0;
      let result1;
      let
        result2;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      if ( input.charCodeAt( pos ) === 67 ) {
        result0 = 'C';
        pos++;
      }
      else {
        result0 = null;
        if ( reportFailures === 0 ) {
          matchFailed( '"C"' );
        }
      }
      if ( result0 !== null ) {
        result1 = [];
        result2 = parse_wsp();
        while ( result2 !== null ) {
          result1.push( result2 );
          result2 = parse_wsp();
        }
        if ( result1 !== null ) {
          result2 = parse_curvetoArgumentSequence();
          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, args ) {
          return args.map( arg => {
            return {
              cmd: 'cubicCurveTo',
              args: arg
            };
          } );
        } )( pos0, result0[ 2 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      if ( result0 === null ) {
        pos0 = pos;
        pos1 = pos;
        if ( input.charCodeAt( pos ) === 99 ) {
          result0 = 'c';
          pos++;
        }
        else {
          result0 = null;
          if ( reportFailures === 0 ) {
            matchFailed( '"c"' );
          }
        }
        if ( result0 !== null ) {
          result1 = [];
          result2 = parse_wsp();
          while ( result2 !== null ) {
            result1.push( result2 );
            result2 = parse_wsp();
          }
          if ( result1 !== null ) {
            result2 = parse_curvetoArgumentSequence();
            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, args ) {
            return args.map( arg => {
              return {
                cmd: 'cubicCurveToRelative',
                args: arg
              };
            } );
          } )( pos0, result0[ 2 ] );
        }
        if ( result0 === null ) {
          pos = pos0;
        }
      }
      return result0;
    }

    function parse_curvetoArgumentSequence() {
      let result0;
      let result1;
      let
        result2;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      result0 = parse_curvetoArgument();
      if ( result0 !== null ) {
        result1 = parse_commaWsp();
        result1 = result1 !== null ? result1 : '';
        if ( result1 !== null ) {
          result2 = parse_curvetoArgumentSequence();
          if ( result2 !== null ) {
            result0 = [ result0, result1, result2 ];
          }
          else {
            result0 = null;
            pos = pos1;
          }
        }
        else {
          result0 = null;
          pos = pos1;
        }
      }
      else {
        result0 = null;
        pos = pos1;
      }
      if ( result0 !== null ) {
        result0 = ( function( offset, a, list ) { return [ a ].concat( list ); } )( pos0, result0[ 0 ], result0[ 2 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      if ( result0 === null ) {
        pos0 = pos;
        result0 = parse_curvetoArgument();
        if ( result0 !== null ) {
          result0 = ( function( offset, a ) { return [ a ]; } )( pos0, result0 );
        }
        if ( result0 === null ) {
          pos = pos0;
        }
      }
      return result0;
    }

    function parse_curvetoArgument() {
      let result0;
      let result1;
      let result2;
      let result3;
      let
        result4;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      result0 = parse_coordinatePair();
      if ( result0 !== null ) {
        result1 = parse_commaWsp();
        result1 = result1 !== null ? result1 : '';
        if ( result1 !== null ) {
          result2 = parse_coordinatePair();
          if ( result2 !== null ) {
            result3 = parse_commaWsp();
            result3 = result3 !== null ? result3 : '';
            if ( result3 !== null ) {
              result4 = parse_coordinatePair();
              if ( result4 !== null ) {
                result0 = [ result0, result1, result2, result3, result4 ];
              }
              else {
                result0 = null;
                pos = pos1;
              }
            }
            else {
              result0 = null;
              pos = pos1;
            }
          }
          else {
            result0 = null;
            pos = pos1;
          }
        }
        else {
          result0 = null;
          pos = pos1;
        }
      }
      else {
        result0 = null;
        pos = pos1;
      }
      if ( result0 !== null ) {
        result0 = ( function( offset, a, b, c ) { return [ a.x, a.y, b.x, b.y, c.x, c.y ]; } )( pos0, result0[ 0 ], result0[ 2 ], result0[ 4 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      return result0;
    }

    function parse_smoothCurveto() {
      let result0;
      let result1;
      let
        result2;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      if ( input.charCodeAt( pos ) === 83 ) {
        result0 = 'S';
        pos++;
      }
      else {
        result0 = null;
        if ( reportFailures === 0 ) {
          matchFailed( '"S"' );
        }
      }
      if ( result0 !== null ) {
        result1 = [];
        result2 = parse_wsp();
        while ( result2 !== null ) {
          result1.push( result2 );
          result2 = parse_wsp();
        }
        if ( result1 !== null ) {
          result2 = parse_smoothCurvetoArgumentSequence();
          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, args ) {
          return args.map( arg => {
            return {
              cmd: 'smoothCubicCurveTo',
              args: arg
            };
          } );
        } )( pos0, result0[ 2 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      if ( result0 === null ) {
        pos0 = pos;
        pos1 = pos;
        if ( input.charCodeAt( pos ) === 115 ) {
          result0 = 's';
          pos++;
        }
        else {
          result0 = null;
          if ( reportFailures === 0 ) {
            matchFailed( '"s"' );
          }
        }
        if ( result0 !== null ) {
          result1 = [];
          result2 = parse_wsp();
          while ( result2 !== null ) {
            result1.push( result2 );
            result2 = parse_wsp();
          }
          if ( result1 !== null ) {
            result2 = parse_smoothCurvetoArgumentSequence();
            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, args ) {
            return args.map( arg => {
              return {
                cmd: 'smoothCubicCurveToRelative',
                args: arg
              };
            } );
          } )( pos0, result0[ 2 ] );
        }
        if ( result0 === null ) {
          pos = pos0;
        }
      }
      return result0;
    }

    function parse_smoothCurvetoArgumentSequence() {
      let result0;
      let result1;
      let
        result2;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      result0 = parse_smoothCurvetoArgument();
      if ( result0 !== null ) {
        result1 = parse_commaWsp();
        result1 = result1 !== null ? result1 : '';
        if ( result1 !== null ) {
          result2 = parse_smoothCurvetoArgumentSequence();
          if ( result2 !== null ) {
            result0 = [ result0, result1, result2 ];
          }
          else {
            result0 = null;
            pos = pos1;
          }
        }
        else {
          result0 = null;
          pos = pos1;
        }
      }
      else {
        result0 = null;
        pos = pos1;
      }
      if ( result0 !== null ) {
        result0 = ( function( offset, a, list ) { return [ a ].concat( list ); } )( pos0, result0[ 0 ], result0[ 2 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      if ( result0 === null ) {
        pos0 = pos;
        result0 = parse_smoothCurvetoArgument();
        if ( result0 !== null ) {
          result0 = ( function( offset, a ) { return [ a ]; } )( pos0, result0 );
        }
        if ( result0 === null ) {
          pos = pos0;
        }
      }
      return result0;
    }

    function parse_smoothCurvetoArgument() {
      let result0;
      let result1;
      let
        result2;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      result0 = parse_coordinatePair();
      if ( result0 !== null ) {
        result1 = parse_commaWsp();
        result1 = result1 !== null ? result1 : '';
        if ( result1 !== null ) {
          result2 = parse_coordinatePair();
          if ( result2 !== null ) {
            result0 = [ result0, result1, result2 ];
          }
          else {
            result0 = null;
            pos = pos1;
          }
        }
        else {
          result0 = null;
          pos = pos1;
        }
      }
      else {
        result0 = null;
        pos = pos1;
      }
      if ( result0 !== null ) {
        result0 = ( function( offset, a, b ) { return [ a.x, a.y, b.x, b.y ]; } )( pos0, result0[ 0 ], result0[ 2 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      return result0;
    }

    function parse_quadraticBezierCurveto() {
      let result0;
      let result1;
      let
        result2;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      if ( input.charCodeAt( pos ) === 81 ) {
        result0 = 'Q';
        pos++;
      }
      else {
        result0 = null;
        if ( reportFailures === 0 ) {
          matchFailed( '"Q"' );
        }
      }
      if ( result0 !== null ) {
        result1 = [];
        result2 = parse_wsp();
        while ( result2 !== null ) {
          result1.push( result2 );
          result2 = parse_wsp();
        }
        if ( result1 !== null ) {
          result2 = parse_quadraticBezierCurvetoArgumentSequence();
          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, args ) {
          return args.map( arg => {
            return {
              cmd: 'quadraticCurveTo',
              args: arg
            };
          } );
        } )( pos0, result0[ 2 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      if ( result0 === null ) {
        pos0 = pos;
        pos1 = pos;
        if ( input.charCodeAt( pos ) === 113 ) {
          result0 = 'q';
          pos++;
        }
        else {
          result0 = null;
          if ( reportFailures === 0 ) {
            matchFailed( '"q"' );
          }
        }
        if ( result0 !== null ) {
          result1 = [];
          result2 = parse_wsp();
          while ( result2 !== null ) {
            result1.push( result2 );
            result2 = parse_wsp();
          }
          if ( result1 !== null ) {
            result2 = parse_quadraticBezierCurvetoArgumentSequence();
            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, args ) {
            return args.map( arg => {
              return {
                cmd: 'quadraticCurveToRelative',
                args: arg
              };
            } );
          } )( pos0, result0[ 2 ] );
        }
        if ( result0 === null ) {
          pos = pos0;
        }
      }
      return result0;
    }

    function parse_quadraticBezierCurvetoArgumentSequence() {
      let result0;
      let result1;
      let
        result2;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      result0 = parse_quadraticBezierCurvetoArgument();
      if ( result0 !== null ) {
        result1 = parse_commaWsp();
        result1 = result1 !== null ? result1 : '';
        if ( result1 !== null ) {
          result2 = parse_quadraticBezierCurvetoArgumentSequence();
          if ( result2 !== null ) {
            result0 = [ result0, result1, result2 ];
          }
          else {
            result0 = null;
            pos = pos1;
          }
        }
        else {
          result0 = null;
          pos = pos1;
        }
      }
      else {
        result0 = null;
        pos = pos1;
      }
      if ( result0 !== null ) {
        result0 = ( function( offset, a, list ) { return [ a ].concat( list ); } )( pos0, result0[ 0 ], result0[ 2 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      if ( result0 === null ) {
        pos0 = pos;
        result0 = parse_quadraticBezierCurvetoArgument();
        if ( result0 !== null ) {
          result0 = ( function( offset, a ) { return [ a ]; } )( pos0, result0 );
        }
        if ( result0 === null ) {
          pos = pos0;
        }
      }
      return result0;
    }

    function parse_quadraticBezierCurvetoArgument() {
      let result0;
      let result1;
      let
        result2;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      result0 = parse_coordinatePair();
      if ( result0 !== null ) {
        result1 = parse_commaWsp();
        result1 = result1 !== null ? result1 : '';
        if ( result1 !== null ) {
          result2 = parse_coordinatePair();
          if ( result2 !== null ) {
            result0 = [ result0, result1, result2 ];
          }
          else {
            result0 = null;
            pos = pos1;
          }
        }
        else {
          result0 = null;
          pos = pos1;
        }
      }
      else {
        result0 = null;
        pos = pos1;
      }
      if ( result0 !== null ) {
        result0 = ( function( offset, a, b ) { return [ a.x, a.y, b.x, b.y ]; } )( pos0, result0[ 0 ], result0[ 2 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      return result0;
    }

    function parse_smoothQuadraticBezierCurveto() {
      let result0;
      let result1;
      let
        result2;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      if ( input.charCodeAt( pos ) === 84 ) {
        result0 = 'T';
        pos++;
      }
      else {
        result0 = null;
        if ( reportFailures === 0 ) {
          matchFailed( '"T"' );
        }
      }
      if ( result0 !== null ) {
        result1 = [];
        result2 = parse_wsp();
        while ( result2 !== null ) {
          result1.push( result2 );
          result2 = parse_wsp();
        }
        if ( result1 !== null ) {
          result2 = parse_smoothQuadraticBezierCurvetoArgumentSequence();
          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, args ) {
          return args.map( arg => {
            return {
              cmd: 'smoothQuadraticCurveTo',
              args: [ arg.x, arg.y ]
            };
          } );
        } )( pos0, result0[ 2 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      if ( result0 === null ) {
        pos0 = pos;
        pos1 = pos;
        if ( input.charCodeAt( pos ) === 116 ) {
          result0 = 't';
          pos++;
        }
        else {
          result0 = null;
          if ( reportFailures === 0 ) {
            matchFailed( '"t"' );
          }
        }
        if ( result0 !== null ) {
          result1 = [];
          result2 = parse_wsp();
          while ( result2 !== null ) {
            result1.push( result2 );
            result2 = parse_wsp();
          }
          if ( result1 !== null ) {
            result2 = parse_smoothQuadraticBezierCurvetoArgumentSequence();
            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, args ) {
            return args.map( arg => {
              return {
                cmd: 'smoothQuadraticCurveToRelative',
                args: [ arg.x, arg.y ]
              };
            } );
          } )( pos0, result0[ 2 ] );
        }
        if ( result0 === null ) {
          pos = pos0;
        }
      }
      return result0;
    }

    function parse_smoothQuadraticBezierCurvetoArgumentSequence() {
      let result0;
      let result1;
      let
        result2;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      result0 = parse_coordinatePair();
      if ( result0 !== null ) {
        result1 = parse_commaWsp();
        result1 = result1 !== null ? result1 : '';
        if ( result1 !== null ) {
          result2 = parse_smoothQuadraticBezierCurvetoArgumentSequence();
          if ( result2 !== null ) {
            result0 = [ result0, result1, result2 ];
          }
          else {
            result0 = null;
            pos = pos1;
          }
        }
        else {
          result0 = null;
          pos = pos1;
        }
      }
      else {
        result0 = null;
        pos = pos1;
      }
      if ( result0 !== null ) {
        result0 = ( function( offset, a, list ) { return [ a ].concat( list ); } )( pos0, result0[ 0 ], result0[ 2 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      if ( result0 === null ) {
        pos0 = pos;
        result0 = parse_coordinatePair();
        if ( result0 !== null ) {
          result0 = ( function( offset, a ) { return [ a ]; } )( pos0, result0 );
        }
        if ( result0 === null ) {
          pos = pos0;
        }
      }
      return result0;
    }

    function parse_ellipticalArc() {
      let result0;
      let result1;
      let
        result2;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      if ( input.charCodeAt( pos ) === 65 ) {
        result0 = 'A';
        pos++;
      }
      else {
        result0 = null;
        if ( reportFailures === 0 ) {
          matchFailed( '"A"' );
        }
      }
      if ( result0 !== null ) {
        result1 = [];
        result2 = parse_wsp();
        while ( result2 !== null ) {
          result1.push( result2 );
          result2 = parse_wsp();
        }
        if ( result1 !== null ) {
          result2 = parse_ellipticalArcArgumentSequence();
          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, args ) {
          return args.map( arg => {
            arg[ 2 ] *= Math.PI / 180;
            return { cmd: 'ellipticalArcTo', args: arg };
          } );
        } )( pos0, result0[ 2 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      if ( result0 === null ) {
        pos0 = pos;
        pos1 = pos;
        if ( input.charCodeAt( pos ) === 97 ) {
          result0 = 'a';
          pos++;
        }
        else {
          result0 = null;
          if ( reportFailures === 0 ) {
            matchFailed( '"a"' );
          }
        }
        if ( result0 !== null ) {
          result1 = [];
          result2 = parse_wsp();
          while ( result2 !== null ) {
            result1.push( result2 );
            result2 = parse_wsp();
          }
          if ( result1 !== null ) {
            result2 = parse_ellipticalArcArgumentSequence();
            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, args ) {
            return args.map( arg => {
              arg[ 2 ] *= Math.PI / 180;
              return { cmd: 'ellipticalArcToRelative', args: arg };
            } );
          } )( pos0, result0[ 2 ] );
        }
        if ( result0 === null ) {
          pos = pos0;
        }
      }
      return result0;
    }

    function parse_ellipticalArcArgumentSequence() {
      let result0;
      let result1;
      let
        result2;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      result0 = parse_ellipticalArcArgument();
      if ( result0 !== null ) {
        result1 = parse_commaWsp();
        result1 = result1 !== null ? result1 : '';
        if ( result1 !== null ) {
          result2 = parse_ellipticalArcArgumentSequence();
          if ( result2 !== null ) {
            result0 = [ result0, result1, result2 ];
          }
          else {
            result0 = null;
            pos = pos1;
          }
        }
        else {
          result0 = null;
          pos = pos1;
        }
      }
      else {
        result0 = null;
        pos = pos1;
      }
      if ( result0 !== null ) {
        result0 = ( function( offset, a, list ) { return [ a ].concat( list ); } )( pos0, result0[ 0 ], result0[ 2 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      if ( result0 === null ) {
        pos0 = pos;
        result0 = parse_ellipticalArcArgument();
        if ( result0 !== null ) {
          result0 = ( function( offset, a ) { return [ a ]; } )( pos0, result0 );
        }
        if ( result0 === null ) {
          pos = pos0;
        }
      }
      return result0;
    }

    function parse_ellipticalArcArgument() {
      let result0;
      let result1;
      let result2;
      let result3;
      let result4;
      let result5;
      let result6;
      let result7;
      let result8;
      let result9;
      let
        result10;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      result0 = parse_nonnegativeNumber();
      if ( result0 !== null ) {
        result1 = parse_commaWsp();
        result1 = result1 !== null ? result1 : '';
        if ( result1 !== null ) {
          result2 = parse_nonnegativeNumber();
          if ( result2 !== null ) {
            result3 = parse_commaWsp();
            result3 = result3 !== null ? result3 : '';
            if ( result3 !== null ) {
              result4 = parse_number();
              if ( result4 !== null ) {
                result5 = parse_commaWsp();
                if ( result5 !== null ) {
                  result6 = parse_flag();
                  if ( result6 !== null ) {
                    result7 = parse_commaWsp();
                    result7 = result7 !== null ? result7 : '';
                    if ( result7 !== null ) {
                      result8 = parse_flag();
                      if ( result8 !== null ) {
                        result9 = parse_commaWsp();
                        result9 = result9 !== null ? result9 : '';
                        if ( result9 !== null ) {
                          result10 = parse_coordinatePair();
                          if ( result10 !== null ) {
                            result0 = [ result0, result1, result2, result3, result4, result5, result6, result7, result8, result9, result10 ];
                          }
                          else {
                            result0 = null;
                            pos = pos1;
                          }
                        }
                        else {
                          result0 = null;
                          pos = pos1;
                        }
                      }
                      else {
                        result0 = null;
                        pos = pos1;
                      }
                    }
                    else {
                      result0 = null;
                      pos = pos1;
                    }
                  }
                  else {
                    result0 = null;
                    pos = pos1;
                  }
                }
                else {
                  result0 = null;
                  pos = pos1;
                }
              }
              else {
                result0 = null;
                pos = pos1;
              }
            }
            else {
              result0 = null;
              pos = pos1;
            }
          }
          else {
            result0 = null;
            pos = pos1;
          }
        }
        else {
          result0 = null;
          pos = pos1;
        }
      }
      else {
        result0 = null;
        pos = pos1;
      }
      if ( result0 !== null ) {
        result0 = ( function( offset, rx, ry, rot, largeArc, sweep, to ) { return [ rx, ry, rot, largeArc, sweep, to.x, to.y ]; } )( pos0, result0[ 0 ], result0[ 2 ], result0[ 4 ], result0[ 6 ], result0[ 8 ], result0[ 10 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      return result0;
    }

    function parse_coordinatePair() {
      let result0;
      let result1;
      let
        result2;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      result0 = parse_number();
      if ( result0 !== null ) {
        result1 = parse_commaWsp();
        result1 = result1 !== null ? result1 : '';
        if ( result1 !== null ) {
          result2 = parse_number();
          if ( result2 !== null ) {
            result0 = [ result0, result1, result2 ];
          }
          else {
            result0 = null;
            pos = pos1;
          }
        }
        else {
          result0 = null;
          pos = pos1;
        }
      }
      else {
        result0 = null;
        pos = pos1;
      }
      if ( result0 !== null ) {
        result0 = ( function( offset, a, b ) { return { x: a, y: b }; } )( pos0, result0[ 0 ], result0[ 2 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      return result0;
    }

    function parse_nonnegativeNumber() {
      let result0;
      let pos0;

      pos0 = pos;
      result0 = parse_floatingPointConstant();
      if ( result0 !== null ) {
        result0 = ( function( offset, number ) { return parseFloat( number ); } )( pos0, result0 );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      if ( result0 === null ) {
        pos0 = pos;
        result0 = parse_digitSequence();
        if ( result0 !== null ) {
          result0 = ( function( offset, number ) { return Number( number ); } )( pos0, result0 );
        }
        if ( result0 === null ) {
          pos = pos0;
        }
      }
      return result0;
    }

    function parse_number() {
      let result0;
      let
        result1;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      result0 = parse_sign();
      result0 = result0 !== null ? result0 : '';
      if ( result0 !== null ) {
        result1 = parse_floatingPointConstant();
        if ( result1 !== null ) {
          result0 = [ result0, result1 ];
        }
        else {
          result0 = null;
          pos = pos1;
        }
      }
      else {
        result0 = null;
        pos = pos1;
      }
      if ( result0 !== null ) {
        result0 = ( function( offset, sign, number ) { return parseFloat( sign + number ); } )( pos0, result0[ 0 ], result0[ 1 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      if ( result0 === null ) {
        pos0 = pos;
        pos1 = pos;
        result0 = parse_sign();
        result0 = result0 !== null ? result0 : '';
        if ( result0 !== null ) {
          result1 = parse_digitSequence();
          if ( result1 !== null ) {
            result0 = [ result0, result1 ];
          }
          else {
            result0 = null;
            pos = pos1;
          }
        }
        else {
          result0 = null;
          pos = pos1;
        }
        if ( result0 !== null ) {
          result0 = ( function( offset, sign, number ) { return Number( sign + number ); } )( pos0, result0[ 0 ], result0[ 1 ] );
        }
        if ( result0 === null ) {
          pos = pos0;
        }
      }
      return result0;
    }

    function parse_flag() {
      let result0;
      let pos0;

      pos0 = pos;
      if ( input.charCodeAt( pos ) === 48 ) {
        result0 = '0';
        pos++;
      }
      else {
        result0 = null;
        if ( reportFailures === 0 ) {
          matchFailed( '"0"' );
        }
      }
      if ( result0 !== null ) {
        result0 = ( function( offset ) { return false; } )( pos0 );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      if ( result0 === null ) {
        pos0 = pos;
        if ( input.charCodeAt( pos ) === 49 ) {
          result0 = '1';
          pos++;
        }
        else {
          result0 = null;
          if ( reportFailures === 0 ) {
            matchFailed( '"1"' );
          }
        }
        if ( result0 !== null ) {
          result0 = ( function( offset ) { return true; } )( pos0 );
        }
        if ( result0 === null ) {
          pos = pos0;
        }
      }
      return result0;
    }

    function parse_commaWsp() {
      let result0;
      let result1;
      let result2;
      let
        result3;
      let pos0;

      pos0 = pos;
      result1 = parse_wsp();
      if ( result1 !== null ) {
        result0 = [];
        while ( result1 !== null ) {
          result0.push( result1 );
          result1 = parse_wsp();
        }
      }
      else {
        result0 = null;
      }
      if ( result0 !== null ) {
        result1 = parse_comma();
        result1 = result1 !== null ? result1 : '';
        if ( result1 !== null ) {
          result2 = [];
          result3 = parse_wsp();
          while ( result3 !== null ) {
            result2.push( result3 );
            result3 = parse_wsp();
          }
          if ( result2 !== null ) {
            result0 = [ result0, result1, result2 ];
          }
          else {
            result0 = null;
            pos = pos0;
          }
        }
        else {
          result0 = null;
          pos = pos0;
        }
      }
      else {
        result0 = null;
        pos = pos0;
      }
      if ( result0 === null ) {
        pos0 = pos;
        result0 = parse_comma();
        if ( result0 !== null ) {
          result1 = [];
          result2 = parse_wsp();
          while ( result2 !== null ) {
            result1.push( result2 );
            result2 = parse_wsp();
          }
          if ( result1 !== null ) {
            result0 = [ result0, result1 ];
          }
          else {
            result0 = null;
            pos = pos0;
          }
        }
        else {
          result0 = null;
          pos = pos0;
        }
      }
      return result0;
    }

    function parse_comma() {
      let result0;

      if ( input.charCodeAt( pos ) === 44 ) {
        result0 = ',';
        pos++;
      }
      else {
        result0 = null;
        if ( reportFailures === 0 ) {
          matchFailed( '","' );
        }
      }
      return result0;
    }

    function parse_floatingPointConstant() {
      let result0;
      let
        result1;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      result0 = parse_fractionalConstant();
      if ( result0 !== null ) {
        result1 = parse_exponent();
        result1 = result1 !== null ? result1 : '';
        if ( result1 !== null ) {
          result0 = [ result0, result1 ];
        }
        else {
          result0 = null;
          pos = pos1;
        }
      }
      else {
        result0 = null;
        pos = pos1;
      }
      if ( result0 !== null ) {
        result0 = ( function( offset, a, b ) { return a + b; } )( pos0, result0[ 0 ], result0[ 1 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      if ( result0 === null ) {
        pos0 = pos;
        pos1 = pos;
        result0 = parse_digitSequence();
        if ( result0 !== null ) {
          result1 = parse_exponent();
          if ( result1 !== null ) {
            result0 = [ result0, result1 ];
          }
          else {
            result0 = null;
            pos = pos1;
          }
        }
        else {
          result0 = null;
          pos = pos1;
        }
        if ( result0 !== null ) {
          result0 = ( function( offset, a, b ) { return a + b; } )( pos0, result0[ 0 ], result0[ 1 ] );
        }
        if ( result0 === null ) {
          pos = pos0;
        }
      }
      return result0;
    }

    function parse_fractionalConstant() {
      let result0;
      let result1;
      let
        result2;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      result0 = parse_digitSequence();
      result0 = result0 !== null ? result0 : '';
      if ( result0 !== null ) {
        if ( input.charCodeAt( pos ) === 46 ) {
          result1 = '.';
          pos++;
        }
        else {
          result1 = null;
          if ( reportFailures === 0 ) {
            matchFailed( '"."' );
          }
        }
        if ( result1 !== null ) {
          result2 = parse_digitSequence();
          if ( result2 !== null ) {
            result0 = [ result0, result1, result2 ];
          }
          else {
            result0 = null;
            pos = pos1;
          }
        }
        else {
          result0 = null;
          pos = pos1;
        }
      }
      else {
        result0 = null;
        pos = pos1;
      }
      if ( result0 !== null ) {
        result0 = ( function( offset, a, b ) { return a + '.' + b; } )( pos0, result0[ 0 ], result0[ 2 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      if ( result0 === null ) {
        pos0 = pos;
        pos1 = pos;
        result0 = parse_digitSequence();
        if ( result0 !== null ) {
          if ( input.charCodeAt( pos ) === 46 ) {
            result1 = '.';
            pos++;
          }
          else {
            result1 = null;
            if ( reportFailures === 0 ) {
              matchFailed( '"."' );
            }
          }
          if ( result1 !== null ) {
            result0 = [ result0, result1 ];
          }
          else {
            result0 = null;
            pos = pos1;
          }
        }
        else {
          result0 = null;
          pos = pos1;
        }
        if ( result0 !== null ) {
          result0 = ( function( offset, a ) { return a; } )( pos0, result0[ 0 ] );
        }
        if ( result0 === null ) {
          pos = pos0;
        }
      }
      return result0;
    }

    function parse_exponent() {
      let result0;
      let result1;
      let
        result2;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      if ( input.charCodeAt( pos ) === 101 ) {
        result0 = 'e';
        pos++;
      }
      else {
        result0 = null;
        if ( reportFailures === 0 ) {
          matchFailed( '"e"' );
        }
      }
      if ( result0 === null ) {
        if ( input.charCodeAt( pos ) === 69 ) {
          result0 = 'E';
          pos++;
        }
        else {
          result0 = null;
          if ( reportFailures === 0 ) {
            matchFailed( '"E"' );
          }
        }
      }
      if ( result0 !== null ) {
        result1 = parse_sign();
        result1 = result1 !== null ? result1 : '';
        if ( result1 !== null ) {
          result2 = parse_digitSequence();
          if ( result2 !== null ) {
            result0 = [ result0, result1, result2 ];
          }
          else {
            result0 = null;
            pos = pos1;
          }
        }
        else {
          result0 = null;
          pos = pos1;
        }
      }
      else {
        result0 = null;
        pos = pos1;
      }
      if ( result0 !== null ) {
        result0 = ( function( offset, a, b, c ) { return a + b + c; } )( pos0, result0[ 0 ], result0[ 1 ], result0[ 2 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      return result0;
    }

    function parse_sign() {
      let result0;

      if ( input.charCodeAt( pos ) === 43 ) {
        result0 = '+';
        pos++;
      }
      else {
        result0 = null;
        if ( reportFailures === 0 ) {
          matchFailed( '"+"' );
        }
      }
      if ( result0 === null ) {
        if ( input.charCodeAt( pos ) === 45 ) {
          result0 = '-';
          pos++;
        }
        else {
          result0 = null;
          if ( reportFailures === 0 ) {
            matchFailed( '"-"' );
          }
        }
      }
      return result0;
    }

    function parse_digitSequence() {
      let result0;
      let
        result1;
      let pos0;
      let
        pos1;

      pos0 = pos;
      pos1 = pos;
      result0 = parse_digit();
      if ( result0 !== null ) {
        result1 = parse_digitSequence();
        if ( result1 !== null ) {
          result0 = [ result0, result1 ];
        }
        else {
          result0 = null;
          pos = pos1;
        }
      }
      else {
        result0 = null;
        pos = pos1;
      }
      if ( result0 !== null ) {
        result0 = ( function( offset, a, b ) { return a + b; } )( pos0, result0[ 0 ], result0[ 1 ] );
      }
      if ( result0 === null ) {
        pos = pos0;
      }
      if ( result0 === null ) {
        result0 = parse_digit();
      }
      return result0;
    }

    function parse_digit() {
      let result0;

      if ( /^[0-9]/.test( input.charAt( pos ) ) ) {
        result0 = input.charAt( pos );
        pos++;
      }
      else {
        result0 = null;
        if ( reportFailures === 0 ) {
          matchFailed( '[0-9]' );
        }
      }
      return result0;
    }

    function parse_wsp() {
      let result0;

      if ( input.charCodeAt( pos ) === 32 ) {
        result0 = ' ';
        pos++;
      }
      else {
        result0 = null;
        if ( reportFailures === 0 ) {
          matchFailed( '" "' );
        }
      }
      if ( result0 === null ) {
        if ( input.charCodeAt( pos ) === 9 ) {
          result0 = '\t';
          pos++;
        }
        else {
          result0 = null;
          if ( reportFailures === 0 ) {
            matchFailed( '"\\t"' );
          }
        }
        if ( result0 === null ) {
          if ( input.charCodeAt( pos ) === 13 ) {
            result0 = '\r';
            pos++;
          }
          else {
            result0 = null;
            if ( reportFailures === 0 ) {
              matchFailed( '"\\r"' );
            }
          }
          if ( result0 === null ) {
            if ( input.charCodeAt( pos ) === 10 ) {
              result0 = '\n';
              pos++;
            }
            else {
              result0 = null;
              if ( reportFailures === 0 ) {
                matchFailed( '"\\n"' );
              }
            }
          }
        }
      }
      return result0;
    }


    function cleanupExpected( expected ) {
      expected.sort();

      let lastExpected = null;
      const cleanExpected = [];
      for ( let 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.
       */

      let line = 1;
      let column = 1;
      let seenCR = false;

      for ( let i = 0; i < Math.max( pos, rightmostFailuresPos ); i++ ) {
        const 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 createMoveTo( args, isRelative ) {
      const result = [ {
        cmd: isRelative ? 'moveToRelative' : 'moveTo',
        args: [ args[ 0 ].x, args[ 0 ].y ]
      } ];

      // any other coordinate pairs are implicit lineTos
      if ( args.length > 1 ) {
        for ( let i = 1; i < args.length; i++ ) {
          result.push( {
            cmd: isRelative ? 'lineToRelative' : 'lineTo',
            args: [ args[ i ].x, args[ i ].y ]
          } );
        }
      }
      return result;
    }


    const 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 ) {
      const offset = Math.max( pos, rightmostFailuresPos );
      const found = offset < input.length ? input.charAt( offset ) : null;
      const 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 ) {
    let expectedHumanized;
    let
      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;

kite.register( 'svgPath', result );
export default kite.svgPath;
