Author: chabotc
Date: Mon Aug 3 14:05:15 2009
New Revision: 800391
URL: http://svn.apache.org/viewvc?rev=800391&view=rev
Log:
Few minor fixes and Unit tests for the expression parser by Jacky Wang
Added:
incubator/shindig/trunk/php/test/gadgets/ExpTypeTest.php
incubator/shindig/trunk/php/test/gadgets/ExpressionParserTest.php
Modified:
incubator/shindig/trunk/php/src/gadgets/templates/ExpLexer.php
incubator/shindig/trunk/php/src/gadgets/templates/ExpParser.php
incubator/shindig/trunk/php/src/gadgets/templates/ExpType.php
incubator/shindig/trunk/php/src/gadgets/templates/ExpressionParser.php
Modified: incubator/shindig/trunk/php/src/gadgets/templates/ExpLexer.php
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/templates/ExpLexer.php?rev=800391&r1=800390&r2=800391&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/templates/ExpLexer.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/templates/ExpLexer.php Mon Aug 3
14:05:15 2009
@@ -28,7 +28,7 @@
* This lexer could handle special formats like floating 12.3e-10 and string
'tell "me" \'yes\\\'' correctly.
*/
-require_once ('ExpType.php');
+require_once 'ExpType.php';
class ExpLexerException extends Exception {
}
@@ -40,7 +40,7 @@
private static $TERNARY_PATTERN = "/[\?\:]/";
private static $PAREN_PATTERN = "/[\[\]\(\)]/";
private static $COMMA_PATTERN = "/[\,]/";
- private static $OPERATOR_PATTERN =
"/\>\=|\<\=|\=\=|\!\=|\&\&|\|\||\*|\/|\%|\>|\<|\!/"; // No +/-: conflict with
floating
+ private static $OPERATOR_PATTERN =
"/\>\=|\<\=|\=\=|\!\=|\&\&|\|\||\*|\/|\%|\>|\<|\!/"; // No +/-: conflict with
floating
private static $OPERATOR_PATTERN2 =
"/^(and|or|div|mod|gt|lt|ge|le|eq|ne|not|empty)$/";
private static $NUMBER_PATTERN =
"/^(([0-9]+\.[0-9]*)|(\.[0-9]+)|([0-9]+))([eE][\+\-]?[0-9]+)?$/";
private static $IDENTITY_PATTERN = "/^[a-zA-Z][a-zA-Z0-9_]*$/";
@@ -114,7 +114,7 @@
$pos = $i + 1;
} elseif ($state == $targetState) {
// test whether it has been escaped
- if (ExpLexer::isEscaped($str, $i)) continue; // bypass the escaped
ones
+ if (ExpLexer::isEscaped($str, $i)) continue; // bypass the escaped
ones
// output the string segment
$string = ExpType::coerceToString(new Token(ExpType::$RAW,
substr($str, $pos, $i - $pos)));
array_push($newTokenStream, $string);
@@ -319,7 +319,7 @@
}
}
}
-
+
private static function hasUnaryLeft($tokenStream, $i) {
$OPERATOR_LEFT_TYPE = array(ExpType::$BINARY_OP, ExpType::$UNARY_OP,
ExpType::$TERNARY,
ExpType::$COMMA);
@@ -375,21 +375,20 @@
array_push($stack, $node->value);
}
break;
- case ExpType::$UNARY_OP: // Check unary operator gramma
+ case ExpType::$UNARY_OP: // Check unary operator gramma
if (! ExpLexer::hasUnaryLeft($tokenStream, $i)) throw new
ExpLexerException("Mal-format unary operator");
break;
- case ExpType::$BINARY_OP: // Check binary operator gramma
+ case ExpType::$BINARY_OP: // Check binary operator gramma
if (ExpLexer::hasUnaryLeft($tokenStream, $i) || !
ExpLexer::hasBinaryRight($tokenStream, $i)) throw new
ExpLexerException("Mal-format binary operator");
break;
- case ExpType::$DOT: // Check dot gramma
+ case ExpType::$DOT: // Check dot gramma
if ($i == count($tokenStream) - 1 || $tokenStream[$i + 1]->type !=
ExpType::$IDENTITY) throw new ExpLexerException("Mal-format dot");
break;
- case ExpType::$FUNCTION: // Check function gramma
+ case ExpType::$FUNCTION: // Check function gramma
if ($i == count($tokenStream) - 1 || $tokenStream[$i + 1]->value !=
'(') throw new ExpLexerException("Mal-format function");
break;
}
}
if (count($stack) != 0) throw new ExpLexerException("Unbalanced
expression");
}
-
-}
+}
\ No newline at end of file
Modified: incubator/shindig/trunk/php/src/gadgets/templates/ExpParser.php
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/templates/ExpParser.php?rev=800391&r1=800390&r2=800391&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/templates/ExpParser.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/templates/ExpParser.php Mon Aug 3
14:05:15 2009
@@ -28,7 +28,7 @@
* This parser accepts the output token stream produced by ExpLexer.
*/
-require_once ('ExpType.php');
+require_once 'ExpType.php';
class ExpParserException extends Exception {
}
@@ -65,9 +65,9 @@
$COMPOSITE_TYPES = array(ExpType::$ARRAY, ExpType::$OBJECT);
$OPERAND_TYPES = array_merge($PRIMITIVE_TYPES, $COMPOSITE_TYPES,
array(ExpType::$IDENTITY));
- $OPERATOR_PRECEDENCE = array('||' => 0, '&&' => 1, '==' => 2, '!=' => 2,
'>' => 3, '<' => 3,
- '>=' => 3, '<=' => 3, '+' => 4, ' - ' => 4, '*' => 5, '/' => 5, '%' =>
5,
- ' -' => 6, '!' => 6, 'empty' => 6, '.' => 7);
+ $OPERATOR_PRECEDENCE = array('||' => 0, '&&' => 1, '==' => 2, '!=' => 2,
'>' => 3,
+ '<' => 3, '>=' => 3, '<=' => 3, '+' => 4, ' - ' => 4, '*' => 5, '/' =>
5, '%' => 5,
+ ' -' => 6, '!' => 6, 'empty' => 6, '.' => 7);
$operatorStack = array();
$operandStack = array();
@@ -104,7 +104,6 @@
$RELATIONAL_OPS = array('==', '!=', '<', '>', '<=', '>=');
$LOGICAL_OPS = array('&&', '||'); // without '!'
-
$sym = $operator->value;
if ($operator->type == ExpType::$UNARY_OP) {
$operand = $this->evaluateIdentity(array_pop($operandStack));
@@ -114,7 +113,7 @@
$lhs = $this->evaluateIdentity(array_pop($operandStack));
}
if ($sym == '.') {
- if ($lhs->type == ExpType::$NULL || $rhs->type == ExpType::$NULL) { //
Dealing with null type
+ if ($lhs->type == ExpType::$NULL || $rhs->type == ExpType::$NULL) { //
Dealing with null type
$result = new Token(ExpType::$NULL, null);
} else {
if ($lhs->type == ExpType::$ARRAY) {
@@ -135,14 +134,13 @@
$rhs = ExpType::coerceToNumber($rhs);
eval('$resval = $lhs->value ' . $sym . '$rhs->value;');
$result = new Token(ExpType::detectType($resval), $resval);
- } elseif ($sym == ' -') { // Unary operator '-'
+ } elseif ($sym == ' -') { // Unary operator '-'
$result = ExpType::coerceToNumber($operand);
- $result = new Token($result->type, - ($result->value));
+ $result = new Token($result->type, -($result->value));
} elseif (in_array($sym, $RELATIONAL_OPS)) {
$result = new Token(ExpType::$BOOL);
// special case: one of the operator is null
- if ($lhs->type == ExpType::$NULL && $rhs->type != ExpType::$NULL ||
$lhs->type != ExpType::$NULL && $rhs->type == ExpType::$NULL) $result->value =
in_array($sym, array(
- '<', '>', '<=', '>=', '==')) ? false : true;
+ if ($lhs->type == ExpType::$NULL && $rhs->type != ExpType::$NULL ||
$lhs->type != ExpType::$NULL && $rhs->type == ExpType::$NULL) $result->value =
in_array($sym, array('<', '>', '<=', '>=', '==')) ? false : true;
eval('$result->value = $lhs->value ' . $sym . ' $rhs->value;');
} elseif (in_array($sym, $LOGICAL_OPS)) {
$result = new Token(ExpType::$BOOL);
@@ -171,7 +169,7 @@
}
throw new ExpParserException("Un-recogonized identity name in the data
context: " . $token->value);
}
-
+
private function evaluateFunction() {
$FUNCTION_TRANS = array('osx:parseJson' => 'json_decode',
'osx:decodeBase64' => 'base64_decode',
'osx:urlEncode' => 'rawurlencode', 'osx:urlDecode' => 'rawurldecode');
@@ -200,13 +198,14 @@
public static function parse($tokenStream, $dataContext) {
$scopes = array();
$expression = new PrimitiveExp(new Token('final'));
+
while ($token = array_shift($tokenStream)) {
// split non-primitive expression into primitive ones
switch ($token->type) {
case ExpType::$PAREN:
switch ($token->value) {
case '[':
- $expression->append(new Token(ExpType::$DOT, '.')); // drop
through
+ $expression->append(new Token(ExpType::$DOT, '.')); // drop
through
case '(':
ExpParser::scopePush($expression, $scopes, $token);
break;
@@ -286,4 +285,4 @@
if (! $rigid && ($token->type == ExpType::$COMMA || $token->type ==
ExpType::$TERNARY)) return true;
return false;
}
-}
+}
\ No newline at end of file
Modified: incubator/shindig/trunk/php/src/gadgets/templates/ExpType.php
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/templates/ExpType.php?rev=800391&r1=800390&r2=800391&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/templates/ExpType.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/templates/ExpType.php Mon Aug 3
14:05:15 2009
@@ -90,20 +90,19 @@
$INTEGER_PATTERN = "/^[0-9]+$/";
$type = $token->type;
if (in_array($type, array(ExpType::$INT, ExpType::$FLOAT))) return $token;
- if ($type == ExpType::$BOOL || ($type == ExpType::$RAW || $type ==
ExpType::$STRING) && preg_match($INTEGER_PATTERN, $token->value) == 1) {
+ if (in_array($type, array(ExpType::$BOOL, ExpType::$NULL)) ||
in_array($type, array(ExpType::$RAW, ExpType::$STRING)) &&
preg_match($INTEGER_PATTERN, $token->value) == 1) {
$int = new Token(ExpType::$INT, (int)($token->value));
return $int;
}
- if (in_array($type, array(ExpType::$NULL, ExpType::$RAW,
ExpType::$STRING))) {
+ if (in_array($type, array(ExpType::$RAW, ExpType::$STRING))) {
$float = new Token(ExpType::$FLOAT, (float)($token->value));
return $float;
}
- throw new ExpTypeException("Unable to coerce token " . print_r($token) . "
to number");
+ throw new ExpTypeException("Unable to coerce token " . print_r($token,
true) . " to number");
}
public static function coerceToString($token) {
- $PRIMITIVE_TYPES = array(ExpType::$INT, ExpType::$FLOAT, ExpType::$STRING,
ExpType::$BOOL,
- ExpType::$NULL);
+ $PRIMITIVE_TYPES = array(ExpType::$INT, ExpType::$FLOAT, ExpType::$STRING,
ExpType::$BOOL, ExpType::$NULL);
$COMPOSITE_TYPES = array(ExpType::$ARRAY, ExpType::$OBJECT);
$type = $token->type;
if ($type == ExpType::$STRING) return $token;
@@ -112,19 +111,20 @@
$string->value = strtr($token->value, ExpType::$ESCAPE_CHARS);
} elseif ($type == ExpType::$BOOL) {
$string->value = ($token->value) ? 'true' : 'false';
+ } elseif ($type == ExpType::$NULL) {
+ $string->value = 'null';
} elseif (in_array($type, $PRIMITIVE_TYPES)) {
$string->value = (string)($token->value);
} elseif (in_array($type, $COMPOSITE_TYPES)) {
- $string->value = print_r($token->value); // maybe call .toString()?
+ $string->value = print_r($token->value, true); // maybe call .toString()?
} else {
- throw new ExpTypeException("Unable to coerce token" . print_r($token) .
" to string");
+ throw new ExpTypeException("Unable to coerce token" . print_r($token,
true) . " to string");
}
return $string;
}
public static function coerceToBool($token) {
- $PRIMITIVE_TYPES = array(ExpType::$INT, ExpType::$FLOAT, ExpType::$STRING,
ExpType::$BOOL,
- ExpType::$NULL);
+ $PRIMITIVE_TYPES = array(ExpType::$INT, ExpType::$FLOAT, ExpType::$STRING,
ExpType::$BOOL, ExpType::$NULL);
$COMPOSITE_TYPES = array(ExpType::$ARRAY, ExpType::$OBJECT);
$type = $token->type;
if ($type == ExpType::$BOOL) return $token;
@@ -136,20 +136,22 @@
} elseif (in_array($type, $COMPOSITE_TYPES)) {
$bool->value = $token->value != null ? true : false;
} else {
- throw new ExpTypeException("Unable to coerce token" . print_r($token) .
" to bool");
+ throw new ExpTypeException("Unable to coerce token" . print_r($token,
true) . " to bool");
}
return $bool;
}
public static function coerceToNull($token) {
+ $COMPOSITE_TYPES = array(ExpType::$ARRAY, ExpType::$OBJECT);
$type = $token->type;
- $value = $token->value;
+ if ($type == ExpType::$NULL) return $token;
$null = new Token(ExpType::$NULL);
- if (($type == ExpType::$RAW) && (strtolower($value) == 'null')) {
+ $value = $token->value;
+ if ($type == ExpType::$RAW && strtolower($value) == 'null' ||
in_array($type, $COMPOSITE_TYPES) && $token->value == null) {
$null->value = null;
} else {
- throw new ExpTypeException("Unable to coerce token" . print_r($token) .
" to null");
+ throw new ExpTypeException("Unable to coerce token" . print_r($token,
true) . " to null");
}
return $null;
}
-}
+}
\ No newline at end of file
Modified: incubator/shindig/trunk/php/src/gadgets/templates/ExpressionParser.php
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/templates/ExpressionParser.php?rev=800391&r1=800390&r2=800391&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/templates/ExpressionParser.php
(original)
+++ incubator/shindig/trunk/php/src/gadgets/templates/ExpressionParser.php Mon
Aug 3 14:05:15 2009
@@ -83,4 +83,4 @@
return $val;
}
}
-}
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/test/gadgets/ExpTypeTest.php
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/php/test/gadgets/ExpTypeTest.php?rev=800391&view=auto
==============================================================================
--- incubator/shindig/trunk/php/test/gadgets/ExpTypeTest.php (added)
+++ incubator/shindig/trunk/php/test/gadgets/ExpTypeTest.php Mon Aug 3
14:05:15 2009
@@ -0,0 +1,103 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * ExpType test case.
+ */
+class ExpTypeTest extends PHPUnit_Framework_TestCase {
+
+ private $tokens;
+
+ /**
+ * Prepares the environment before running a test.
+ */
+ protected function setUp() {
+ parent::setUp();
+ ExpType::$RAW; // dummy here, for loading ExpType.php
+ $int = new Token(ExpType::$INT, 1);
+ $float = new Token(ExpType::$FLOAT, 1.0);
+ $string = new Token(ExpType::$STRING, 'Jacky Wang');
+ $bool = new Token(ExpType::$BOOL, true);
+ $null = new Token(ExpType::$NULL, null);
+ $array = new Token(ExpType::$ARRAY, array());
+ $object = new Token(ExpType::$OBJECT, (object)("it's object"));
+ $this->tokens = array('int' => $int, 'float' => $float, 'string' =>
$string, 'bool' => $bool, 'null' => $null, 'array' => $array, 'object' =>
$object);
+ }
+
+ /**
+ * Cleans up the environment after running a test.
+ */
+ protected function tearDown() {
+ parent::tearDown();
+ }
+
+ /**
+ * Tests ExpType::detectType
+ */
+ public function testDetectType() {
+ foreach ($this->tokens as $token) {
+ $this->assertEquals($token->type, ExpType::detectType($token->value));
+ }
+ }
+
+ /**
+ * Tests ExpType::coerce
+ */
+ public function testCoerce() {
+ // coerce number
+ $this->assertEquals($this->tokens['int'],
ExpType::coerceToNumber($this->tokens['int']));
+ $this->assertEquals($this->tokens['float'],
ExpType::coerceToNumber($this->tokens['float']));
+ $this->assertEquals(new Token(ExpType::$INT, 2),
ExpType::coerceToNumber(new Token(ExpType::$RAW, '2')));
+ $this->assertEquals(new Token(ExpType::$INT, 2),
ExpType::coerceToNumber(new Token(ExpType::$STRING, '2')));
+ $this->assertEquals(new Token(ExpType::$INT, 1),
ExpType::coerceToNumber(new Token(ExpType::$BOOL, true)));
+ $this->assertEquals(new Token(ExpType::$INT, 0),
ExpType::coerceToNumber(new Token(ExpType::$BOOL, false)));
+ $this->assertEquals(new Token(ExpType::$INT, 0),
ExpType::coerceToNumber(new Token(ExpType::$NULL, null)));
+ $this->assertEquals(new Token(ExpType::$FLOAT, 1.0),
ExpType::coerceToNumber(new Token(ExpType::$RAW, '1.0')));
+ $this->assertEquals(new Token(ExpType::$FLOAT, 1.0),
ExpType::coerceToNumber(new Token(ExpType::$STRING, '1.0')));
+
+ // coerce string
+ $this->assertEquals($this->tokens['string'],
ExpType::coerceToString($this->tokens['string']));
+ $this->assertEquals(new Token(ExpType::$STRING, '2'),
ExpType::coerceToString(new Token(ExpType::$RAW, '2')));
+ $this->assertEquals(new Token(ExpType::$STRING, '2'),
ExpType::coerceToString(new Token(ExpType::$INT, 2)));
+ $this->assertEquals(new Token(ExpType::$STRING, '2'),
ExpType::coerceToString(new Token(ExpType::$FLOAT, 2.0)));
+ $this->assertEquals(new Token(ExpType::$STRING, '2.5'),
ExpType::coerceToString(new Token(ExpType::$FLOAT, 2.5)));
+ $this->assertEquals(new Token(ExpType::$STRING, 'true'),
ExpType::coerceToString(new Token(ExpType::$BOOL, true)));
+ $this->assertEquals(new Token(ExpType::$STRING, 'false'),
ExpType::coerceToString(new Token(ExpType::$BOOL, false)));
+ $this->assertEquals(new Token(ExpType::$STRING, 'null'),
ExpType::coerceToString(new Token(ExpType::$NULL, null)));
+
+ // coerce bool
+ $this->assertEquals($this->tokens['bool'],
ExpType::coerceToBool($this->tokens['bool']));
+ $this->assertEquals(new Token(ExpType::$BOOL, true),
ExpType::coerceToBool(new Token(ExpType::$RAW, 'True')));
+ $this->assertEquals(new Token(ExpType::$BOOL, true),
ExpType::coerceToBool(new Token(ExpType::$RAW, 'true')));
+ $this->assertEquals(new Token(ExpType::$BOOL, false),
ExpType::coerceToBool(new Token(ExpType::$RAW, 'False')));
+ $this->assertEquals(new Token(ExpType::$BOOL, false),
ExpType::coerceToBool(new Token(ExpType::$RAW, 'false')));
+ $this->assertEquals(new Token(ExpType::$BOOL, true),
ExpType::coerceToBool(new Token(ExpType::$STRING, 'false')));
+ $this->assertEquals(new Token(ExpType::$BOOL, false),
ExpType::coerceToBool(new Token(ExpType::$STRING, '')));
+ $this->assertEquals(new Token(ExpType::$BOOL, true),
ExpType::coerceToBool(new Token(ExpType::$INT, 2)));
+ $this->assertEquals(new Token(ExpType::$BOOL, false),
ExpType::coerceToBool(new Token(ExpType::$INT, 0)));
+ $this->assertEquals(new Token(ExpType::$BOOL, true),
ExpType::coerceToBool(new Token(ExpType::$FLOAT, 2.0)));
+ $this->assertEquals(new Token(ExpType::$BOOL, false),
ExpType::coerceToBool(new Token(ExpType::$FLOAT, 0.0)));
+ $this->assertEquals(new Token(ExpType::$BOOL, false),
ExpType::coerceToBool(new Token(ExpType::$NULL, null)));
+
+ // coerce null
+ $this->assertEquals($this->tokens['null'],
ExpType::coerceToNull($this->tokens['null']));
+ $this->assertEquals($this->tokens['null'], ExpType::coerceToNull(new
Token(ExpType::$RAW, 'null')));
+ }
+}
\ No newline at end of file
Added: incubator/shindig/trunk/php/test/gadgets/ExpressionParserTest.php
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/php/test/gadgets/ExpressionParserTest.php?rev=800391&view=auto
==============================================================================
--- incubator/shindig/trunk/php/test/gadgets/ExpressionParserTest.php (added)
+++ incubator/shindig/trunk/php/test/gadgets/ExpressionParserTest.php Mon Aug
3 14:05:15 2009
@@ -0,0 +1,176 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+class ObjEe {
+ public $Ee;
+}
+
+/**
+ * ExpressionParser test case.
+ */
+class ExpressionParserTest extends PHPUnit_Framework_TestCase {
+
+ private $input;
+ private $tokenStream;
+ private $dataContext;
+
+ /**
+ * Prepares the environment before running a test.
+ */
+ protected function setUp() {
+ parent::setUp();
+ $encoded_json = base64_encode('{"array_attr": [0, 1]}');
+ $attr_equ = "no_prefix_id.Ee+---((2-1)*(4.0-3)-1.0/2+5e-1)>-.5e+1+4 or not
empty cur_id['empty_str']&&!top_id.null_attr";
+ $this->input =
'osx:parseJson(osx:urlDecode(osx:urlEncode(osx:decodeBase64("' . $encoded_json
. '"))))'
+ . '.array_attr['
+ . $attr_equ . "?0:1"
+ . "]==1?(true?'no_prefix_id.Ee > 0':"
+ . '"\'should never be here\' \\\\\\""'
+ . "):'no_prefix_id.Ee <= 0'";
+
+ $this->tokenStream = array(
+ new Token(ExpType::$FUNCTION, 'osx:parseJson'),
+ new Token(ExpType::$PAREN, '('),
+ new Token(ExpType::$FUNCTION, 'osx:urlDecode'),
+ new Token(ExpType::$PAREN, '('),
+ new Token(ExpType::$FUNCTION, 'osx:urlEncode'),
+ new Token(ExpType::$PAREN, '('),
+ new Token(ExpType::$FUNCTION, 'osx:decodeBase64'),
+ new Token(ExpType::$PAREN, '('),
+ new Token(ExpType::$STRING, 'eyJhcnJheV9hdHRyIjpbMSwgMF19'),
+ new Token(ExpType::$PAREN, ')'),
+ new Token(ExpType::$PAREN, ')'),
+ new Token(ExpType::$PAREN, ')'),
+ new Token(ExpType::$PAREN, ')'),
+ new Token(ExpType::$DOT, '.'),
+ new Token(ExpType::$IDENTITY, 'array_attr'),
+ new Token(ExpType::$PAREN, '['),
+ new Token(ExpType::$IDENTITY, 'no_prefix_id'),
+ new Token(ExpType::$DOT, '.'),
+ new Token(ExpType::$IDENTITY, 'Ee'),
+ new Token(ExpType::$BINARY_OP, '+'),
+ new Token(ExpType::$UNARY_OP, '- '),
+ new Token(ExpType::$UNARY_OP, '- '),
+ new Token(ExpType::$UNARY_OP, '- '),
+ new Token(ExpType::$PAREN, '('),
+ new Token(ExpType::$PAREN, '('),
+ new Token(ExpType::$INT, 2),
+ new Token(ExpType::$BINARY_OP, ' - '),
+ new Token(ExpType::$INT, 1),
+ new Token(ExpType::$PAREN, ')'),
+ new Token(ExpType::$BINARY_OP, '*'),
+ new Token(ExpType::$PAREN, '('),
+ new Token(ExpType::$FLOAT, 4.0),
+ new Token(ExpType::$BINARY_OP, ' - '),
+ new Token(ExpType::$INT, 3),
+ new Token(ExpType::$BINARY_OP, ' - '),
+ new Token(ExpType::$FLOAT, 1.0),
+ new Token(ExpType::$BINARY_OP, '/'),
+ new Token(ExpType::$INT, 2),
+ new Token(ExpType::$BINARY_OP, '+'),
+ new Token(ExpType::$FLOAT, 0.5),
+ new Token(ExpType::$PAREN, ')'),
+ new Token(ExpType::$BINARY_OP, '>'),
+ new Token(ExpType::$UNARY_OP, '- '),
+ new Token(ExpType::$FLOAT, 5.0),
+ new Token(ExpType::$BINARY_OP, '+'),
+ new Token(ExpType::$INT, 4),
+ new Token(ExpType::$BINARY_OP, '||'),
+ new Token(ExpType::$UNARY_OP, '!'),
+ new Token(ExpType::$UNARY_OP, 'empty'),
+ new Token(ExpType::$IDENTITY, 'cur_id'),
+ new Token(ExpType::$PAREN, '['),
+ new Token(ExpType::$STRING, 'empty_str'),
+ new Token(ExpType::$PAREN, ']'),
+ new Token(ExpType::$BINARY_OP, '&&'),
+ new Token(ExpType::$UNARY_OP, '!'),
+ new Token(ExpType::$IDENTITY, 'top_id'),
+ new Token(ExpType::$DOT, '.'),
+ new Token(ExpType::$IDENTITY, 'null_attr'),
+ new Token(ExpType::$TERNARY, '?'),
+ new Token(ExpType::$INT, 0),
+ new Token(ExpType::$TERNARY, ':'),
+ new Token(ExpType::$INT, 1),
+ new Token(ExpType::$PAREN, ']'),
+ new Token(ExpType::$BINARY_OP, '=='),
+ new Token(ExpType::$INT, 1),
+ new Token(ExpType::$TERNARY, '?'),
+ new Token(ExpType::$PAREN, '('),
+ new Token(ExpType::$BOOL, true),
+ new Token(ExpType::$TERNARY, '?'),
+ new Token(ExpType::$STRING, 'no_prefix_id.Ee > 0'),
+ new Token(ExpType::$TERNARY, ':'),
+ new Token(ExpType::$STRING, '"\'should never be here\' \\\\\\""'),
+ new Token(ExpType::$PAREN, ')'),
+ new Token(ExpType::$TERNARY, ':'),
+ new Token(ExpType::$STRING, 'no_prefix_id.Ee <= 0')
+ );
+
+ $no_prefix_id = new ObjEe();
+ $no_prefix_id->Ee = 1; // change this number to see the difference
+ $cur_id = array('empty_str' => '');
+ $top_id = (object)'empty_object';
+ $this->dataContext = array(
+ 'no_prefix_id' => $no_prefix_id,
+ 'Cur' => array('cur_id' => $cur_id),
+ 'My' => array(),
+ 'Top' => array('top_id' => $top_id)
+ );
+ }
+
+ /**
+ * Cleans up the environment after running a test.
+ */
+ protected function tearDown() {
+ parent::tearDown();
+ }
+
+ /**
+ * Tests ExpLexer::process
+ */
+ public function testProcess() {
+ $actualTokenStream = ExpLexer::process($this->input);
+ $this->assertEquals($this->tokenStream, $actualTokenStream);
+ }
+
+ /**
+ * Tests ExpParser::parse
+ */
+ public function testParse() {
+ $this->dataContext['no_prefix_id']->Ee = 1;
+ $actualResult = ExpParser::parse($this->tokenStream, $this->dataContext);
+ $this->assertEquals(new Token(ExpType::$STRING, 'no_prefix_id.Ee > 0'),
$actualResult);
+
+ $this->dataContext['no_prefix_id']->Ee = -1;
+ $actualResult = ExpParser::parse($this->tokenStream, $this->dataContext);
+ $this->assertEquals(new Token(ExpType::$STRING, 'no_prefix_id.Ee <= 0'),
$actualResult);
+ }
+
+ /**
+ * Tests ExpressionParser::evaluate
+ */
+ public function testEvaluate() {
+ $actualOutput = ExpressionParser::evaluate($this->input,
$this->dataContext);
+
+ // Expected result
+ $this->assertEquals('no_prefix_id.Ee > 0', $actualOutput);
+ }
+
+}