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);
+  }
+
+}


Reply via email to