From 9269b6b4adc56b0fb6b3ed9a63074b3cfe7047ed Mon Sep 17 00:00:00 2001 From: bzick Date: Sun, 26 Apr 2015 22:24:20 +0300 Subject: [PATCH] Fix: parse error if macro defined without arguments --- composer.lock | 309 +++++++++++++++++++++++-------- src/Fenom/Compiler.php | 36 ++-- tests/cases/Fenom/MacrosTest.php | 36 ++-- 3 files changed, 276 insertions(+), 105 deletions(-) diff --git a/composer.lock b/composer.lock index 58f4ba3..7754a27 100644 --- a/composer.lock +++ b/composer.lock @@ -154,17 +154,125 @@ "time": "2014-08-11 04:32:36" }, { - "name": "phpunit/php-code-coverage", - "version": "2.0.14", + "name": "phpdocumentor/reflection-docblock", + "version": "2.0.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "ca158276c1200cc27f5409a5e338486bc0b4fc94" + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca158276c1200cc27f5409a5e338486bc0b4fc94", - "reference": "ca158276c1200cc27f5409a5e338486bc0b4fc94", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8", + "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "suggest": { + "dflydev/markdown": "~1.0", + "erusev/parsedown": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "phpDocumentor": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "mike.vanriel@naenius.com" + } + ], + "time": "2015-02-03 12:10:50" + }, + { + "name": "phpspec/prophecy", + "version": "v1.3.1", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "9ca52329bcdd1500de24427542577ebf3fc2f1c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/9ca52329bcdd1500de24427542577ebf3fc2f1c9", + "reference": "9ca52329bcdd1500de24427542577ebf3fc2f1c9", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "~1.0,>=1.0.2", + "phpdocumentor/reflection-docblock": "~2.0" + }, + "require-dev": { + "phpspec/phpspec": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "psr-0": { + "Prophecy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "http://phpspec.org", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2014-11-17 16:23:49" + }, + { + "name": "phpunit/php-code-coverage", + "version": "2.0.15", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "34cc484af1ca149188d0d9e91412191e398e0b67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/34cc484af1ca149188d0d9e91412191e398e0b67", + "reference": "34cc484af1ca149188d0d9e91412191e398e0b67", "shasum": "" }, "require": { @@ -177,7 +285,7 @@ }, "require-dev": { "ext-xdebug": ">=2.1.4", - "phpunit/phpunit": "~4.1" + "phpunit/phpunit": "~4" }, "suggest": { "ext-dom": "*", @@ -196,9 +304,6 @@ ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], @@ -216,7 +321,7 @@ "testing", "xunit" ], - "time": "2014-12-26 13:28:33" + "time": "2015-01-24 10:06:35" }, { "name": "phpunit/php-file-iterator", @@ -353,16 +458,16 @@ }, { "name": "phpunit/php-token-stream", - "version": "1.3.0", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "f8d5d08c56de5cfd592b3340424a81733259a876" + "reference": "db32c18eba00b121c145575fcbcd4d4d24e6db74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/f8d5d08c56de5cfd592b3340424a81733259a876", - "reference": "f8d5d08c56de5cfd592b3340424a81733259a876", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/db32c18eba00b121c145575fcbcd4d4d24e6db74", + "reference": "db32c18eba00b121c145575fcbcd4d4d24e6db74", "shasum": "" }, "require": { @@ -375,7 +480,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3-dev" + "dev-master": "1.4-dev" } }, "autoload": { @@ -398,20 +503,20 @@ "keywords": [ "tokenizer" ], - "time": "2014-08-31 06:12:13" + "time": "2015-01-17 09:51:32" }, { "name": "phpunit/phpunit", - "version": "4.4.1", + "version": "4.5.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "6a5e49a86ce5e33b8d0657abe145057fc513543a" + "reference": "5b578d3865a9128b9c209b011fda6539ec06e7a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6a5e49a86ce5e33b8d0657abe145057fc513543a", - "reference": "6a5e49a86ce5e33b8d0657abe145057fc513543a", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/5b578d3865a9128b9c209b011fda6539ec06e7a5", + "reference": "5b578d3865a9128b9c209b011fda6539ec06e7a5", "shasum": "" }, "require": { @@ -421,15 +526,16 @@ "ext-reflection": "*", "ext-spl": "*", "php": ">=5.3.3", + "phpspec/prophecy": "~1.3.1", "phpunit/php-code-coverage": "~2.0", "phpunit/php-file-iterator": "~1.3.2", "phpunit/php-text-template": "~1.2", "phpunit/php-timer": "~1.0.2", "phpunit/phpunit-mock-objects": "~2.3", - "sebastian/comparator": "~1.0", + "sebastian/comparator": "~1.1", "sebastian/diff": "~1.1", - "sebastian/environment": "~1.1", - "sebastian/exporter": "~1.0", + "sebastian/environment": "~1.2", + "sebastian/exporter": "~1.2", "sebastian/global-state": "~1.0", "sebastian/version": "~1.0", "symfony/yaml": "~2.0" @@ -443,7 +549,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.4.x-dev" + "dev-master": "4.5.x-dev" } }, "autoload": { @@ -469,7 +575,7 @@ "testing", "xunit" ], - "time": "2014-12-28 07:57:05" + "time": "2015-02-05 15:51:19" }, { "name": "phpunit/phpunit-mock-objects", @@ -641,25 +747,25 @@ }, { "name": "sebastian/comparator", - "version": "1.1.0", + "version": "1.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "c484a80f97573ab934e37826dba0135a3301b26a" + "reference": "1dd8869519a225f7f2b9eb663e225298fade819e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/c484a80f97573ab934e37826dba0135a3301b26a", - "reference": "c484a80f97573ab934e37826dba0135a3301b26a", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dd8869519a225f7f2b9eb663e225298fade819e", + "reference": "1dd8869519a225f7f2b9eb663e225298fade819e", "shasum": "" }, "require": { "php": ">=5.3.3", - "sebastian/diff": "~1.1", - "sebastian/exporter": "~1.0" + "sebastian/diff": "~1.2", + "sebastian/exporter": "~1.2" }, "require-dev": { - "phpunit/phpunit": "~4.1" + "phpunit/phpunit": "~4.4" }, "type": "library", "extra": { @@ -701,7 +807,7 @@ "compare", "equality" ], - "time": "2014-11-16 21:32:38" + "time": "2015-01-29 16:28:08" }, { "name": "sebastian/diff", @@ -807,28 +913,29 @@ }, { "name": "sebastian/exporter", - "version": "1.0.2", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "c7d59948d6e82818e1bdff7cadb6c34710eb7dc0" + "reference": "84839970d05254c73cde183a721c7af13aede943" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/c7d59948d6e82818e1bdff7cadb6c34710eb7dc0", - "reference": "c7d59948d6e82818e1bdff7cadb6c34710eb7dc0", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/84839970d05254c73cde183a721c7af13aede943", + "reference": "84839970d05254c73cde183a721c7af13aede943", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.3", + "sebastian/recursion-context": "~1.0" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "~4.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.2.x-dev" } }, "autoload": { @@ -868,7 +975,7 @@ "export", "exporter" ], - "time": "2014-09-10 00:51:36" + "time": "2015-01-27 07:23:06" }, { "name": "sebastian/global-state", @@ -921,6 +1028,59 @@ ], "time": "2014-10-06 09:23:50" }, + { + "name": "sebastian/recursion-context", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "3989662bbb30a29d20d9faa04a846af79b276252" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/3989662bbb30a29d20d9faa04a846af79b276252", + "reference": "3989662bbb30a29d20d9faa04a846af79b276252", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2015-01-24 09:48:32" + }, { "name": "sebastian/version", "version": "1.0.4", @@ -958,17 +1118,17 @@ }, { "name": "symfony/config", - "version": "v2.6.1", + "version": "v2.6.4", "target-dir": "Symfony/Component/Config", "source": { "type": "git", "url": "https://github.com/symfony/Config.git", - "reference": "84c0c150c1520995f09ea9e47e817068b353cb0f" + "reference": "a9f781ba1221067d1f07c8cec0bc50f81b8d7408" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Config/zipball/84c0c150c1520995f09ea9e47e817068b353cb0f", - "reference": "84c0c150c1520995f09ea9e47e817068b353cb0f", + "url": "https://api.github.com/repos/symfony/Config/zipball/a9f781ba1221067d1f07c8cec0bc50f81b8d7408", + "reference": "a9f781ba1221067d1f07c8cec0bc50f81b8d7408", "shasum": "" }, "require": { @@ -1002,21 +1162,21 @@ ], "description": "Symfony Config Component", "homepage": "http://symfony.com", - "time": "2014-12-02 20:19:20" + "time": "2015-01-21 20:57:55" }, { "name": "symfony/console", - "version": "v2.6.1", + "version": "v2.6.4", "target-dir": "Symfony/Component/Console", "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "ef825fd9f809d275926547c9e57cbf14968793e8" + "reference": "e44154bfe3e41e8267d7a3794cd9da9a51cfac34" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/ef825fd9f809d275926547c9e57cbf14968793e8", - "reference": "ef825fd9f809d275926547c9e57cbf14968793e8", + "url": "https://api.github.com/repos/symfony/Console/zipball/e44154bfe3e41e8267d7a3794cd9da9a51cfac34", + "reference": "e44154bfe3e41e8267d7a3794cd9da9a51cfac34", "shasum": "" }, "require": { @@ -1059,21 +1219,21 @@ ], "description": "Symfony Console Component", "homepage": "http://symfony.com", - "time": "2014-12-02 20:19:20" + "time": "2015-01-25 04:39:26" }, { "name": "symfony/event-dispatcher", - "version": "v2.6.1", + "version": "v2.6.4", "target-dir": "Symfony/Component/EventDispatcher", "source": { "type": "git", "url": "https://github.com/symfony/EventDispatcher.git", - "reference": "720fe9bca893df7ad1b4546649473b5afddf0216" + "reference": "f75989f3ab2743a82fe0b03ded2598a2b1546813" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/720fe9bca893df7ad1b4546649473b5afddf0216", - "reference": "720fe9bca893df7ad1b4546649473b5afddf0216", + "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/f75989f3ab2743a82fe0b03ded2598a2b1546813", + "reference": "f75989f3ab2743a82fe0b03ded2598a2b1546813", "shasum": "" }, "require": { @@ -1081,10 +1241,10 @@ }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~2.0", + "symfony/config": "~2.0,>=2.0.5", "symfony/dependency-injection": "~2.6", "symfony/expression-language": "~2.6", - "symfony/stopwatch": "~2.2" + "symfony/stopwatch": "~2.3" }, "suggest": { "symfony/dependency-injection": "", @@ -1117,21 +1277,21 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "http://symfony.com", - "time": "2014-12-02 20:19:20" + "time": "2015-02-01 16:10:57" }, { "name": "symfony/filesystem", - "version": "v2.6.1", + "version": "v2.6.4", "target-dir": "Symfony/Component/Filesystem", "source": { "type": "git", "url": "https://github.com/symfony/Filesystem.git", - "reference": "ff6efc95256cb33031933729e68b01d720b5436b" + "reference": "a1f566d1f92e142fa1593f4555d6d89e3044a9b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Filesystem/zipball/ff6efc95256cb33031933729e68b01d720b5436b", - "reference": "ff6efc95256cb33031933729e68b01d720b5436b", + "url": "https://api.github.com/repos/symfony/Filesystem/zipball/a1f566d1f92e142fa1593f4555d6d89e3044a9b7", + "reference": "a1f566d1f92e142fa1593f4555d6d89e3044a9b7", "shasum": "" }, "require": { @@ -1164,21 +1324,21 @@ ], "description": "Symfony Filesystem Component", "homepage": "http://symfony.com", - "time": "2014-12-02 20:19:20" + "time": "2015-01-03 21:13:09" }, { "name": "symfony/stopwatch", - "version": "v2.6.1", + "version": "v2.6.4", "target-dir": "Symfony/Component/Stopwatch", "source": { "type": "git", "url": "https://github.com/symfony/Stopwatch.git", - "reference": "261abd360cfb6ac65ea93ffd82073e2011d034fc" + "reference": "e8da5286132ba75ce4b4275fbf0f4cd369bfd71c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/261abd360cfb6ac65ea93ffd82073e2011d034fc", - "reference": "261abd360cfb6ac65ea93ffd82073e2011d034fc", + "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/e8da5286132ba75ce4b4275fbf0f4cd369bfd71c", + "reference": "e8da5286132ba75ce4b4275fbf0f4cd369bfd71c", "shasum": "" }, "require": { @@ -1211,21 +1371,21 @@ ], "description": "Symfony Stopwatch Component", "homepage": "http://symfony.com", - "time": "2014-12-02 20:19:20" + "time": "2015-01-03 08:01:59" }, { "name": "symfony/yaml", - "version": "v2.6.1", + "version": "v2.6.4", "target-dir": "Symfony/Component/Yaml", "source": { "type": "git", "url": "https://github.com/symfony/Yaml.git", - "reference": "3346fc090a3eb6b53d408db2903b241af51dcb20" + "reference": "60ed7751671113cf1ee7d7778e691642c2e9acd8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/3346fc090a3eb6b53d408db2903b241af51dcb20", - "reference": "3346fc090a3eb6b53d408db2903b241af51dcb20", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/60ed7751671113cf1ee7d7778e691642c2e9acd8", + "reference": "60ed7751671113cf1ee7d7778e691642c2e9acd8", "shasum": "" }, "require": { @@ -1258,7 +1418,7 @@ ], "description": "Symfony Yaml Component", "homepage": "http://symfony.com", - "time": "2014-12-02 20:19:20" + "time": "2015-01-25 04:39:26" } ], "aliases": [], @@ -1267,6 +1427,7 @@ "satooshi/php-coveralls": 20 }, "prefer-stable": false, + "prefer-lowest": false, "platform": { "php": ">=5.3.0", "ext-tokenizer": "*" diff --git a/src/Fenom/Compiler.php b/src/Fenom/Compiler.php index 9daf1a1..604a983 100644 --- a/src/Fenom/Compiler.php +++ b/src/Fenom/Compiler.php @@ -925,28 +925,28 @@ class Compiler if (!$tokens->valid()) { return; } - $tokens->next()->need('(')->next(); - if ($tokens->is(')')) { - return; - } - while ($tokens->is(Tokenizer::MACRO_STRING, T_VARIABLE)) { - $param = $tokens->current(); - if ($tokens->is(T_VARIABLE)) { - $param = ltrim($param, '$'); - } + $tokens->next(); + if($tokens->is('(') || !$tokens->isNext(')')){ $tokens->next(); - $args[] = $param; - if ($tokens->is('=')) { - $tokens->next(); - if ($tokens->is(T_CONSTANT_ENCAPSED_STRING, T_LNUMBER, T_DNUMBER) || $tokens->isSpecialVal()) { - $defaults[$param] = $tokens->getAndNext(); - } else { - throw new InvalidUsageException("Macro parameters may have only scalar defaults"); + while ($tokens->is(Tokenizer::MACRO_STRING, T_VARIABLE)) { + $param = $tokens->current(); + if ($tokens->is(T_VARIABLE)) { + $param = ltrim($param, '$'); } + $tokens->next(); + $args[] = $param; + if ($tokens->is('=')) { + $tokens->next(); + if ($tokens->is(T_CONSTANT_ENCAPSED_STRING, T_LNUMBER, T_DNUMBER) || $tokens->isSpecialVal()) { + $defaults[$param] = $tokens->getAndNext(); + } else { + throw new InvalidUsageException("Macro parameters may have only scalar defaults"); + } + } + $tokens->skipIf(','); } - $tokens->skipIf(','); + $tokens->skipIf(')'); } - $tokens->skipIf(')'); $scope["macro"] = array( "name" => $scope["name"], "args" => $args, diff --git a/tests/cases/Fenom/MacrosTest.php b/tests/cases/Fenom/MacrosTest.php index 57cb51e..129e370 100644 --- a/tests/cases/Fenom/MacrosTest.php +++ b/tests/cases/Fenom/MacrosTest.php @@ -7,22 +7,28 @@ class MacrosTest extends TestCase public function setUp() { parent::setUp(); - $this->tpl( - "math.tpl", - ' - {macro plus(x, y)} - x + y = {$x + $y} - {/macro} + $this->tpl("math.tpl", + '{macro plus(x, y)} + x + y = {$x + $y} + {/macro} - {macro minus(x, y, z=0)} - x - y - z = {$x - $y - $z} - {/macro} + {macro minus(x, y, z=0)} + x - y - z = {$x - $y - $z} + {/macro} - {macro multi(x, y)} - x * y = {$x * $y} - {/macro} + {macro multi(x, y)} + x * y = {$x * $y} + {/macro} - Math: {macro.plus x=2 y=3}, {macro.minus x=10 y=4} + {macro e()} + 2.71827 + {/macro} + + {macro pi} + 3.14159 + {/macro} + + Math: {macro.plus x=2 y=3}, {macro.minus x=10 y=4} ' ); @@ -99,6 +105,10 @@ class MacrosTest extends TestCase exit; } + /** + * @throws \Exception + * @group macros + */ public function testMacros() { $tpl = $this->fenom->compile('math.tpl');