diff --git a/blocks/api/post.pegjs b/blocks/api/post.pegjs index 329c27b9e5f4a7..15635d4f1aa763 100644 --- a/blocks/api/post.pegjs +++ b/blocks/api/post.pegjs @@ -283,15 +283,18 @@ Block_Name / Core_Block_Name Namespaced_Block_Name - = $(ASCII_Letter ASCII_AlphaNumeric* "/" ASCII_Letter ASCII_AlphaNumeric*) + = $( Block_Name_Part "/" Block_Name_Part ) Core_Block_Name - = type:$(ASCII_Letter ASCII_AlphaNumeric*) + = type:$( Block_Name_Part ) { /** **/ return 'core/' + type; } +Block_Name_Part + = $( [a-z][a-z0-9_-]* ) + Block_Attributes = attrs:$("{" (!("}" WS+ """/"? "-->") .)* "}") { @@ -299,20 +302,6 @@ Block_Attributes return maybeJSON( attrs ); } -ASCII_AlphaNumeric - = ASCII_Letter - / ASCII_Digit - / Special_Chars - -ASCII_Letter - = [a-zA-Z] - -ASCII_Digit - = [0-9] - -Special_Chars - = [\-\_] - WS = [ \t\r\n] diff --git a/blocks/api/registration.js b/blocks/api/registration.js index cd7b5e546cad3e..33cc40342dd5e3 100644 --- a/blocks/api/registration.js +++ b/blocks/api/registration.js @@ -55,15 +55,9 @@ export function registerBlockType( name, settings ) { ); return; } - if ( /[A-Z]+/.test( name ) ) { + if ( ! /^[a-z][a-z0-9-]*\/[a-z][a-z0-9-]*$/.test( name ) ) { console.error( - 'Block names must not contain uppercase characters.' - ); - return; - } - if ( ! /^[a-z0-9-]+\/[a-z0-9-]+$/.test( name ) ) { - console.error( - 'Block names must contain a namespace prefix. Example: my-plugin/my-custom-block' + 'Block names must contain a namespace prefix, include only lowercase alphanumeric characters or dashes, and start with a letter. Example: my-plugin/my-custom-block' ); return; } diff --git a/blocks/api/test/registration.js b/blocks/api/test/registration.js index 6f4d1c2df161c6..a183053f04ed7f 100644 --- a/blocks/api/test/registration.js +++ b/blocks/api/test/registration.js @@ -48,25 +48,31 @@ describe( 'blocks', () => { it( 'should reject blocks without a namespace', () => { const block = registerBlockType( 'doing-it-wrong' ); - expect( console.error ).toHaveBeenCalledWith( 'Block names must contain a namespace prefix. Example: my-plugin/my-custom-block' ); + expect( console.error ).toHaveBeenCalledWith( 'Block names must contain a namespace prefix, include only lowercase alphanumeric characters or dashes, and start with a letter. Example: my-plugin/my-custom-block' ); expect( block ).toBeUndefined(); } ); it( 'should reject blocks with too many namespaces', () => { const block = registerBlockType( 'doing/it/wrong' ); - expect( console.error ).toHaveBeenCalledWith( 'Block names must contain a namespace prefix. Example: my-plugin/my-custom-block' ); + expect( console.error ).toHaveBeenCalledWith( 'Block names must contain a namespace prefix, include only lowercase alphanumeric characters or dashes, and start with a letter. Example: my-plugin/my-custom-block' ); expect( block ).toBeUndefined(); } ); it( 'should reject blocks with invalid characters', () => { const block = registerBlockType( 'still/_doing_it_wrong' ); - expect( console.error ).toHaveBeenCalledWith( 'Block names must contain a namespace prefix. Example: my-plugin/my-custom-block' ); + expect( console.error ).toHaveBeenCalledWith( 'Block names must contain a namespace prefix, include only lowercase alphanumeric characters or dashes, and start with a letter. Example: my-plugin/my-custom-block' ); expect( block ).toBeUndefined(); } ); it( 'should reject blocks with uppercase characters', () => { const block = registerBlockType( 'Core/Paragraph' ); - expect( console.error ).toHaveBeenCalledWith( 'Block names must not contain uppercase characters.' ); + expect( console.error ).toHaveBeenCalledWith( 'Block names must contain a namespace prefix, include only lowercase alphanumeric characters or dashes, and start with a letter. Example: my-plugin/my-custom-block' ); + expect( block ).toBeUndefined(); + } ); + + it( 'should reject blocks not starting with a letter', () => { + const block = registerBlockType( 'my-plugin/4-fancy-block', defaultBlockSettings ); + expect( console.error ).toHaveBeenCalledWith( 'Block names must contain a namespace prefix, include only lowercase alphanumeric characters or dashes, and start with a letter. Example: my-plugin/my-custom-block' ); expect( block ).toBeUndefined(); } ); diff --git a/blocks/test/fixtures/core__4-invalid-starting-letter.html b/blocks/test/fixtures/core__4-invalid-starting-letter.html new file mode 100644 index 00000000000000..220f8b60c8d654 --- /dev/null +++ b/blocks/test/fixtures/core__4-invalid-starting-letter.html @@ -0,0 +1 @@ + diff --git a/blocks/test/fixtures/core__4-invalid-starting-letter.json b/blocks/test/fixtures/core__4-invalid-starting-letter.json new file mode 100644 index 00000000000000..a497b39b93f989 --- /dev/null +++ b/blocks/test/fixtures/core__4-invalid-starting-letter.json @@ -0,0 +1,11 @@ +[ + { + "uid": "_uid_0", + "name": "core/freeform", + "isValid": true, + "attributes": { + "content": "" + }, + "originalContent": "" + } +] diff --git a/blocks/test/fixtures/core__4-invalid-starting-letter.parsed.json b/blocks/test/fixtures/core__4-invalid-starting-letter.parsed.json new file mode 100644 index 00000000000000..8916c770317652 --- /dev/null +++ b/blocks/test/fixtures/core__4-invalid-starting-letter.parsed.json @@ -0,0 +1,6 @@ +[ + { + "attrs": {}, + "innerHTML": "\n" + } +] diff --git a/blocks/test/fixtures/core__4-invalid-starting-letter.serialized.html b/blocks/test/fixtures/core__4-invalid-starting-letter.serialized.html new file mode 100644 index 00000000000000..220f8b60c8d654 --- /dev/null +++ b/blocks/test/fixtures/core__4-invalid-starting-letter.serialized.html @@ -0,0 +1 @@ + diff --git a/blocks/test/fixtures/core__invalid-Capitals.html b/blocks/test/fixtures/core__invalid-Capitals.html new file mode 100644 index 00000000000000..1eaeb570265d9e --- /dev/null +++ b/blocks/test/fixtures/core__invalid-Capitals.html @@ -0,0 +1 @@ + diff --git a/blocks/test/fixtures/core__invalid-Capitals.json b/blocks/test/fixtures/core__invalid-Capitals.json new file mode 100644 index 00000000000000..7fac37fcb660dd --- /dev/null +++ b/blocks/test/fixtures/core__invalid-Capitals.json @@ -0,0 +1,11 @@ +[ + { + "uid": "_uid_0", + "name": "core/freeform", + "isValid": true, + "attributes": { + "content": "" + }, + "originalContent": "" + } +] diff --git a/blocks/test/fixtures/core__invalid-Capitals.parsed.json b/blocks/test/fixtures/core__invalid-Capitals.parsed.json new file mode 100644 index 00000000000000..51888e4529cfb3 --- /dev/null +++ b/blocks/test/fixtures/core__invalid-Capitals.parsed.json @@ -0,0 +1,6 @@ +[ + { + "attrs": {}, + "innerHTML": "\n" + } +] diff --git a/blocks/test/fixtures/core__invalid-Capitals.serialized.html b/blocks/test/fixtures/core__invalid-Capitals.serialized.html new file mode 100644 index 00000000000000..1eaeb570265d9e --- /dev/null +++ b/blocks/test/fixtures/core__invalid-Capitals.serialized.html @@ -0,0 +1 @@ + diff --git a/blocks/test/fixtures/core__invalid-special.html b/blocks/test/fixtures/core__invalid-special.html new file mode 100644 index 00000000000000..548aef63c749bf --- /dev/null +++ b/blocks/test/fixtures/core__invalid-special.html @@ -0,0 +1 @@ + diff --git a/blocks/test/fixtures/core__invalid-special.json b/blocks/test/fixtures/core__invalid-special.json new file mode 100644 index 00000000000000..409611dcfe89e1 --- /dev/null +++ b/blocks/test/fixtures/core__invalid-special.json @@ -0,0 +1,11 @@ +[ + { + "uid": "_uid_0", + "name": "core/freeform", + "isValid": true, + "attributes": { + "content": "" + }, + "originalContent": "" + } +] diff --git a/blocks/test/fixtures/core__invalid-special.parsed.json b/blocks/test/fixtures/core__invalid-special.parsed.json new file mode 100644 index 00000000000000..97c7af3387253f --- /dev/null +++ b/blocks/test/fixtures/core__invalid-special.parsed.json @@ -0,0 +1,6 @@ +[ + { + "attrs": {}, + "innerHTML": "\n" + } +] diff --git a/blocks/test/fixtures/core__invalid-special.serialized.html b/blocks/test/fixtures/core__invalid-special.serialized.html new file mode 100644 index 00000000000000..548aef63c749bf --- /dev/null +++ b/blocks/test/fixtures/core__invalid-special.serialized.html @@ -0,0 +1 @@ + diff --git a/docs/block-api.md b/docs/block-api.md index 784c611e57028e..4462a6093c592a 100644 --- a/docs/block-api.md +++ b/docs/block-api.md @@ -19,7 +19,9 @@ The name for a block is a unique string that identifies a block. Names have to b registerBlockType( 'my-plugin/book', {} ); ``` -*Note:* this name is used on the comment delimiters as ``. Those blocks provided by core don't include a namespace when serialized. +*Note:* A block name can only contain lowercase alphanumeric characters and dashes, and must begin with a letter. + +*Note:* This name is used on the comment delimiters as ``. Those blocks provided by core don't include a namespace when serialized. ### Block Configuration diff --git a/lib/parser.php b/lib/parser.php index b8f0e98ec12a36..bfcd03c2d806bf 100644 --- a/lib/parser.php +++ b/lib/parser.php @@ -260,8 +260,6 @@ private function peg_buildException($message, $expected, $pos) { private $peg_c29; private $peg_c30; private $peg_c31; - private $peg_c32; - private $peg_c33; private function peg_f0($pre, $t, $html) { return array( $t, $html ); } private function peg_f1($pre, $ts, $post) { return peg_join_blocks( $pre, $ts, $post ); } @@ -1363,44 +1361,22 @@ private function peg_parseNamespaced_Block_Name() { $s0 = $this->peg_currPos; $s1 = $this->peg_currPos; - $s2 = $this->peg_parseASCII_Letter(); + $s2 = $this->peg_parseBlock_Name_Part(); if ($s2 !== $this->peg_FAILED) { - $s3 = array(); - $s4 = $this->peg_parseASCII_AlphaNumeric(); - while ($s4 !== $this->peg_FAILED) { - $s3[] = $s4; - $s4 = $this->peg_parseASCII_AlphaNumeric(); + if ($this->input_substr($this->peg_currPos, 1) === $this->peg_c15) { + $s3 = $this->peg_c15; + $this->peg_currPos++; + } else { + $s3 = $this->peg_FAILED; + if ($this->peg_silentFails === 0) { + $this->peg_fail($this->peg_c16); + } } if ($s3 !== $this->peg_FAILED) { - if ($this->input_substr($this->peg_currPos, 1) === $this->peg_c15) { - $s4 = $this->peg_c15; - $this->peg_currPos++; - } else { - $s4 = $this->peg_FAILED; - if ($this->peg_silentFails === 0) { - $this->peg_fail($this->peg_c16); - } - } + $s4 = $this->peg_parseBlock_Name_Part(); if ($s4 !== $this->peg_FAILED) { - $s5 = $this->peg_parseASCII_Letter(); - if ($s5 !== $this->peg_FAILED) { - $s6 = array(); - $s7 = $this->peg_parseASCII_AlphaNumeric(); - while ($s7 !== $this->peg_FAILED) { - $s6[] = $s7; - $s7 = $this->peg_parseASCII_AlphaNumeric(); - } - if ($s6 !== $this->peg_FAILED) { - $s2 = array($s2, $s3, $s4, $s5, $s6); - $s1 = $s2; - } else { - $this->peg_currPos = $s1; - $s1 = $this->peg_FAILED; - } - } else { - $this->peg_currPos = $s1; - $s1 = $this->peg_FAILED; - } + $s2 = array($s2, $s3, $s4); + $s1 = $s2; } else { $this->peg_currPos = $s1; $s1 = $this->peg_FAILED; @@ -1426,26 +1402,7 @@ private function peg_parseCore_Block_Name() { $s0 = $this->peg_currPos; $s1 = $this->peg_currPos; - $s2 = $this->peg_currPos; - $s3 = $this->peg_parseASCII_Letter(); - if ($s3 !== $this->peg_FAILED) { - $s4 = array(); - $s5 = $this->peg_parseASCII_AlphaNumeric(); - while ($s5 !== $this->peg_FAILED) { - $s4[] = $s5; - $s5 = $this->peg_parseASCII_AlphaNumeric(); - } - if ($s4 !== $this->peg_FAILED) { - $s3 = array($s3, $s4); - $s2 = $s3; - } else { - $this->peg_currPos = $s2; - $s2 = $this->peg_FAILED; - } - } else { - $this->peg_currPos = $s2; - $s2 = $this->peg_FAILED; - } + $s2 = $this->peg_parseBlock_Name_Part(); if ($s2 !== $this->peg_FAILED) { $s1 = $this->input_substr($s1, $this->peg_currPos - $s1); } else { @@ -1460,18 +1417,74 @@ private function peg_parseCore_Block_Name() { 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_c17, $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_c18); + } + } + if ($s2 !== $this->peg_FAILED) { + $s3 = array(); + if (Gutenberg_PEG_peg_char_class_test($this->peg_c19, $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_c20); + } + } + while ($s4 !== $this->peg_FAILED) { + $s3[] = $s4; + if (Gutenberg_PEG_peg_char_class_test($this->peg_c19, $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_c20); + } + } + } + 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; + if ($this->input_substr($this->peg_currPos, 1) === $this->peg_c21) { + $s3 = $this->peg_c21; $this->peg_currPos++; } else { $s3 = $this->peg_FAILED; if ($this->peg_silentFails === 0) { - $this->peg_fail($this->peg_c18); + $this->peg_fail($this->peg_c22); } } if ($s3 !== $this->peg_FAILED) { @@ -1480,13 +1493,13 @@ private function peg_parseBlock_Attributes() { $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; + if ($this->input_substr($this->peg_currPos, 1) === $this->peg_c23) { + $s8 = $this->peg_c23; $this->peg_currPos++; } else { $s8 = $this->peg_FAILED; if ($this->peg_silentFails === 0) { - $this->peg_fail($this->peg_c20); + $this->peg_fail($this->peg_c24); } } if ($s8 !== $this->peg_FAILED) { @@ -1501,7 +1514,7 @@ private function peg_parseBlock_Attributes() { $s9 = $this->peg_FAILED; } if ($s9 !== $this->peg_FAILED) { - $s10 = $this->peg_c21; + $s10 = $this->peg_c25; if ($s10 !== $this->peg_FAILED) { if ($this->input_substr($this->peg_currPos, 1) === $this->peg_c15) { $s11 = $this->peg_c15; @@ -1582,13 +1595,13 @@ private function peg_parseBlock_Attributes() { $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; + if ($this->input_substr($this->peg_currPos, 1) === $this->peg_c23) { + $s8 = $this->peg_c23; $this->peg_currPos++; } else { $s8 = $this->peg_FAILED; if ($this->peg_silentFails === 0) { - $this->peg_fail($this->peg_c20); + $this->peg_fail($this->peg_c24); } } if ($s8 !== $this->peg_FAILED) { @@ -1603,7 +1616,7 @@ private function peg_parseBlock_Attributes() { $s9 = $this->peg_FAILED; } if ($s9 !== $this->peg_FAILED) { - $s10 = $this->peg_c21; + $s10 = $this->peg_c25; if ($s10 !== $this->peg_FAILED) { if ($this->input_substr($this->peg_currPos, 1) === $this->peg_c15) { $s11 = $this->peg_c15; @@ -1680,13 +1693,13 @@ private function peg_parseBlock_Attributes() { } } if ($s4 !== $this->peg_FAILED) { - if ($this->input_substr($this->peg_currPos, 1) === $this->peg_c19) { - $s5 = $this->peg_c19; + if ($this->input_substr($this->peg_currPos, 1) === $this->peg_c23) { + $s5 = $this->peg_c23; $this->peg_currPos++; } else { $s5 = $this->peg_FAILED; if ($this->peg_silentFails === 0) { - $this->peg_fail($this->peg_c20); + $this->peg_fail($this->peg_c24); } } if ($s5 !== $this->peg_FAILED) { @@ -1718,50 +1731,7 @@ private function peg_parseBlock_Attributes() { return $s0; } - private function peg_parseASCII_AlphaNumeric() { - - $s0 = $this->peg_parseASCII_Letter(); - if ($s0 === $this->peg_FAILED) { - $s0 = $this->peg_parseASCII_Digit(); - if ($s0 === $this->peg_FAILED) { - $s0 = $this->peg_parseSpecial_Chars(); - } - } - - return $s0; - } - - private function peg_parseASCII_Letter() { - - if (Gutenberg_PEG_peg_char_class_test($this->peg_c22, $this->input_substr($this->peg_currPos, 1))) { - $s0 = $this->input_substr($this->peg_currPos, 1); - $this->peg_currPos++; - } else { - $s0 = $this->peg_FAILED; - if ($this->peg_silentFails === 0) { - $this->peg_fail($this->peg_c23); - } - } - - return $s0; - } - - private function peg_parseASCII_Digit() { - - if (Gutenberg_PEG_peg_char_class_test($this->peg_c24, $this->input_substr($this->peg_currPos, 1))) { - $s0 = $this->input_substr($this->peg_currPos, 1); - $this->peg_currPos++; - } else { - $s0 = $this->peg_FAILED; - if ($this->peg_silentFails === 0) { - $this->peg_fail($this->peg_c25); - } - } - - return $s0; - } - - private function peg_parseSpecial_Chars() { + private function peg_parseWS() { if (Gutenberg_PEG_peg_char_class_test($this->peg_c26, $this->input_substr($this->peg_currPos, 1))) { $s0 = $this->input_substr($this->peg_currPos, 1); @@ -1776,7 +1746,7 @@ private function peg_parseSpecial_Chars() { return $s0; } - private function peg_parseWS() { + private function peg_parseNewline() { if (Gutenberg_PEG_peg_char_class_test($this->peg_c28, $this->input_substr($this->peg_currPos, 1))) { $s0 = $this->input_substr($this->peg_currPos, 1); @@ -1791,7 +1761,7 @@ private function peg_parseWS() { return $s0; } - private function peg_parseNewline() { + private function peg_parse_() { if (Gutenberg_PEG_peg_char_class_test($this->peg_c30, $this->input_substr($this->peg_currPos, 1))) { $s0 = $this->input_substr($this->peg_currPos, 1); @@ -1806,21 +1776,6 @@ private function peg_parseNewline() { return $s0; } - private function peg_parse_() { - - if (Gutenberg_PEG_peg_char_class_test($this->peg_c32, $this->input_substr($this->peg_currPos, 1))) { - $s0 = $this->input_substr($this->peg_currPos, 1); - $this->peg_currPos++; - } else { - $s0 = $this->peg_FAILED; - if ($this->peg_silentFails === 0) { - $this->peg_fail($this->peg_c33); - } - } - - return $s0; - } - private function peg_parse__() { $s0 = array(); @@ -1883,23 +1838,21 @@ public function parse($input) { $this->peg_c14 = array( "type" => "literal", "value" => "/wp:", "description" => "\"/wp:\"" ); $this->peg_c15 = "/"; $this->peg_c16 = array( "type" => "literal", "value" => "/", "description" => "\"/\"" ); - $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(97,122), array(65,90)); - $this->peg_c23 = array( "type" => "class", "value" => "[a-zA-Z]", "description" => "[a-zA-Z]" ); - $this->peg_c24 = array(array(48,57)); - $this->peg_c25 = array( "type" => "class", "value" => "[0-9]", "description" => "[0-9]" ); - $this->peg_c26 = array(array(45,45), array(95,95)); - $this->peg_c27 = array( "type" => "class", "value" => "[-_]", "description" => "[-_]" ); - $this->peg_c28 = array(array(32,32), array(9,9), array(13,13), array(10,10)); - $this->peg_c29 = array( "type" => "class", "value" => "[ \t\r\n]", "description" => "[ \t\r\n]" ); - $this->peg_c30 = array(array(13,13), array(10,10)); - $this->peg_c31 = array( "type" => "class", "value" => "[\r\n]", "description" => "[\r\n]" ); - $this->peg_c32 = array(array(32,32), array(9,9)); - $this->peg_c33 = array( "type" => "class", "value" => "[ \t]", "description" => "[ \t]" ); + $this->peg_c17 = array(array(97,122)); + $this->peg_c18 = array( "type" => "class", "value" => "[a-z]", "description" => "[a-z]" ); + $this->peg_c19 = array(array(97,122), array(48,57), array(95,95), array(45,45)); + $this->peg_c20 = array( "type" => "class", "value" => "[a-z0-9_-]", "description" => "[a-z0-9_-]" ); + $this->peg_c21 = "{"; + $this->peg_c22 = array( "type" => "literal", "value" => "{", "description" => "\"{\"" ); + $this->peg_c23 = "}"; + $this->peg_c24 = array( "type" => "literal", "value" => "}", "description" => "\"}\"" ); + $this->peg_c25 = ""; + $this->peg_c26 = array(array(32,32), array(9,9), array(13,13), array(10,10)); + $this->peg_c27 = array( "type" => "class", "value" => "[ \t\r\n]", "description" => "[ \t\r\n]" ); + $this->peg_c28 = array(array(13,13), array(10,10)); + $this->peg_c29 = array( "type" => "class", "value" => "[\r\n]", "description" => "[\r\n]" ); + $this->peg_c30 = array(array(32,32), array(9,9)); + $this->peg_c31 = array( "type" => "class", "value" => "[ \t]", "description" => "[ \t]" ); $peg_startRuleFunctions = array( 'Block_List' => array($this, "peg_parseBlock_List") ); $peg_startRuleFunction = array($this, "peg_parseBlock_List");