diff --git a/Library/Builder/Operators/CastOperatorBuilder.php b/Library/Builder/Operators/CastOperatorBuilder.php new file mode 100644 index 0000000000..1b77fdfe6a --- /dev/null +++ b/Library/Builder/Operators/CastOperatorBuilder.php @@ -0,0 +1,67 @@ +<?php + +/* + +--------------------------------------------------------------------------+ + | Zephir Language | + +--------------------------------------------------------------------------+ + | Copyright (c) 2013-2014 Zephir Team and contributors | + +--------------------------------------------------------------------------+ + | This source file is subject the MIT license, that is bundled with | + | this package in the file LICENSE, and is available through the | + | world-wide-web at the following url: | + | http://zephir-lang.com/license.html | + | | + | If you did not receive a copy of the MIT license and are unable | + | to obtain it through the world-wide-web, please send a note to | + | license@zephir-lang.com so we can mail you a copy immediately. | + +--------------------------------------------------------------------------+ +*/ + +namespace Zephir\Builder\Operators; + +use Zephir\Builder\Operators\AbstractOperatorBuilder; + +/** + * CastOperatorBuilder + * + * Allows to manually build a 'cast' operator AST node + */ +class CastOperatorBuilder extends AbstractOperatorBuilder +{ + protected $leftOperand; + + protected $rightOperand; + + /** + * @param $left + * @param $right + * @param null $file + * @param int $line + * @param int $char + */ + public function __construct($left, $right, $file = null, $line = 0, $char = 0) + { + $this->leftOperand = $left; + $this->rightOperand = $right; + $this->file = $file; + $this->line = $line; + $this->char = $char; + } + + /** + * Returns a builder definition + * + * @return array + */ + public function get() + { + return array( + 'type' => 'cast', + 'left' => $this->leftOperand, + 'right' => $this->rightOperand->get(), + 'file' => $this->file, + 'line' => $this->line, + 'char' => $this->char + ); + } +} diff --git a/Library/Compiler.php b/Library/Compiler.php index e548ad963e..64aed3069c 100755 --- a/Library/Compiler.php +++ b/Library/Compiler.php @@ -30,7 +30,7 @@ */ class Compiler { - const VERSION = '0.5.8a'; + const VERSION = '0.5.9a'; /** * @var CompilerFile[] @@ -112,7 +112,7 @@ public function __construct(Config $config, Logger $logger) $this->fileSystem = new FileSystem(); $this->checkRequires(); } - + /** * Check require extensions orther when build your extension */ @@ -127,13 +127,13 @@ protected function checkRequires() $collection_error .= $value . ", "; } } - + if ($collection_error != PHP_EOL . "\tCould not load Extension : ") { $collection_error .= PHP_EOL . "\tYou must add extensions above before build this extension!"; throw new Exception($collection_error); } } - + } /** diff --git a/Library/Expression.php b/Library/Expression.php index d5ca7bfcec..00ca30a057 100644 --- a/Library/Expression.php +++ b/Library/Expression.php @@ -59,6 +59,7 @@ use Zephir\Operators\Other\RequireOperator; use Zephir\Operators\Other\TypeOfOperator; use Zephir\Operators\Other\CastOperator; +use Zephir\Operators\Other\RangeInclusiveOperator; use Zephir\Expression\Closure; use Zephir\Expression\ClosureArrow; @@ -561,6 +562,12 @@ public function compile(CompilationContext $compilationContext) $expr->setExpectReturn($this->_expecting, $this->_expectingVariable); return $expr->compile($expression, $compilationContext); + case 'irange': + $expr = new RangeInclusiveOperator(); + $expr->setReadOnly($this->isReadOnly()); + $expr->setExpectReturn($this->_expecting, $this->_expectingVariable); + return $expr->compile($expression, $compilationContext); + case 'list': if ($expression['left']['type'] == 'list') { $compilationContext->logger->warning("Unnecessary extra parentheses", "extra-parentheses", $expression); diff --git a/Library/Operators/Other/CastOperator.php b/Library/Operators/Other/CastOperator.php index a9052a82a7..340ad96686 100644 --- a/Library/Operators/Other/CastOperator.php +++ b/Library/Operators/Other/CastOperator.php @@ -36,6 +36,8 @@ class CastOperator extends BaseOperator { /** + * Compiles a type cast operation + * * @param $expression * @param CompilationContext $compilationContext * @return bool|CompiledExpression @@ -230,6 +232,23 @@ public function compile($expression, CompilationContext $compilationContext) } break; + case 'array': + switch ($resolved->getType()) { + case 'variable': + $compilationContext->headersManager->add('kernel/operators'); + $symbolVariable = $compilationContext->symbolTable->getTempVariable('array', $compilationContext, $expression); + $symbolVariable->setMustInitNull(true); + $symbolVariable->setIsInitialized(true, $compilationContext, $expression); + $compilationContext->codePrinter->output('zephir_get_arrval(' . $symbolVariable->getName() . ', ' . $resolved->getCode() . ');'); + if ($symbolVariable->isTemporal()) { + $symbolVariable->setIdle(true); + } + return new CompiledExpression('variable', $symbolVariable->getName(), $expression); + default: + throw new CompilerException("Cannot cast: " . $resolved->getType() . " to " . $expression['left'], $expression); + } + break; + case 'object': switch ($resolved->getType()) { diff --git a/Library/Operators/Other/RangeInclusiveOperator.php b/Library/Operators/Other/RangeInclusiveOperator.php new file mode 100644 index 0000000000..a64fcf7ab4 --- /dev/null +++ b/Library/Operators/Other/RangeInclusiveOperator.php @@ -0,0 +1,68 @@ +<?php + +/* + +--------------------------------------------------------------------------+ + | Zephir Language | + +--------------------------------------------------------------------------+ + | Copyright (c) 2013-2014 Zephir Team and contributors | + +--------------------------------------------------------------------------+ + | This source file is subject the MIT license, that is bundled with | + | this package in the file LICENSE, and is available through the | + | world-wide-web at the following url: | + | http://zephir-lang.com/license.html | + | | + | If you did not receive a copy of the MIT license and are unable | + | to obtain it through the world-wide-web, please send a note to | + | license@zephir-lang.com so we can mail you a copy immediately. | + +--------------------------------------------------------------------------+ +*/ + +namespace Zephir\Operators\Other; + +use Zephir\Operators\BaseOperator; +use Zephir\CompilationContext; +use Zephir\Expression; +use Zephir\CompilerException; +use Zephir\CompiledExpression; +use Zephir\Builder\FunctionCallBuilder; +use Zephir\Builder\Operators\CastOperatorBuilder; + +/** + * RangeInclusive + * + * Inclusive range operator + */ +class RangeInclusiveOperator extends BaseOperator +{ + /** + * @param array $expression + * @param CompilationContext $compilationContext + * @return CompiledExpression + * @throws CompilerException + */ + public function compile(array $expression, CompilationContext $compilationContext) + { + + if (!isset($expression['left'])) { + throw new CompilerException("Invalid 'left' operand for 'irange' expression", $expression['left']); + } + + if (!isset($expression['right'])) { + throw new CompilerException("Invalid 'right' operand for 'irange' expression", $expression['right']); + } + + $builder = new FunctionCallBuilder('range', array( + array('parameter' => $expression['left']), + array('parameter' => $expression['right']) + )); + + /** + * Implicit type coercing + */ + $castBuilder = new CastOperatorBuilder('array', $builder); + + $expression = new Expression($castBuilder->get()); + $expression->setReadOnly($this->_readOnly); + return $expression->compile($compilationContext); + } +} diff --git a/Library/Passes/CallGathererPass.php b/Library/Passes/CallGathererPass.php index 156b1d9058..c7126f50f6 100644 --- a/Library/Passes/CallGathererPass.php +++ b/Library/Passes/CallGathererPass.php @@ -178,6 +178,8 @@ public function passExpression(array $expression) case 'greater': case 'greater-equal': case 'less-equal': + case 'irange': + case 'erange': $this->passExpression($expression['left']); $this->passExpression($expression['right']); break; diff --git a/Library/Passes/LocalContextPass.php b/Library/Passes/LocalContextPass.php index e1e847069a..014eb611e3 100644 --- a/Library/Passes/LocalContextPass.php +++ b/Library/Passes/LocalContextPass.php @@ -197,6 +197,8 @@ public function passLetStatement(array $statement) case 'closure': case 'closure-arrow': case 'reference': + case 'irange': + case 'erange': $this->markVariableNoLocal($assignment['variable']); break; @@ -343,6 +345,8 @@ public function passExpression(array $expression) case 'bitwise_xor': case 'bitwise_shiftleft': case 'bitwise_shiftright': + case 'irange': + case 'erange': $this->passExpression($expression['left']); $this->passExpression($expression['right']); break; diff --git a/Library/Passes/MutateGathererPass.php b/Library/Passes/MutateGathererPass.php index ddfca56f99..937b1aa7c4 100644 --- a/Library/Passes/MutateGathererPass.php +++ b/Library/Passes/MutateGathererPass.php @@ -194,6 +194,8 @@ public function passExpression(array $expression) case 'bitwise_xor': case 'bitwise_shiftleft': case 'bitwise_shiftright': + case 'irange': + case 'erange': $this->passExpression($expression['left']); $this->passExpression($expression['right']); break; diff --git a/Library/Passes/StaticTypeInference.php b/Library/Passes/StaticTypeInference.php index bf48a7ece6..687684022b 100644 --- a/Library/Passes/StaticTypeInference.php +++ b/Library/Passes/StaticTypeInference.php @@ -389,6 +389,10 @@ public function passExpression(array $expression) case 'less-equal': return 'bool'; + case 'irange': + case 'erange': + return 'variable'; + case 'typeof': $this->passExpression($expression['left']); return 'string'; diff --git a/ext/test/router.zep.c b/ext/test/router.zep.c index de014ec914..0b46a3dfdb 100644 --- a/ext/test/router.zep.c +++ b/ext/test/router.zep.c @@ -106,8 +106,8 @@ PHP_METHOD(Test_Router, __construct) { zephir_fcall_cache_entry *_3 = NULL; int ZEPHIR_LAST_CALL_STATUS; - zval *_1, *_5; - zval *defaultRoutes_param = NULL, *routes, *_0, *_2 = NULL, *_4; + zval *_1, *_4; + zval *defaultRoutes_param = NULL, *routes, *_0 = NULL, *_2 = NULL, *_5; zend_bool defaultRoutes; ZEPHIR_MM_GROW(); @@ -134,23 +134,23 @@ PHP_METHOD(Test_Router, __construct) { zephir_check_temp_parameter(_2); zephir_check_call_status(); zephir_array_append(&routes, _0, PH_SEPARATE, "test/router.zep", 90); + ZEPHIR_INIT_NVAR(_2); + object_init_ex(_2, test_router_route_ce); ZEPHIR_INIT_VAR(_4); - object_init_ex(_4, test_router_route_ce); + array_init_size(_4, 5); + add_assoc_long_ex(_4, SS("controller"), 1); + add_assoc_long_ex(_4, SS("action"), 2); + add_assoc_long_ex(_4, SS("params"), 3); ZEPHIR_INIT_VAR(_5); - array_init_size(_5, 5); - add_assoc_long_ex(_5, SS("controller"), 1); - add_assoc_long_ex(_5, SS("action"), 2); - add_assoc_long_ex(_5, SS("params"), 3); - ZEPHIR_INIT_NVAR(_2); - ZVAL_STRING(_2, "#^/([a-zA-Z0-9\\_\\-]+)/([a-zA-Z0-9\\.\\_]+)(/.*)*$#", ZEPHIR_TEMP_PARAM_COPY); - ZEPHIR_CALL_METHOD(NULL, _4, "__construct", &_3, _2, _5); - zephir_check_temp_parameter(_2); + ZVAL_STRING(_5, "#^/([a-zA-Z0-9\\_\\-]+)/([a-zA-Z0-9\\.\\_]+)(/.*)*$#", ZEPHIR_TEMP_PARAM_COPY); + ZEPHIR_CALL_METHOD(NULL, _2, "__construct", &_3, _5, _4); + zephir_check_temp_parameter(_5); zephir_check_call_status(); - zephir_array_append(&routes, _4, PH_SEPARATE, "test/router.zep", 96); + zephir_array_append(&routes, _2, PH_SEPARATE, "test/router.zep", 96); } - ZEPHIR_INIT_NVAR(_2); - array_init(_2); - zephir_update_property_this(this_ptr, SL("_params"), _2 TSRMLS_CC); + ZEPHIR_INIT_NVAR(_0); + array_init(_0); + zephir_update_property_this(this_ptr, SL("_params"), _0 TSRMLS_CC); zephir_update_property_this(this_ptr, SL("_routes"), routes TSRMLS_CC); ZEPHIR_MM_RESTORE(); diff --git a/ext/test/trie.zep.c b/ext/test/trie.zep.c index 2c2ae5e598..469f38122e 100644 --- a/ext/test/trie.zep.c +++ b/ext/test/trie.zep.c @@ -69,7 +69,7 @@ PHP_METHOD(Test_Trie, getTrieNodeByKey) { zephir_read_property(&_3, trieNode, SL("children"), PH_NOISY_CC); if (!(zephir_array_isset(_3, character))) { if (create) { - ZEPHIR_INIT_LNVAR(_4); + ZEPHIR_INIT_NVAR(_4); if (!_5) { _5 = zend_fetch_class(SL("tries\\trienode"), ZEND_FETCH_CLASS_AUTO TSRMLS_CC); } diff --git a/ext/test/trytest.zep.c b/ext/test/trytest.zep.c index 218f071992..daa61c9574 100644 --- a/ext/test/trytest.zep.c +++ b/ext/test/trytest.zep.c @@ -97,7 +97,7 @@ PHP_METHOD(Test_TryTest, testTry2) { PHP_METHOD(Test_TryTest, testTry3) { int ZEPHIR_LAST_CALL_STATUS; - zval *_0, *_1 = NULL; + zval *_0 = NULL, *_1; ZEPHIR_MM_GROW(); @@ -118,9 +118,9 @@ PHP_METHOD(Test_TryTest, testTry3) { try_end_1: if (EG(exception)) { - ZEPHIR_INIT_NVAR(_1); - ZEPHIR_CPY_WRT(_1, EG(exception)); - if (zephir_instance_of_ev(_1, zend_exception_get_default(TSRMLS_C) TSRMLS_CC)) { + ZEPHIR_INIT_NVAR(_0); + ZEPHIR_CPY_WRT(_0, EG(exception)); + if (zephir_instance_of_ev(_0, zend_exception_get_default(TSRMLS_C) TSRMLS_CC)) { zend_clear_exception(TSRMLS_C); RETURN_MM_STRING("error", 1); } @@ -156,7 +156,7 @@ PHP_METHOD(Test_TryTest, testTry4) { goto try_end_1; } else { - ZEPHIR_INIT_LNVAR(_0); + ZEPHIR_INIT_NVAR(_0); object_init_ex(_0, spl_ce_RuntimeException); ZEPHIR_INIT_NVAR(_1); ZVAL_STRING(_1, "error!", ZEPHIR_TEMP_PARAM_COPY); @@ -171,15 +171,15 @@ PHP_METHOD(Test_TryTest, testTry4) { try_end_1: if (EG(exception)) { - ZEPHIR_INIT_NVAR(_1); - ZEPHIR_CPY_WRT(_1, EG(exception)); - if (zephir_instance_of_ev(_1, spl_ce_RuntimeException TSRMLS_CC)) { + ZEPHIR_INIT_NVAR(_0); + ZEPHIR_CPY_WRT(_0, EG(exception)); + if (zephir_instance_of_ev(_0, spl_ce_RuntimeException TSRMLS_CC)) { zend_clear_exception(TSRMLS_C); RETURN_MM_STRING("domain error", 1); } - ZEPHIR_INIT_NVAR(_1); - ZEPHIR_CPY_WRT(_1, EG(exception)); - if (zephir_instance_of_ev(_1, zend_exception_get_default(TSRMLS_C) TSRMLS_CC)) { + ZEPHIR_INIT_NVAR(_0); + ZEPHIR_CPY_WRT(_0, EG(exception)); + if (zephir_instance_of_ev(_0, zend_exception_get_default(TSRMLS_C) TSRMLS_CC)) { zend_clear_exception(TSRMLS_C); RETURN_MM_STRING("error", 1); } @@ -215,7 +215,7 @@ PHP_METHOD(Test_TryTest, testTry5) { goto try_end_1; } else { - ZEPHIR_INIT_LNVAR(_0); + ZEPHIR_INIT_NVAR(_0); object_init_ex(_0, spl_ce_RuntimeException); ZEPHIR_INIT_NVAR(_1); ZVAL_STRING(_1, "error!", ZEPHIR_TEMP_PARAM_COPY); @@ -230,13 +230,13 @@ PHP_METHOD(Test_TryTest, testTry5) { try_end_1: if (EG(exception)) { - ZEPHIR_INIT_NVAR(_1); - ZEPHIR_CPY_WRT(_1, EG(exception)); - if (zephir_instance_of_ev(_1, spl_ce_RuntimeException TSRMLS_CC)) { + ZEPHIR_INIT_NVAR(_0); + ZEPHIR_CPY_WRT(_0, EG(exception)); + if (zephir_instance_of_ev(_0, spl_ce_RuntimeException TSRMLS_CC)) { zend_clear_exception(TSRMLS_C); RETURN_MM_STRING("any error", 1); } - if (zephir_instance_of_ev(_1, zend_exception_get_default(TSRMLS_C) TSRMLS_CC)) { + if (zephir_instance_of_ev(_0, zend_exception_get_default(TSRMLS_C) TSRMLS_CC)) { zend_clear_exception(TSRMLS_C); RETURN_MM_STRING("any error", 1); } @@ -272,7 +272,7 @@ PHP_METHOD(Test_TryTest, testTry6) { goto try_end_1; } else { - ZEPHIR_INIT_LNVAR(_0); + ZEPHIR_INIT_NVAR(_0); object_init_ex(_0, spl_ce_RuntimeException); ZEPHIR_INIT_NVAR(_1); ZVAL_STRING(_1, "error!", ZEPHIR_TEMP_PARAM_COPY); @@ -329,7 +329,7 @@ PHP_METHOD(Test_TryTest, testTry7) { goto try_end_1; } else { - ZEPHIR_INIT_LNVAR(_0); + ZEPHIR_INIT_NVAR(_0); object_init_ex(_0, spl_ce_RuntimeException); ZEPHIR_INIT_NVAR(_1); ZVAL_STRING(_1, "error!", ZEPHIR_TEMP_PARAM_COPY); diff --git a/parser/base.c b/parser/base.c index d64ac7c563..5900c9ed78 100644 --- a/parser/base.c +++ b/parser/base.c @@ -369,6 +369,12 @@ int xx_parse_program(char *program, unsigned int program_length, char *file_path case XX_T_DOUBLECOLON: xx_(xx_parser, XX_DOUBLECOLON, NULL, parser_status); break; + case XX_T_INCLUSIVE_RANGE: + xx_(xx_parser, XX_INCLUSIVE_RANGE, NULL, parser_status); + break; + case XX_T_EXCLUSIVE_RANGE: + xx_(xx_parser, XX_EXCLUSIVE_RANGE, NULL, parser_status); + break; case XX_T_NOT: xx_(xx_parser, XX_NOT, NULL, parser_status); break; diff --git a/parser/parser.h b/parser/parser.h index c481228eb8..40279e325c 100644 --- a/parser/parser.h +++ b/parser/parser.h @@ -33,89 +33,91 @@ #define XX_ISSET 33 #define XX_FETCH 34 #define XX_EMPTY 35 -#define XX_TYPEOF 36 -#define XX_CLONE 37 -#define XX_NEW 38 -#define XX_NOT 39 -#define XX_BITWISE_AND 40 -#define XX_PARENTHESES_CLOSE 41 -#define XX_SBRACKET_OPEN 42 -#define XX_ARROW 43 -#define XX_NAMESPACE 44 -#define XX_IDENTIFIER 45 -#define XX_DOTCOMMA 46 -#define XX_USE 47 -#define XX_AS 48 -#define XX_INTERFACE 49 -#define XX_EXTENDS 50 -#define XX_CLASS 51 -#define XX_IMPLEMENTS 52 -#define XX_ABSTRACT 53 -#define XX_FINAL 54 -#define XX_BRACKET_OPEN 55 -#define XX_BRACKET_CLOSE 56 -#define XX_COMMENT 57 -#define XX_ASSIGN 58 -#define XX_CONST 59 -#define XX_CONSTANT 60 -#define XX_FUNCTION 61 -#define XX_PARENTHESES_OPEN 62 -#define XX_INLINE 63 -#define XX_DEPRECATED 64 -#define XX_VOID 65 -#define XX_NULL 66 -#define XX_THIS 67 -#define XX_SBRACKET_CLOSE 68 -#define XX_TYPE_INTEGER 69 -#define XX_TYPE_UINTEGER 70 -#define XX_TYPE_LONG 71 -#define XX_TYPE_ULONG 72 -#define XX_TYPE_CHAR 73 -#define XX_TYPE_UCHAR 74 -#define XX_TYPE_DOUBLE 75 -#define XX_TYPE_BOOL 76 -#define XX_TYPE_STRING 77 -#define XX_TYPE_ARRAY 78 -#define XX_TYPE_VAR 79 -#define XX_TYPE_CALLABLE 80 -#define XX_TYPE_RESOURCE 81 -#define XX_TYPE_OBJECT 82 -#define XX_BREAK 83 -#define XX_CONTINUE 84 -#define XX_IF 85 -#define XX_ELSE 86 -#define XX_ELSEIF 87 -#define XX_SWITCH 88 -#define XX_CASE 89 -#define XX_COLON 90 -#define XX_DEFAULT 91 -#define XX_LOOP 92 -#define XX_WHILE 93 -#define XX_DO 94 -#define XX_TRY 95 -#define XX_CATCH 96 -#define XX_FOR 97 -#define XX_IN 98 -#define XX_REVERSE 99 -#define XX_LET 100 -#define XX_ADDASSIGN 101 -#define XX_SUBASSIGN 102 -#define XX_MULASSIGN 103 -#define XX_DIVASSIGN 104 -#define XX_CONCATASSIGN 105 -#define XX_MODASSIGN 106 -#define XX_STRING 107 -#define XX_DOUBLECOLON 108 -#define XX_INCR 109 -#define XX_DECR 110 -#define XX_ECHO 111 -#define XX_RETURN 112 -#define XX_UNSET 113 -#define XX_THROW 114 -#define XX_PLUS 115 -#define XX_INTEGER 116 -#define XX_CHAR 117 -#define XX_DOUBLE 118 -#define XX_TRUE 119 -#define XX_FALSE 120 -#define XX_CBLOCK 121 +#define XX_INCLUSIVE_RANGE 36 +#define XX_EXCLUSIVE_RANGE 37 +#define XX_TYPEOF 38 +#define XX_CLONE 39 +#define XX_NEW 40 +#define XX_NOT 41 +#define XX_BITWISE_AND 42 +#define XX_PARENTHESES_CLOSE 43 +#define XX_SBRACKET_OPEN 44 +#define XX_ARROW 45 +#define XX_NAMESPACE 46 +#define XX_IDENTIFIER 47 +#define XX_DOTCOMMA 48 +#define XX_USE 49 +#define XX_AS 50 +#define XX_INTERFACE 51 +#define XX_EXTENDS 52 +#define XX_CLASS 53 +#define XX_IMPLEMENTS 54 +#define XX_ABSTRACT 55 +#define XX_FINAL 56 +#define XX_BRACKET_OPEN 57 +#define XX_BRACKET_CLOSE 58 +#define XX_COMMENT 59 +#define XX_ASSIGN 60 +#define XX_CONST 61 +#define XX_CONSTANT 62 +#define XX_FUNCTION 63 +#define XX_PARENTHESES_OPEN 64 +#define XX_INLINE 65 +#define XX_DEPRECATED 66 +#define XX_VOID 67 +#define XX_NULL 68 +#define XX_THIS 69 +#define XX_SBRACKET_CLOSE 70 +#define XX_TYPE_INTEGER 71 +#define XX_TYPE_UINTEGER 72 +#define XX_TYPE_LONG 73 +#define XX_TYPE_ULONG 74 +#define XX_TYPE_CHAR 75 +#define XX_TYPE_UCHAR 76 +#define XX_TYPE_DOUBLE 77 +#define XX_TYPE_BOOL 78 +#define XX_TYPE_STRING 79 +#define XX_TYPE_ARRAY 80 +#define XX_TYPE_VAR 81 +#define XX_TYPE_CALLABLE 82 +#define XX_TYPE_RESOURCE 83 +#define XX_TYPE_OBJECT 84 +#define XX_BREAK 85 +#define XX_CONTINUE 86 +#define XX_IF 87 +#define XX_ELSE 88 +#define XX_ELSEIF 89 +#define XX_SWITCH 90 +#define XX_CASE 91 +#define XX_COLON 92 +#define XX_DEFAULT 93 +#define XX_LOOP 94 +#define XX_WHILE 95 +#define XX_DO 96 +#define XX_TRY 97 +#define XX_CATCH 98 +#define XX_FOR 99 +#define XX_IN 100 +#define XX_REVERSE 101 +#define XX_LET 102 +#define XX_ADDASSIGN 103 +#define XX_SUBASSIGN 104 +#define XX_MULASSIGN 105 +#define XX_DIVASSIGN 106 +#define XX_CONCATASSIGN 107 +#define XX_MODASSIGN 108 +#define XX_STRING 109 +#define XX_DOUBLECOLON 110 +#define XX_INCR 111 +#define XX_DECR 112 +#define XX_ECHO 113 +#define XX_RETURN 114 +#define XX_UNSET 115 +#define XX_THROW 116 +#define XX_PLUS 117 +#define XX_INTEGER 118 +#define XX_CHAR 119 +#define XX_DOUBLE 120 +#define XX_TRUE 121 +#define XX_FALSE 122 +#define XX_CBLOCK 123 diff --git a/parser/parser.lemon b/parser/parser.lemon index cd4cf04a75..1b0458ce8d 100644 --- a/parser/parser.lemon +++ b/parser/parser.lemon @@ -44,6 +44,7 @@ %left ADD SUB CONCAT . %left MUL DIV MOD . %right ISSET FETCH EMPTY . +%left INCLUSIVE_RANGE EXCLUSIVE_RANGE . %right TYPEOF . %right CLONE . %right NEW . @@ -2728,6 +2729,16 @@ xx_common_expr(R) ::= xx_common_expr(O1) INSTANCEOF xx_common_expr(O2) . { R = xx_ret_expr("instanceof", O1, O2, NULL, status->scanner_state); } +/* y = a .. b */ +xx_common_expr(R) ::= xx_common_expr(O1) INCLUSIVE_RANGE xx_common_expr(O2) . { + R = xx_ret_expr("irange", O1, O2, NULL, status->scanner_state); +} + +/* y = a ... b */ +xx_common_expr(R) ::= xx_common_expr(O1) EXCLUSIVE_RANGE xx_common_expr(O2) . { + R = xx_ret_expr("erange", O1, O2, NULL, status->scanner_state); +} + /* y = fetch x, z[k] */ xx_fetch_expr(R) ::= FETCH IDENTIFIER(O1) COMMA xx_common_expr(O2) . { R = xx_ret_expr("fetch", xx_ret_literal(XX_T_IDENTIFIER, O1, status->scanner_state), O2, NULL, status->scanner_state); diff --git a/parser/scanner.h b/parser/scanner.h index 6b7ba701cb..abbe4d563d 100644 --- a/parser/scanner.h +++ b/parser/scanner.h @@ -148,6 +148,8 @@ #define XX_T_BITWISE_SHIFTLEFT 419 #define XX_T_BITWISE_SHIFTRIGHT 420 #define XX_T_DOUBLEARROW 440 +#define XX_T_INCLUSIVE_RANGE 441 +#define XX_T_EXCLUSIVE_RANGE 442 #define XX_T_CBLOCK 451 diff --git a/parser/scanner.re b/parser/scanner.re index dde8f20224..0234ac30b8 100644 --- a/parser/scanner.re +++ b/parser/scanner.re @@ -865,6 +865,18 @@ int xx_get_token(xx_scanner_state *s, xx_scanner_token *token) { return 0; } + ".." { + s->active_char += 2; + token->opcode = XX_T_INCLUSIVE_RANGE; + return 0; + } + + "..." { + s->active_char += 3; + token->opcode = XX_T_EXCLUSIVE_RANGE; + return 0; + } + ":" { s->active_char++; token->opcode = XX_T_COLON;