<?php
/*
 * Generated by PEG.js 0.10.x with phpegjs plugin
 *
 * http://pegjs.majda.cz/
 */


/* Useful functions: */

/* Gutenberg_PEG_chr_unicode - get unicode character from its char code */
if (!function_exists("Gutenberg_PEG_chr_unicode")) {
    function Gutenberg_PEG_chr_unicode($code) {
        return html_entity_decode("&#$code;", ENT_QUOTES, "UTF-8");
    }
}
/* Gutenberg_PEG_ord_unicode - get unicode char code from string */
if (!function_exists("Gutenberg_PEG_ord_unicode")) {
    function Gutenberg_PEG_ord_unicode($character) {
        if (strlen($character) === 1) {
            return ord($character);
        }
        $json = json_encode($character);
        $utf16_1 = hexdec(substr($json, 3, 4));
        if (substr($json, 7, 2) === "\u") {
            $utf16_2 = hexdec(substr($json, 9, 4));
            return 0x10000 + (($utf16_1 & 0x3ff) << 10) + ($utf16_2 & 0x3ff);
        } else {
            return $utf16_1;
        }
    }
}
/* Gutenberg_PEG_peg_char_class_test - simple character class test */
if (!function_exists("Gutenberg_PEG_peg_char_class_test")) {
    function Gutenberg_PEG_peg_char_class_test($class, $character) {
        $code = Gutenberg_PEG_ord_unicode($character);
        foreach ($class as $range) {
            if ($code >= $range[0] && $code <= $range[1]) {
                return true;
            }
        }
        return false;
    }
}

/* Syntax error exception */
if (!class_exists("Gutenberg_PEG_SyntaxError", false)) {
    class Gutenberg_PEG_SyntaxError extends Exception {
        public $expected;
        public $found;
        public $grammarOffset;
        public $grammarLine;
        public $grammarColumn;
        public $name;
        public function __construct($message, $expected, $found, $offset, $line, $column) {
            parent::__construct($message, 0);
            $this->expected = $expected;
            $this->found = $found;
            $this->grammarOffset = $offset;
            $this->grammarLine = $line;
            $this->grammarColumn = $column;
            $this->name = "Gutenberg_PEG_SyntaxError";
        }
    }
}

class Gutenberg_PEG_Parser {
    private $peg_currPos          = 0;
    private $peg_reportedPos      = 0;
    private $peg_cachedPos        = 0;
    private $peg_cachedPosDetails = array('line' => 1, 'column' => 1, 'seenCR' => false );
    private $peg_maxFailPos       = 0;
    private $peg_maxFailExpected  = array();
    private $peg_silentFails      = 0;
    private $input                = array();
    private $input_length         = 0;

    private function cleanup_state() {
      $this->peg_currPos          = 0;
      $this->peg_reportedPos      = 0;
      $this->peg_cachedPos        = 0;
      $this->peg_cachedPosDetails = array('line' => 1, 'column' => 1, 'seenCR' => false );
      $this->peg_maxFailPos       = 0;
      $this->peg_maxFailExpected  = array();
      $this->peg_silentFails      = 0;
      $this->input                = array();
      $this->input_length         = 0;

    }

    private function input_substr($start, $length) {
      if ($length === 1 && $start < $this->input_length) {
        return $this->input[$start];
      }
      $substr = '';
      $max = min($start + $length, $this->input_length);
      for ($i = $start; $i < $max; $i++) {
        $substr .= $this->input[$i];
      }
      return $substr;
    }


    private function text() {
      return substr($this->input, $this->peg_reportedPos, $this->peg_reportedPos + $this->peg_currPos);
    }

    private function offset() {
      return $this->peg_reportedPos;
    }

    private function line() {
      $compute_pd = $this->peg_computePosDetails($this->peg_reportedPos);
      return $compute_pd["line"];
    }

    private function column() {
      $compute_pd = $this->peg_computePosDetails($this->peg_reportedPos);
      return $compute_pd["column"];
    }

    private function expected($description) {
      throw $this->peg_buildException(
        null,
        array(array("type" => "other", "description" => $description )),
        $this->peg_reportedPos
      );
    }

    private function error($message) {
      throw $this->peg_buildException($message, null, $this->peg_reportedPos);
    }

    private function peg_advancePos(&$details, $startPos, $endPos) {
      for ($p = $startPos; $p < $endPos; $p++) {
        $ch = $this->input_substr($p, 1);
        if ($ch === "\n") {
          if (!$details["seenCR"]) { $details["line"]++; }
          $details["column"] = 1;
          $details["seenCR"] = false;
        } else if ($ch === "\r" || $ch === "\u2028" || $ch === "\u2029") {
          $details["line"]++;
          $details["column"] = 1;
          $details["seenCR"] = true;
        } else {
          $details["column"]++;
          $details["seenCR"] = false;
        }
      }
    }

    private function peg_computePosDetails($pos) {
      if ($this->peg_cachedPos !== $pos) {
        if ($this->peg_cachedPos > $pos) {
          $this->peg_cachedPos = 0;
          $this->peg_cachedPosDetails = array( "line" => 1, "column" => 1, "seenCR" => false );
        }
        $this->peg_advancePos($this->peg_cachedPosDetails, $this->peg_cachedPos, $pos);
        $this->peg_cachedPos = $pos;
      }

      return $this->peg_cachedPosDetails;
    }

    private function peg_fail($expected) {
      if ($this->peg_currPos < $this->peg_maxFailPos) { return; }

      if ($this->peg_currPos > $this->peg_maxFailPos) {
        $this->peg_maxFailPos = $this->peg_currPos;
        $this->peg_maxFailExpected = array();
      }

      $this->peg_maxFailExpected[] = $expected;
    }

    private function peg_buildException_expectedComparator($a, $b) {
      if ($a["description"] < $b["description"]) {
        return -1;
      } else if ($a["description"] > $b["description"]) {
        return 1;
      } else {
        return 0;
      }
    }

    private function peg_buildException($message, $expected, $pos) {
      $posDetails = $this->peg_computePosDetails($pos);
      $found      = $pos < $this->input_length ? $this->input[$pos] : null;

      if ($expected !== null) {
        usort($expected, array($this, "peg_buildException_expectedComparator"));
        $i = 1;
        while ($i < count($expected)) {
          if ($expected[$i - 1] === $expected[$i]) {
            array_splice($expected, $i, 1);
          } else {
            $i++;
          }
        }
      }

      if ($message === null) {
        $expectedDescs = array_fill(0, count($expected), null);

        for ($i = 0; $i < count($expected); $i++) {
          $expectedDescs[$i] = $expected[$i]["description"];
        }

        $expectedDesc = count($expected) > 1
          ? join(", ", array_slice($expectedDescs, 0, -1))
              . " or "
              . $expectedDescs[count($expected) - 1]
          : $expectedDescs[0];

        $foundDesc = $found ? json_encode($found) : "end of input";

        $message = "Expected " . $expectedDesc . " but " . $foundDesc . " found.";
      }

      return new Gutenberg_PEG_SyntaxError(
        $message,
        $expected,
        $found,
        $pos,
        $posDetails["line"],
        $posDetails["column"]
      );
    }

    private $peg_FAILED;
    private $peg_c0;
    private $peg_c1;
    private $peg_c2;
    private $peg_c3;
    private $peg_c4;
    private $peg_c5;
    private $peg_c6;
    private $peg_c7;
    private $peg_c8;
    private $peg_c9;
    private $peg_c10;
    private $peg_c11;
    private $peg_c12;
    private $peg_c13;
    private $peg_c14;
    private $peg_c15;
    private $peg_c16;
    private $peg_c17;
    private $peg_c18;
    private $peg_c19;
    private $peg_c20;
    private $peg_c21;
    private $peg_c22;
    private $peg_c23;

    private function peg_f0($pre, $b, $html) { return array( $b, $html ); }
    private function peg_f1($pre, $bs, $post) { return peg_join_blocks( $pre, $bs, $post ); }
    private function peg_f2($blockName, $a) { return $a; }
    private function peg_f3($blockName, $attrs) {
        return array(
          'blockName'  => $blockName,
          'attrs'      => $attrs,
          'innerBlocks' => array(),
          'innerHTML' => '',
        );
        }
    private function peg_f4($s, $children, $e) {
        list( $innerHTML, $innerBlocks ) = peg_array_partition( $children, 'is_string' );

        return array(
          'blockName'  => $s['blockName'],
          'attrs'      => $s['attrs'],
          'innerBlocks'  => $innerBlocks,
          'innerHTML'  => implode( '', $innerHTML ),
        );
        }
    private function peg_f5($blockName, $attrs) {
        return array(
          'blockName' => $blockName,
          'attrs'     => $attrs,
        );
        }
    private function peg_f6($blockName) {
        return array(
          'blockName' => $blockName,
        );
        }
    private function peg_f7($type) { return "core/$type"; }
    private function peg_f8($attrs) { return json_decode( $attrs, true ); }

    private function peg_parseBlock_List() {

      $s0 = $this->peg_currPos;
      $s1 = $this->peg_currPos;
      $s2 = array();
      $s3 = $this->peg_currPos;
      $s4 = $this->peg_currPos;
      $this->peg_silentFails++;
      $s5 = $this->peg_parseBlock();
      $this->peg_silentFails--;
      if ($s5 === $this->peg_FAILED) {
        $s4 = null;
      } else {
        $this->peg_currPos = $s4;
        $s4 = $this->peg_FAILED;
      }
      if ($s4 !== $this->peg_FAILED) {
        if ($this->input_length > $this->peg_currPos) {
          $s5 = $this->input_substr($this->peg_currPos, 1);
          $this->peg_currPos++;
        } else {
          $s5 = $this->peg_FAILED;
          if ($this->peg_silentFails === 0) {
              $this->peg_fail($this->peg_c0);
          }
        }
        if ($s5 !== $this->peg_FAILED) {
          $s4 = array($s4, $s5);
          $s3 = $s4;
        } else {
          $this->peg_currPos = $s3;
          $s3 = $this->peg_FAILED;
        }
      } else {
        $this->peg_currPos = $s3;
        $s3 = $this->peg_FAILED;
      }
      while ($s3 !== $this->peg_FAILED) {
        $s2[] = $s3;
        $s3 = $this->peg_currPos;
        $s4 = $this->peg_currPos;
        $this->peg_silentFails++;
        $s5 = $this->peg_parseBlock();
        $this->peg_silentFails--;
        if ($s5 === $this->peg_FAILED) {
          $s4 = null;
        } else {
          $this->peg_currPos = $s4;
          $s4 = $this->peg_FAILED;
        }
        if ($s4 !== $this->peg_FAILED) {
          if ($this->input_length > $this->peg_currPos) {
            $s5 = $this->input_substr($this->peg_currPos, 1);
            $this->peg_currPos++;
          } else {
            $s5 = $this->peg_FAILED;
            if ($this->peg_silentFails === 0) {
                $this->peg_fail($this->peg_c0);
            }
          }
          if ($s5 !== $this->peg_FAILED) {
            $s4 = array($s4, $s5);
            $s3 = $s4;
          } else {
            $this->peg_currPos = $s3;
            $s3 = $this->peg_FAILED;
          }
        } else {
          $this->peg_currPos = $s3;
          $s3 = $this->peg_FAILED;
        }
      }
      if ($s2 !== $this->peg_FAILED) {
        $s1 = $this->input_substr($s1, $this->peg_currPos - $s1);
      } else {
        $s1 = $s2;
      }
      if ($s1 !== $this->peg_FAILED) {
        $s2 = array();
        $s3 = $this->peg_currPos;
        $s4 = $this->peg_parseBlock();
        if ($s4 !== $this->peg_FAILED) {
          $s5 = $this->peg_currPos;
          $s6 = array();
          $s7 = $this->peg_currPos;
          $s8 = $this->peg_currPos;
          $this->peg_silentFails++;
          $s9 = $this->peg_parseBlock();
          $this->peg_silentFails--;
          if ($s9 === $this->peg_FAILED) {
            $s8 = null;
          } else {
            $this->peg_currPos = $s8;
            $s8 = $this->peg_FAILED;
          }
          if ($s8 !== $this->peg_FAILED) {
            if ($this->input_length > $this->peg_currPos) {
              $s9 = $this->input_substr($this->peg_currPos, 1);
              $this->peg_currPos++;
            } else {
              $s9 = $this->peg_FAILED;
              if ($this->peg_silentFails === 0) {
                  $this->peg_fail($this->peg_c0);
              }
            }
            if ($s9 !== $this->peg_FAILED) {
              $s8 = array($s8, $s9);
              $s7 = $s8;
            } else {
              $this->peg_currPos = $s7;
              $s7 = $this->peg_FAILED;
            }
          } else {
            $this->peg_currPos = $s7;
            $s7 = $this->peg_FAILED;
          }
          while ($s7 !== $this->peg_FAILED) {
            $s6[] = $s7;
            $s7 = $this->peg_currPos;
            $s8 = $this->peg_currPos;
            $this->peg_silentFails++;
            $s9 = $this->peg_parseBlock();
            $this->peg_silentFails--;
            if ($s9 === $this->peg_FAILED) {
              $s8 = null;
            } else {
              $this->peg_currPos = $s8;
              $s8 = $this->peg_FAILED;
            }
            if ($s8 !== $this->peg_FAILED) {
              if ($this->input_length > $this->peg_currPos) {
                $s9 = $this->input_substr($this->peg_currPos, 1);
                $this->peg_currPos++;
              } else {
                $s9 = $this->peg_FAILED;
                if ($this->peg_silentFails === 0) {
                    $this->peg_fail($this->peg_c0);
                }
              }
              if ($s9 !== $this->peg_FAILED) {
                $s8 = array($s8, $s9);
                $s7 = $s8;
              } else {
                $this->peg_currPos = $s7;
                $s7 = $this->peg_FAILED;
              }
            } else {
              $this->peg_currPos = $s7;
              $s7 = $this->peg_FAILED;
            }
          }
          if ($s6 !== $this->peg_FAILED) {
            $s5 = $this->input_substr($s5, $this->peg_currPos - $s5);
          } else {
            $s5 = $s6;
          }
          if ($s5 !== $this->peg_FAILED) {
            $this->peg_reportedPos = $s3;
            $s4 = $this->peg_f0($s1, $s4, $s5);
            $s3 = $s4;
          } else {
            $this->peg_currPos = $s3;
            $s3 = $this->peg_FAILED;
          }
        } else {
          $this->peg_currPos = $s3;
          $s3 = $this->peg_FAILED;
        }
        while ($s3 !== $this->peg_FAILED) {
          $s2[] = $s3;
          $s3 = $this->peg_currPos;
          $s4 = $this->peg_parseBlock();
          if ($s4 !== $this->peg_FAILED) {
            $s5 = $this->peg_currPos;
            $s6 = array();
            $s7 = $this->peg_currPos;
            $s8 = $this->peg_currPos;
            $this->peg_silentFails++;
            $s9 = $this->peg_parseBlock();
            $this->peg_silentFails--;
            if ($s9 === $this->peg_FAILED) {
              $s8 = null;
            } else {
              $this->peg_currPos = $s8;
              $s8 = $this->peg_FAILED;
            }
            if ($s8 !== $this->peg_FAILED) {
              if ($this->input_length > $this->peg_currPos) {
                $s9 = $this->input_substr($this->peg_currPos, 1);
                $this->peg_currPos++;
              } else {
                $s9 = $this->peg_FAILED;
                if ($this->peg_silentFails === 0) {
                    $this->peg_fail($this->peg_c0);
                }
              }
              if ($s9 !== $this->peg_FAILED) {
                $s8 = array($s8, $s9);
                $s7 = $s8;
              } else {
                $this->peg_currPos = $s7;
                $s7 = $this->peg_FAILED;
              }
            } else {
              $this->peg_currPos = $s7;
              $s7 = $this->peg_FAILED;
            }
            while ($s7 !== $this->peg_FAILED) {
              $s6[] = $s7;
              $s7 = $this->peg_currPos;
              $s8 = $this->peg_currPos;
              $this->peg_silentFails++;
              $s9 = $this->peg_parseBlock();
              $this->peg_silentFails--;
              if ($s9 === $this->peg_FAILED) {
                $s8 = null;
              } else {
                $this->peg_currPos = $s8;
                $s8 = $this->peg_FAILED;
              }
              if ($s8 !== $this->peg_FAILED) {
                if ($this->input_length > $this->peg_currPos) {
                  $s9 = $this->input_substr($this->peg_currPos, 1);
                  $this->peg_currPos++;
                } else {
                  $s9 = $this->peg_FAILED;
                  if ($this->peg_silentFails === 0) {
                      $this->peg_fail($this->peg_c0);
                  }
                }
                if ($s9 !== $this->peg_FAILED) {
                  $s8 = array($s8, $s9);
                  $s7 = $s8;
                } else {
                  $this->peg_currPos = $s7;
                  $s7 = $this->peg_FAILED;
                }
              } else {
                $this->peg_currPos = $s7;
                $s7 = $this->peg_FAILED;
              }
            }
            if ($s6 !== $this->peg_FAILED) {
              $s5 = $this->input_substr($s5, $this->peg_currPos - $s5);
            } else {
              $s5 = $s6;
            }
            if ($s5 !== $this->peg_FAILED) {
              $this->peg_reportedPos = $s3;
              $s4 = $this->peg_f0($s1, $s4, $s5);
              $s3 = $s4;
            } else {
              $this->peg_currPos = $s3;
              $s3 = $this->peg_FAILED;
            }
          } else {
            $this->peg_currPos = $s3;
            $s3 = $this->peg_FAILED;
          }
        }
        if ($s2 !== $this->peg_FAILED) {
          $s3 = $this->peg_currPos;
          $s4 = array();
          if ($this->input_length > $this->peg_currPos) {
            $s5 = $this->input_substr($this->peg_currPos, 1);
            $this->peg_currPos++;
          } else {
            $s5 = $this->peg_FAILED;
            if ($this->peg_silentFails === 0) {
                $this->peg_fail($this->peg_c0);
            }
          }
          while ($s5 !== $this->peg_FAILED) {
            $s4[] = $s5;
            if ($this->input_length > $this->peg_currPos) {
              $s5 = $this->input_substr($this->peg_currPos, 1);
              $this->peg_currPos++;
            } else {
              $s5 = $this->peg_FAILED;
              if ($this->peg_silentFails === 0) {
                  $this->peg_fail($this->peg_c0);
              }
            }
          }
          if ($s4 !== $this->peg_FAILED) {
            $s3 = $this->input_substr($s3, $this->peg_currPos - $s3);
          } else {
            $s3 = $s4;
          }
          if ($s3 !== $this->peg_FAILED) {
            $this->peg_reportedPos = $s0;
            $s1 = $this->peg_f1($s1, $s2, $s3);
            $s0 = $s1;
          } else {
            $this->peg_currPos = $s0;
            $s0 = $this->peg_FAILED;
          }
        } else {
          $this->peg_currPos = $s0;
          $s0 = $this->peg_FAILED;
        }
      } else {
        $this->peg_currPos = $s0;
        $s0 = $this->peg_FAILED;
      }

      return $s0;
    }

    private function peg_parseBlock() {

      $s0 = $this->peg_parseBlock_Void();
      if ($s0 === $this->peg_FAILED) {
        $s0 = $this->peg_parseBlock_Balanced();
      }

      return $s0;
    }

    private function peg_parseBlock_Void() {

      $s0 = $this->peg_currPos;
      if ($this->input_substr($this->peg_currPos, 4) === $this->peg_c1) {
        $s1 = $this->peg_c1;
        $this->peg_currPos += 4;
      } else {
        $s1 = $this->peg_FAILED;
        if ($this->peg_silentFails === 0) {
            $this->peg_fail($this->peg_c2);
        }
      }
      if ($s1 !== $this->peg_FAILED) {
        $s2 = $this->peg_parse__();
        if ($s2 !== $this->peg_FAILED) {
          if ($this->input_substr($this->peg_currPos, 3) === $this->peg_c3) {
            $s3 = $this->peg_c3;
            $this->peg_currPos += 3;
          } else {
            $s3 = $this->peg_FAILED;
            if ($this->peg_silentFails === 0) {
                $this->peg_fail($this->peg_c4);
            }
          }
          if ($s3 !== $this->peg_FAILED) {
            $s4 = $this->peg_parseBlock_Name();
            if ($s4 !== $this->peg_FAILED) {
              $s5 = $this->peg_parse__();
              if ($s5 !== $this->peg_FAILED) {
                $s6 = $this->peg_currPos;
                $s7 = $this->peg_parseBlock_Attributes();
                if ($s7 !== $this->peg_FAILED) {
                  $s8 = $this->peg_parse__();
                  if ($s8 !== $this->peg_FAILED) {
                    $this->peg_reportedPos = $s6;
                    $s7 = $this->peg_f2($s4, $s7);
                    $s6 = $s7;
                  } else {
                    $this->peg_currPos = $s6;
                    $s6 = $this->peg_FAILED;
                  }
                } else {
                  $this->peg_currPos = $s6;
                  $s6 = $this->peg_FAILED;
                }
                if ($s6 === $this->peg_FAILED) {
                  $s6 = null;
                }
                if ($s6 !== $this->peg_FAILED) {
                  if ($this->input_substr($this->peg_currPos, 4) === $this->peg_c5) {
                    $s7 = $this->peg_c5;
                    $this->peg_currPos += 4;
                  } else {
                    $s7 = $this->peg_FAILED;
                    if ($this->peg_silentFails === 0) {
                        $this->peg_fail($this->peg_c6);
                    }
                  }
                  if ($s7 !== $this->peg_FAILED) {
                    $this->peg_reportedPos = $s0;
                    $s1 = $this->peg_f3($s4, $s6);
                    $s0 = $s1;
                  } else {
                    $this->peg_currPos = $s0;
                    $s0 = $this->peg_FAILED;
                  }
                } else {
                  $this->peg_currPos = $s0;
                  $s0 = $this->peg_FAILED;
                }
              } else {
                $this->peg_currPos = $s0;
                $s0 = $this->peg_FAILED;
              }
            } else {
              $this->peg_currPos = $s0;
              $s0 = $this->peg_FAILED;
            }
          } else {
            $this->peg_currPos = $s0;
            $s0 = $this->peg_FAILED;
          }
        } else {
          $this->peg_currPos = $s0;
          $s0 = $this->peg_FAILED;
        }
      } else {
        $this->peg_currPos = $s0;
        $s0 = $this->peg_FAILED;
      }

      return $s0;
    }

    private function peg_parseBlock_Balanced() {

      $s0 = $this->peg_currPos;
      $s1 = $this->peg_parseBlock_Start();
      if ($s1 !== $this->peg_FAILED) {
        $s2 = array();
        $s3 = $this->peg_parseBlock();
        if ($s3 === $this->peg_FAILED) {
          $s3 = $this->peg_currPos;
          $s4 = $this->peg_currPos;
          $s5 = $this->peg_currPos;
          $this->peg_silentFails++;
          $s6 = $this->peg_parseBlock_End();
          $this->peg_silentFails--;
          if ($s6 === $this->peg_FAILED) {
            $s5 = null;
          } else {
            $this->peg_currPos = $s5;
            $s5 = $this->peg_FAILED;
          }
          if ($s5 !== $this->peg_FAILED) {
            if ($this->input_length > $this->peg_currPos) {
              $s6 = $this->input_substr($this->peg_currPos, 1);
              $this->peg_currPos++;
            } else {
              $s6 = $this->peg_FAILED;
              if ($this->peg_silentFails === 0) {
                  $this->peg_fail($this->peg_c0);
              }
            }
            if ($s6 !== $this->peg_FAILED) {
              $s5 = array($s5, $s6);
              $s4 = $s5;
            } else {
              $this->peg_currPos = $s4;
              $s4 = $this->peg_FAILED;
            }
          } else {
            $this->peg_currPos = $s4;
            $s4 = $this->peg_FAILED;
          }
          if ($s4 !== $this->peg_FAILED) {
            $s3 = $this->input_substr($s3, $this->peg_currPos - $s3);
          } else {
            $s3 = $s4;
          }
        }
        while ($s3 !== $this->peg_FAILED) {
          $s2[] = $s3;
          $s3 = $this->peg_parseBlock();
          if ($s3 === $this->peg_FAILED) {
            $s3 = $this->peg_currPos;
            $s4 = $this->peg_currPos;
            $s5 = $this->peg_currPos;
            $this->peg_silentFails++;
            $s6 = $this->peg_parseBlock_End();
            $this->peg_silentFails--;
            if ($s6 === $this->peg_FAILED) {
              $s5 = null;
            } else {
              $this->peg_currPos = $s5;
              $s5 = $this->peg_FAILED;
            }
            if ($s5 !== $this->peg_FAILED) {
              if ($this->input_length > $this->peg_currPos) {
                $s6 = $this->input_substr($this->peg_currPos, 1);
                $this->peg_currPos++;
              } else {
                $s6 = $this->peg_FAILED;
                if ($this->peg_silentFails === 0) {
                    $this->peg_fail($this->peg_c0);
                }
              }
              if ($s6 !== $this->peg_FAILED) {
                $s5 = array($s5, $s6);
                $s4 = $s5;
              } else {
                $this->peg_currPos = $s4;
                $s4 = $this->peg_FAILED;
              }
            } else {
              $this->peg_currPos = $s4;
              $s4 = $this->peg_FAILED;
            }
            if ($s4 !== $this->peg_FAILED) {
              $s3 = $this->input_substr($s3, $this->peg_currPos - $s3);
            } else {
              $s3 = $s4;
            }
          }
        }
        if ($s2 !== $this->peg_FAILED) {
          $s3 = $this->peg_parseBlock_End();
          if ($s3 !== $this->peg_FAILED) {
            $this->peg_reportedPos = $s0;
            $s1 = $this->peg_f4($s1, $s2, $s3);
            $s0 = $s1;
          } else {
            $this->peg_currPos = $s0;
            $s0 = $this->peg_FAILED;
          }
        } else {
          $this->peg_currPos = $s0;
          $s0 = $this->peg_FAILED;
        }
      } else {
        $this->peg_currPos = $s0;
        $s0 = $this->peg_FAILED;
      }

      return $s0;
    }

    private function peg_parseBlock_Start() {

      $s0 = $this->peg_currPos;
      if ($this->input_substr($this->peg_currPos, 4) === $this->peg_c1) {
        $s1 = $this->peg_c1;
        $this->peg_currPos += 4;
      } else {
        $s1 = $this->peg_FAILED;
        if ($this->peg_silentFails === 0) {
            $this->peg_fail($this->peg_c2);
        }
      }
      if ($s1 !== $this->peg_FAILED) {
        $s2 = $this->peg_parse__();
        if ($s2 !== $this->peg_FAILED) {
          if ($this->input_substr($this->peg_currPos, 3) === $this->peg_c3) {
            $s3 = $this->peg_c3;
            $this->peg_currPos += 3;
          } else {
            $s3 = $this->peg_FAILED;
            if ($this->peg_silentFails === 0) {
                $this->peg_fail($this->peg_c4);
            }
          }
          if ($s3 !== $this->peg_FAILED) {
            $s4 = $this->peg_parseBlock_Name();
            if ($s4 !== $this->peg_FAILED) {
              $s5 = $this->peg_parse__();
              if ($s5 !== $this->peg_FAILED) {
                $s6 = $this->peg_currPos;
                $s7 = $this->peg_parseBlock_Attributes();
                if ($s7 !== $this->peg_FAILED) {
                  $s8 = $this->peg_parse__();
                  if ($s8 !== $this->peg_FAILED) {
                    $this->peg_reportedPos = $s6;
                    $s7 = $this->peg_f2($s4, $s7);
                    $s6 = $s7;
                  } else {
                    $this->peg_currPos = $s6;
                    $s6 = $this->peg_FAILED;
                  }
                } else {
                  $this->peg_currPos = $s6;
                  $s6 = $this->peg_FAILED;
                }
                if ($s6 === $this->peg_FAILED) {
                  $s6 = null;
                }
                if ($s6 !== $this->peg_FAILED) {
                  if ($this->input_substr($this->peg_currPos, 3) === $this->peg_c7) {
                    $s7 = $this->peg_c7;
                    $this->peg_currPos += 3;
                  } else {
                    $s7 = $this->peg_FAILED;
                    if ($this->peg_silentFails === 0) {
                        $this->peg_fail($this->peg_c8);
                    }
                  }
                  if ($s7 !== $this->peg_FAILED) {
                    $this->peg_reportedPos = $s0;
                    $s1 = $this->peg_f5($s4, $s6);
                    $s0 = $s1;
                  } else {
                    $this->peg_currPos = $s0;
                    $s0 = $this->peg_FAILED;
                  }
                } else {
                  $this->peg_currPos = $s0;
                  $s0 = $this->peg_FAILED;
                }
              } else {
                $this->peg_currPos = $s0;
                $s0 = $this->peg_FAILED;
              }
            } else {
              $this->peg_currPos = $s0;
              $s0 = $this->peg_FAILED;
            }
          } else {
            $this->peg_currPos = $s0;
            $s0 = $this->peg_FAILED;
          }
        } else {
          $this->peg_currPos = $s0;
          $s0 = $this->peg_FAILED;
        }
      } else {
        $this->peg_currPos = $s0;
        $s0 = $this->peg_FAILED;
      }

      return $s0;
    }

    private function peg_parseBlock_End() {

      $s0 = $this->peg_currPos;
      if ($this->input_substr($this->peg_currPos, 4) === $this->peg_c1) {
        $s1 = $this->peg_c1;
        $this->peg_currPos += 4;
      } else {
        $s1 = $this->peg_FAILED;
        if ($this->peg_silentFails === 0) {
            $this->peg_fail($this->peg_c2);
        }
      }
      if ($s1 !== $this->peg_FAILED) {
        $s2 = $this->peg_parse__();
        if ($s2 !== $this->peg_FAILED) {
          if ($this->input_substr($this->peg_currPos, 4) === $this->peg_c9) {
            $s3 = $this->peg_c9;
            $this->peg_currPos += 4;
          } else {
            $s3 = $this->peg_FAILED;
            if ($this->peg_silentFails === 0) {
                $this->peg_fail($this->peg_c10);
            }
          }
          if ($s3 !== $this->peg_FAILED) {
            $s4 = $this->peg_parseBlock_Name();
            if ($s4 !== $this->peg_FAILED) {
              $s5 = $this->peg_parse__();
              if ($s5 !== $this->peg_FAILED) {
                if ($this->input_substr($this->peg_currPos, 3) === $this->peg_c7) {
                  $s6 = $this->peg_c7;
                  $this->peg_currPos += 3;
                } else {
                  $s6 = $this->peg_FAILED;
                  if ($this->peg_silentFails === 0) {
                      $this->peg_fail($this->peg_c8);
                  }
                }
                if ($s6 !== $this->peg_FAILED) {
                  $this->peg_reportedPos = $s0;
                  $s1 = $this->peg_f6($s4);
                  $s0 = $s1;
                } else {
                  $this->peg_currPos = $s0;
                  $s0 = $this->peg_FAILED;
                }
              } else {
                $this->peg_currPos = $s0;
                $s0 = $this->peg_FAILED;
              }
            } else {
              $this->peg_currPos = $s0;
              $s0 = $this->peg_FAILED;
            }
          } else {
            $this->peg_currPos = $s0;
            $s0 = $this->peg_FAILED;
          }
        } else {
          $this->peg_currPos = $s0;
          $s0 = $this->peg_FAILED;
        }
      } else {
        $this->peg_currPos = $s0;
        $s0 = $this->peg_FAILED;
      }

      return $s0;
    }

    private function peg_parseBlock_Name() {

      $s0 = $this->peg_parseNamespaced_Block_Name();
      if ($s0 === $this->peg_FAILED) {
        $s0 = $this->peg_parseCore_Block_Name();
      }

      return $s0;
    }

    private function peg_parseNamespaced_Block_Name() {

      $s0 = $this->peg_currPos;
      $s1 = $this->peg_currPos;
      $s2 = $this->peg_parseBlock_Name_Part();
      if ($s2 !== $this->peg_FAILED) {
        if ($this->input_substr($this->peg_currPos, 1) === $this->peg_c11) {
          $s3 = $this->peg_c11;
          $this->peg_currPos++;
        } else {
          $s3 = $this->peg_FAILED;
          if ($this->peg_silentFails === 0) {
              $this->peg_fail($this->peg_c12);
          }
        }
        if ($s3 !== $this->peg_FAILED) {
          $s4 = $this->peg_parseBlock_Name_Part();
          if ($s4 !== $this->peg_FAILED) {
            $s2 = array($s2, $s3, $s4);
            $s1 = $s2;
          } else {
            $this->peg_currPos = $s1;
            $s1 = $this->peg_FAILED;
          }
        } else {
          $this->peg_currPos = $s1;
          $s1 = $this->peg_FAILED;
        }
      } else {
        $this->peg_currPos = $s1;
        $s1 = $this->peg_FAILED;
      }
      if ($s1 !== $this->peg_FAILED) {
        $s0 = $this->input_substr($s0, $this->peg_currPos - $s0);
      } else {
        $s0 = $s1;
      }

      return $s0;
    }

    private function peg_parseCore_Block_Name() {

      $s0 = $this->peg_currPos;
      $s1 = $this->peg_currPos;
      $s2 = $this->peg_parseBlock_Name_Part();
      if ($s2 !== $this->peg_FAILED) {
        $s1 = $this->input_substr($s1, $this->peg_currPos - $s1);
      } else {
        $s1 = $s2;
      }
      if ($s1 !== $this->peg_FAILED) {
        $this->peg_reportedPos = $s0;
        $s1 = $this->peg_f7($s1);
      }
      $s0 = $s1;

      return $s0;
    }

    private function peg_parseBlock_Name_Part() {

      $s0 = $this->peg_currPos;
      $s1 = $this->peg_currPos;
      if (Gutenberg_PEG_peg_char_class_test($this->peg_c13, $this->input_substr($this->peg_currPos, 1))) {
        $s2 = $this->input_substr($this->peg_currPos, 1);
        $this->peg_currPos++;
      } else {
        $s2 = $this->peg_FAILED;
        if ($this->peg_silentFails === 0) {
            $this->peg_fail($this->peg_c14);
        }
      }
      if ($s2 !== $this->peg_FAILED) {
        $s3 = array();
        if (Gutenberg_PEG_peg_char_class_test($this->peg_c15, $this->input_substr($this->peg_currPos, 1))) {
          $s4 = $this->input_substr($this->peg_currPos, 1);
          $this->peg_currPos++;
        } else {
          $s4 = $this->peg_FAILED;
          if ($this->peg_silentFails === 0) {
              $this->peg_fail($this->peg_c16);
          }
        }
        while ($s4 !== $this->peg_FAILED) {
          $s3[] = $s4;
          if (Gutenberg_PEG_peg_char_class_test($this->peg_c15, $this->input_substr($this->peg_currPos, 1))) {
            $s4 = $this->input_substr($this->peg_currPos, 1);
            $this->peg_currPos++;
          } else {
            $s4 = $this->peg_FAILED;
            if ($this->peg_silentFails === 0) {
                $this->peg_fail($this->peg_c16);
            }
          }
        }
        if ($s3 !== $this->peg_FAILED) {
          $s2 = array($s2, $s3);
          $s1 = $s2;
        } else {
          $this->peg_currPos = $s1;
          $s1 = $this->peg_FAILED;
        }
      } else {
        $this->peg_currPos = $s1;
        $s1 = $this->peg_FAILED;
      }
      if ($s1 !== $this->peg_FAILED) {
        $s0 = $this->input_substr($s0, $this->peg_currPos - $s0);
      } else {
        $s0 = $s1;
      }

      return $s0;
    }

    private function peg_parseBlock_Attributes() {

      $s0 = $this->peg_currPos;
      $s1 = $this->peg_currPos;
      $s2 = $this->peg_currPos;
      if ($this->input_substr($this->peg_currPos, 1) === $this->peg_c17) {
        $s3 = $this->peg_c17;
        $this->peg_currPos++;
      } else {
        $s3 = $this->peg_FAILED;
        if ($this->peg_silentFails === 0) {
            $this->peg_fail($this->peg_c18);
        }
      }
      if ($s3 !== $this->peg_FAILED) {
        $s4 = array();
        $s5 = $this->peg_currPos;
        $s6 = $this->peg_currPos;
        $this->peg_silentFails++;
        $s7 = $this->peg_currPos;
        if ($this->input_substr($this->peg_currPos, 1) === $this->peg_c19) {
          $s8 = $this->peg_c19;
          $this->peg_currPos++;
        } else {
          $s8 = $this->peg_FAILED;
          if ($this->peg_silentFails === 0) {
              $this->peg_fail($this->peg_c20);
          }
        }
        if ($s8 !== $this->peg_FAILED) {
          $s9 = $this->peg_parse__();
          if ($s9 !== $this->peg_FAILED) {
            $s10 = $this->peg_c21;
            if ($s10 !== $this->peg_FAILED) {
              if ($this->input_substr($this->peg_currPos, 1) === $this->peg_c11) {
                $s11 = $this->peg_c11;
                $this->peg_currPos++;
              } else {
                $s11 = $this->peg_FAILED;
                if ($this->peg_silentFails === 0) {
                    $this->peg_fail($this->peg_c12);
                }
              }
              if ($s11 === $this->peg_FAILED) {
                $s11 = null;
              }
              if ($s11 !== $this->peg_FAILED) {
                if ($this->input_substr($this->peg_currPos, 3) === $this->peg_c7) {
                  $s12 = $this->peg_c7;
                  $this->peg_currPos += 3;
                } else {
                  $s12 = $this->peg_FAILED;
                  if ($this->peg_silentFails === 0) {
                      $this->peg_fail($this->peg_c8);
                  }
                }
                if ($s12 !== $this->peg_FAILED) {
                  $s8 = array($s8, $s9, $s10, $s11, $s12);
                  $s7 = $s8;
                } else {
                  $this->peg_currPos = $s7;
                  $s7 = $this->peg_FAILED;
                }
              } else {
                $this->peg_currPos = $s7;
                $s7 = $this->peg_FAILED;
              }
            } else {
              $this->peg_currPos = $s7;
              $s7 = $this->peg_FAILED;
            }
          } else {
            $this->peg_currPos = $s7;
            $s7 = $this->peg_FAILED;
          }
        } else {
          $this->peg_currPos = $s7;
          $s7 = $this->peg_FAILED;
        }
        $this->peg_silentFails--;
        if ($s7 === $this->peg_FAILED) {
          $s6 = null;
        } else {
          $this->peg_currPos = $s6;
          $s6 = $this->peg_FAILED;
        }
        if ($s6 !== $this->peg_FAILED) {
          if ($this->input_length > $this->peg_currPos) {
            $s7 = $this->input_substr($this->peg_currPos, 1);
            $this->peg_currPos++;
          } else {
            $s7 = $this->peg_FAILED;
            if ($this->peg_silentFails === 0) {
                $this->peg_fail($this->peg_c0);
            }
          }
          if ($s7 !== $this->peg_FAILED) {
            $s6 = array($s6, $s7);
            $s5 = $s6;
          } else {
            $this->peg_currPos = $s5;
            $s5 = $this->peg_FAILED;
          }
        } else {
          $this->peg_currPos = $s5;
          $s5 = $this->peg_FAILED;
        }
        while ($s5 !== $this->peg_FAILED) {
          $s4[] = $s5;
          $s5 = $this->peg_currPos;
          $s6 = $this->peg_currPos;
          $this->peg_silentFails++;
          $s7 = $this->peg_currPos;
          if ($this->input_substr($this->peg_currPos, 1) === $this->peg_c19) {
            $s8 = $this->peg_c19;
            $this->peg_currPos++;
          } else {
            $s8 = $this->peg_FAILED;
            if ($this->peg_silentFails === 0) {
                $this->peg_fail($this->peg_c20);
            }
          }
          if ($s8 !== $this->peg_FAILED) {
            $s9 = $this->peg_parse__();
            if ($s9 !== $this->peg_FAILED) {
              $s10 = $this->peg_c21;
              if ($s10 !== $this->peg_FAILED) {
                if ($this->input_substr($this->peg_currPos, 1) === $this->peg_c11) {
                  $s11 = $this->peg_c11;
                  $this->peg_currPos++;
                } else {
                  $s11 = $this->peg_FAILED;
                  if ($this->peg_silentFails === 0) {
                      $this->peg_fail($this->peg_c12);
                  }
                }
                if ($s11 === $this->peg_FAILED) {
                  $s11 = null;
                }
                if ($s11 !== $this->peg_FAILED) {
                  if ($this->input_substr($this->peg_currPos, 3) === $this->peg_c7) {
                    $s12 = $this->peg_c7;
                    $this->peg_currPos += 3;
                  } else {
                    $s12 = $this->peg_FAILED;
                    if ($this->peg_silentFails === 0) {
                        $this->peg_fail($this->peg_c8);
                    }
                  }
                  if ($s12 !== $this->peg_FAILED) {
                    $s8 = array($s8, $s9, $s10, $s11, $s12);
                    $s7 = $s8;
                  } else {
                    $this->peg_currPos = $s7;
                    $s7 = $this->peg_FAILED;
                  }
                } else {
                  $this->peg_currPos = $s7;
                  $s7 = $this->peg_FAILED;
                }
              } else {
                $this->peg_currPos = $s7;
                $s7 = $this->peg_FAILED;
              }
            } else {
              $this->peg_currPos = $s7;
              $s7 = $this->peg_FAILED;
            }
          } else {
            $this->peg_currPos = $s7;
            $s7 = $this->peg_FAILED;
          }
          $this->peg_silentFails--;
          if ($s7 === $this->peg_FAILED) {
            $s6 = null;
          } else {
            $this->peg_currPos = $s6;
            $s6 = $this->peg_FAILED;
          }
          if ($s6 !== $this->peg_FAILED) {
            if ($this->input_length > $this->peg_currPos) {
              $s7 = $this->input_substr($this->peg_currPos, 1);
              $this->peg_currPos++;
            } else {
              $s7 = $this->peg_FAILED;
              if ($this->peg_silentFails === 0) {
                  $this->peg_fail($this->peg_c0);
              }
            }
            if ($s7 !== $this->peg_FAILED) {
              $s6 = array($s6, $s7);
              $s5 = $s6;
            } else {
              $this->peg_currPos = $s5;
              $s5 = $this->peg_FAILED;
            }
          } else {
            $this->peg_currPos = $s5;
            $s5 = $this->peg_FAILED;
          }
        }
        if ($s4 !== $this->peg_FAILED) {
          if ($this->input_substr($this->peg_currPos, 1) === $this->peg_c19) {
            $s5 = $this->peg_c19;
            $this->peg_currPos++;
          } else {
            $s5 = $this->peg_FAILED;
            if ($this->peg_silentFails === 0) {
                $this->peg_fail($this->peg_c20);
            }
          }
          if ($s5 !== $this->peg_FAILED) {
            $s3 = array($s3, $s4, $s5);
            $s2 = $s3;
          } else {
            $this->peg_currPos = $s2;
            $s2 = $this->peg_FAILED;
          }
        } else {
          $this->peg_currPos = $s2;
          $s2 = $this->peg_FAILED;
        }
      } else {
        $this->peg_currPos = $s2;
        $s2 = $this->peg_FAILED;
      }
      if ($s2 !== $this->peg_FAILED) {
        $s1 = $this->input_substr($s1, $this->peg_currPos - $s1);
      } else {
        $s1 = $s2;
      }
      if ($s1 !== $this->peg_FAILED) {
        $this->peg_reportedPos = $s0;
        $s1 = $this->peg_f8($s1);
      }
      $s0 = $s1;

      return $s0;
    }

    private function peg_parse__() {

      $s0 = array();
      if (Gutenberg_PEG_peg_char_class_test($this->peg_c22, $this->input_substr($this->peg_currPos, 1))) {
        $s1 = $this->input_substr($this->peg_currPos, 1);
        $this->peg_currPos++;
      } else {
        $s1 = $this->peg_FAILED;
        if ($this->peg_silentFails === 0) {
            $this->peg_fail($this->peg_c23);
        }
      }
      if ($s1 !== $this->peg_FAILED) {
        while ($s1 !== $this->peg_FAILED) {
          $s0[] = $s1;
          if (Gutenberg_PEG_peg_char_class_test($this->peg_c22, $this->input_substr($this->peg_currPos, 1))) {
            $s1 = $this->input_substr($this->peg_currPos, 1);
            $this->peg_currPos++;
          } else {
            $s1 = $this->peg_FAILED;
            if ($this->peg_silentFails === 0) {
                $this->peg_fail($this->peg_c23);
            }
          }
        }
      } else {
        $s0 = $this->peg_FAILED;
      }

      return $s0;
    }

  public function parse($input) {
    $arguments = func_get_args();
    $options = count($arguments) > 1 ? $arguments[1] : array();
    $this->cleanup_state();

    if (is_array($input)) {
        $this->input = $input;
    } else {
        preg_match_all("/./us", $input, $match);
        $this->input = $match[0];
    }
    $this->input_length = count($this->input);

    $this->peg_FAILED = new stdClass;
    $this->peg_c0 = array("type" => "any", "description" => "any character" );
    $this->peg_c1 = "<!--";
    $this->peg_c2 = array( "type" => "literal", "value" => "<!--", "description" => "\"<!--\"" );
    $this->peg_c3 = "wp:";
    $this->peg_c4 = array( "type" => "literal", "value" => "wp:", "description" => "\"wp:\"" );
    $this->peg_c5 = "/-->";
    $this->peg_c6 = array( "type" => "literal", "value" => "/-->", "description" => "\"/-->\"" );
    $this->peg_c7 = "-->";
    $this->peg_c8 = array( "type" => "literal", "value" => "-->", "description" => "\"-->\"" );
    $this->peg_c9 = "/wp:";
    $this->peg_c10 = array( "type" => "literal", "value" => "/wp:", "description" => "\"/wp:\"" );
    $this->peg_c11 = "/";
    $this->peg_c12 = array( "type" => "literal", "value" => "/", "description" => "\"/\"" );
    $this->peg_c13 = array(array(97,122));
    $this->peg_c14 = array( "type" => "class", "value" => "[a-z]", "description" => "[a-z]" );
    $this->peg_c15 = array(array(97,122), array(48,57), array(95,95), array(45,45));
    $this->peg_c16 = array( "type" => "class", "value" => "[a-z0-9_-]", "description" => "[a-z0-9_-]" );
    $this->peg_c17 = "{";
    $this->peg_c18 = array( "type" => "literal", "value" => "{", "description" => "\"{\"" );
    $this->peg_c19 = "}";
    $this->peg_c20 = array( "type" => "literal", "value" => "}", "description" => "\"}\"" );
    $this->peg_c21 = "";
    $this->peg_c22 = array(array(32,32), array(9,9), array(13,13), array(10,10));
    $this->peg_c23 = array( "type" => "class", "value" => "[ \t\r\n]", "description" => "[ \t\r\n]" );

    $peg_startRuleFunctions = array( 'Block_List' => array($this, "peg_parseBlock_List") );
    $peg_startRuleFunction  = array($this, "peg_parseBlock_List");
    if (isset($options["startRule"])) {
      if (!(isset($peg_startRuleFunctions[$options["startRule"]]))) {
        throw new Exception("Can't start parsing from rule \"" + $options["startRule"] + "\".");
      }

      $peg_startRuleFunction = $peg_startRuleFunctions[$options["startRule"]];
    }

    /* BEGIN initializer code */

    // The `maybeJSON` function is not needed in PHP because its return semantics
    // are the same as `json_decode`

    // array arguments are backwards because of PHP
    if ( ! function_exists( 'peg_array_partition' ) ) {
        function peg_array_partition( $array, $predicate ) {
            $truthy = array();
            $falsey = array();

            foreach ( $array as $item ) {
                call_user_func( $predicate, $item )
                    ? $truthy[] = $item
                    : $falsey[] = $item;
            }

            return array( $truthy, $falsey );
        }
    }

    if ( ! function_exists( 'peg_join_blocks' ) ) {
        function peg_join_blocks( $pre, $tokens, $post ) {
            $blocks = array();

            if ( ! empty( $pre ) ) {
                $blocks[] = array( 'attrs' => array(), 'innerHTML' => $pre );
            }

            foreach ( $tokens as $token ) {
                list( $token, $html ) = $token;

                $blocks[] = $token;

                if ( ! empty( $html ) ) {
                    $blocks[] = array( 'attrs' => array(), 'innerHTML' => $html );
                }
            }

            if ( ! empty( $post ) ) {
                $blocks[] = array( 'attrs' => array(), 'innerHTML' => $post );
            }

            return $blocks;
        }
    }


    /* END initializer code */

    $peg_result = call_user_func($peg_startRuleFunction);

    if ($peg_result !== $this->peg_FAILED && $this->peg_currPos === $this->input_length) {
      $this->cleanup_state(); // Free up memory
      return $peg_result;
    } else {
      if ($peg_result !== $this->peg_FAILED && $this->peg_currPos < $this->input_length) {
        $this->peg_fail(array("type" => "end", "description" => "end of input" ));
      }

      $exception = $this->peg_buildException(null, $this->peg_maxFailExpected, $this->peg_maxFailPos);
      $this->cleanup_state(); // Free up memory
      throw $exception;
    }
  }

};