diff --git a/src/Type/InnerParser.php b/src/Type/InnerParser.php index 01d205e45..eb05aa448 100644 --- a/src/Type/InnerParser.php +++ b/src/Type/InnerParser.php @@ -25,17 +25,20 @@ public function __construct() 'skip' => '\s+', 'parenthesis_' => '<', '_parenthesis' => '>', + 'empty_string' => '""|\'\'', + 'number' => '(\+|\-)?(0|[1-9]\d*)(\.\d+)?', + 'null' => 'null', 'comma' => ',', 'name' => '(?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\\\)*[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*', 'quote_:quoted_string' => '"', 'apostrophe_:apostrophed_string' => '\'', ], 'quoted_string' => [ - 'quoted_string' => '(?:[^"]|"")+', + 'quoted_string' => '[^"]+', '_quote:default' => '"', ], 'apostrophed_string' => [ - 'apostrophed_string' => '(?:[^\']|\'\')+', + 'apostrophed_string' => '[^\']+', '_apostrophe:default' => '\'', ], ], @@ -43,29 +46,35 @@ public function __construct() 'type' => new Choice('type', ['simple_type', 'compound_type'], null), 1 => new Token(1, 'name', null, -1, true), 2 => new Concatenation(2, [1], '#simple_type'), - 3 => new Token(3, 'quote_', null, -1, false), - 4 => new Token(4, 'quoted_string', null, -1, true), - 5 => new Token(5, '_quote', null, -1, false), - 6 => new Concatenation(6, [3, 4, 5], '#simple_type'), - 7 => new Token(7, 'apostrophe_', null, -1, false), - 8 => new Token(8, 'apostrophed_string', null, -1, true), - 9 => new Token(9, '_apostrophe', null, -1, false), - 10 => new Concatenation(10, [7, 8, 9], '#simple_type'), - 'simple_type' => new Choice('simple_type', [2, 6, 10], null), - 12 => new Token(12, 'name', null, -1, true), - 13 => new Token(13, 'parenthesis_', null, -1, false), - 14 => new Token(14, 'comma', null, -1, false), - 15 => new Concatenation(15, [14, 'type'], '#compound_type'), - 16 => new Repetition(16, 0, -1, 15, null), - 17 => new Token(17, '_parenthesis', null, -1, false), - 'compound_type' => new Concatenation('compound_type', [12, 13, 'type', 16, 17], null), + 3 => new Token(3, 'number', null, -1, true), + 4 => new Concatenation(4, [3], '#simple_type'), + 5 => new Token(5, 'null', null, -1, true), + 6 => new Concatenation(6, [5], '#simple_type'), + 7 => new Token(7, 'empty_string', null, -1, true), + 8 => new Concatenation(8, [7], '#simple_type'), + 9 => new Token(9, 'quote_', null, -1, false), + 10 => new Token(10, 'quoted_string', null, -1, true), + 11 => new Token(11, '_quote', null, -1, false), + 12 => new Concatenation(12, [9, 10, 11], '#simple_type'), + 13 => new Token(13, 'apostrophe_', null, -1, false), + 14 => new Token(14, 'apostrophed_string', null, -1, true), + 15 => new Token(15, '_apostrophe', null, -1, false), + 16 => new Concatenation(16, [13, 14, 15], '#simple_type'), + 'simple_type' => new Choice('simple_type', [2, 4, 6, 8, 12, 16], null), + 18 => new Token(18, 'name', null, -1, true), + 19 => new Token(19, 'parenthesis_', null, -1, false), + 20 => new Token(20, 'comma', null, -1, false), + 21 => new Concatenation(21, [20, 'type'], '#compound_type'), + 22 => new Repetition(22, 0, -1, 21, null), + 23 => new Token(23, '_parenthesis', null, -1, false), + 'compound_type' => new Concatenation('compound_type', [18, 19, 'type', 22, 23], null), ], [] ); $this->getRule('type')->setPPRepresentation(' simple_type() | compound_type()'); $this->getRule('simple_type')->setDefaultId('#simple_type'); - $this->getRule('simple_type')->setPPRepresentation(' | ::quote_:: ::_quote:: | ::apostrophe_:: ::_apostrophe::'); + $this->getRule('simple_type')->setPPRepresentation(' | | | | ::quote_:: ::_quote:: | ::apostrophe_:: ::_apostrophe::'); $this->getRule('compound_type')->setDefaultId('#compound_type'); $this->getRule('compound_type')->setPPRepresentation(' ::parenthesis_:: type() ( ::comma:: type() )* ::_parenthesis::'); } diff --git a/src/Type/TypeVisitor.php b/src/Type/TypeVisitor.php index 79ea9bc07..6b9257c62 100644 --- a/src/Type/TypeVisitor.php +++ b/src/Type/TypeVisitor.php @@ -40,6 +40,18 @@ private function visitSimpleType(TreeNode $element) return ['name' => $value, 'params' => []]; } + if ('empty_string' === $token) { + return ''; + } + + if ('null' === $token) { + return null; + } + + if ('number' === $token) { + return false === strpos($value, '.') ? intval($value) : floatval($value); + } + $escapeChar = 'quoted_string' === $token ? '"' : "'"; if (false === strpos($value, $escapeChar)) { diff --git a/src/Type/grammar.pp b/src/Type/grammar.pp index cad372ce9..fe98e784e 100644 --- a/src/Type/grammar.pp +++ b/src/Type/grammar.pp @@ -2,15 +2,18 @@ %token parenthesis_ < %token _parenthesis > +%token empty_string ""|'' +%token number (\+|\-)?(0|[1-9]\d*)(\.\d+)? +%token null null %token comma , %token name (?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\\)*[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]* %token quote_ " -> quoted_string -%token quoted_string:quoted_string (?:[^"]|"")+ +%token quoted_string:quoted_string [^"]+ %token quoted_string:_quote " -> default %token apostrophe_ ' -> apostrophed_string -%token apostrophed_string:apostrophed_string (?:[^']|'')+ +%token apostrophed_string:apostrophed_string [^']+ %token apostrophed_string:_apostrophe ' -> default type: @@ -18,6 +21,9 @@ #simple_type: + | + | + | | ::quote_:: ::_quote:: | ::apostrophe_:: ::_apostrophe:: diff --git a/tests/Serializer/Type/ParserTest.php b/tests/Serializer/Type/ParserTest.php index 67c114faf..9ceec0d6d 100644 --- a/tests/Serializer/Type/ParserTest.php +++ b/tests/Serializer/Type/ParserTest.php @@ -47,6 +47,30 @@ public function validTypesProvider(): iterable 'array', $type('array', [['name' => 'Foo', 'params' => []]]), ]; + yield [ + 'Foo<\'a\'>', + $type('Foo', ['a']), + ]; + yield [ + 'Foo<5>', + $type('Foo', [5]), + ]; + yield [ + 'Foo<5.5>', + $type('Foo', [5.5]), + ]; + yield [ + 'Foo', + $type('Foo', [null]), + ]; + yield [ + 'Foo<\'a\',\'b\',\'c\'>', + $type('Foo', ['a', 'b', 'c']), + ]; + yield [ + 'Foo<\'a\',\'\'>', + $type('Foo', ['a', '']), + ]; yield [ 'array', $type('array', [['name' => 'Foo', 'params' => []], ['name' => 'Bar', 'params' => []]]), @@ -72,14 +96,6 @@ public function validTypesProvider(): iterable 'Foo<"asdf asdf">', $type('Foo', ['asdf asdf']), ]; - yield [ - 'Foo<"""bar""">', - $type('Foo', ['"bar"']), - ]; - yield [ - "Foo<'a''b'>", - $type('Foo', ["a'b"]), - ]; } public function testEmptyString(): void