jenkins-bot has submitted this change and it was merged.

Change subject: add ternary operator (version 0.0.9)
......................................................................


add ternary operator (version 0.0.9)

example:

echo true?'true':'false'; // 'true'

Change-Id: Ic7b4b5092628ee2446f6ab6f75d4080a28c2bcc5
---
M Foxway.php
M includes/Interpreter.php
M includes/Runtime.php
M tests/phpunit/includes/InterpreterTest.php
4 files changed, 176 insertions(+), 11 deletions(-)

Approvals:
  Pastakhov: Verified; Looks good to me, approved
  Hashar: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/Foxway.php b/Foxway.php
index cd71152..4ece886 100644
--- a/Foxway.php
+++ b/Foxway.php
@@ -15,7 +15,7 @@
        die( 'This file is an extension to MediaWiki and thus not a valid entry 
point.' );
 }
 
-define( 'Foxway_VERSION' , '0.0.8' );
+define( 'Foxway_VERSION' , '0.0.9' );
 
 // Register this extension on Special:Version
 $wgExtensionCredits['parserhook'][] = array(
diff --git a/includes/Interpreter.php b/includes/Interpreter.php
index dab7d7d..a64d6ce 100644
--- a/includes/Interpreter.php
+++ b/includes/Interpreter.php
@@ -38,6 +38,8 @@
                T_IS_NOT_EQUAL,                         // !=
                T_IS_IDENTICAL,                         // ===
                T_IS_NOT_IDENTICAL,                     // !==
+               '?',
+               ':',
                );
 
        public static function run($source, $is_debug = false) {
@@ -48,6 +50,7 @@
                $expectListParams = false;
                $expectCurlyClose = false;
                $expectQuotesClose = false;
+               $expectTernarySeparators = 0;
                $parenthesesLevel = 0;
                $incrementVariable = false;
                $variableName = null;
@@ -55,20 +58,21 @@
                $line = 1;
                $runtime = new Runtime();
 
-               foreach ($tokens as $token) {
+               reset($tokens);
+               while ( list(, $token) = each($tokens) ) {
                        if ( is_string($token) ) {
                                $id = $token;
                        } else {
                                list($id, $text, $line) = $token;
                        }
 
+                       //\MWDebug::log( 'WHILE ' . var_export($token,true) );
+
                        if( $expected && in_array($id, self::$skipTokenIds) === 
false && in_array($id, $expected) === false) {
                                $id_str = is_string($id) ? "' $id '" : 
token_name($id);
-                               $return .= '<br><span class="error">' . 
wfMessage( 'foxway-php-syntax-error-unexpected', $id_str, $line )->escaped() . 
'</span>';
+                               $return .= '<br><span class="error" title="' . 
__LINE__ . '">' . wfMessage( 'foxway-php-syntax-error-unexpected', $id_str, 
$line )->escaped() . '</span>';
                                break;
                        }
-
-                       //\MWDebug::log( var_export($token,true) );
 
                        switch ($id) {
                                case ';':
@@ -129,6 +133,108 @@
                                case T_IS_NOT_IDENTICAL: // !==
                                                $runtime->addOperator( $id );
                                        break;
+                               case '?':
+                                       if( $runtime->getMathResult() ) { // 
true
+                                               $expectTernarySeparators++; // 
just go further
+                                       } else { // false, to skip to the 
ternary operator separator
+                                               $tmp_skip = 0; // it to parse 
the syntax of nested ternary operators
+                                               $skipedTokens = 0; // it for 
debug messages and check correct syntax
+                                               $token = current($tokens);
+                                               do {
+                                                       //\MWDebug::log( 
var_export($token, true) );
+                                                       if ( is_string($token) 
) {
+                                                               $id = $token;
+                                                       } else {
+                                                               list($id, 
$text, $line) = $token;
+                                                       }
+                                                       switch ($id) {
+                                                               case '?': // is 
embedded ternary operator
+                                                                       
$tmp_skip++; // will skip ternary separators
+                                                                       break;
+                                                               case ':':
+                                                                       if( 
$tmp_skip > 0 ) { // were the embedded ternary operator?
+                                                                               
$tmp_skip--;
+                                                                       } else 
{ /************************ EXIT HERE ***********************************/
+                                                                               
break 2; // found the required separator, we go from here and just go further
+                                                                       }       
 /************************ EXIT HERE ***********************************/
+                                                                       break;
+                                                               case 
T_WHITESPACE:
+                                                               case T_COMMENT:
+                                                               case 
T_DOC_COMMENT:
+                                                                       break; 
// just ignore, does not affect the count skipped operators
+                                                               case ',':
+                                                               case ';':
+                                                               case T_IF: // 
This should not occur here, syntax error
+                                                                       $return 
.= $return .= '<br><span class="error" title="' . __LINE__ . '">' . wfMessage( 
'foxway-php-syntax-error-unexpected', is_string($id) ? "' $id '" : 
token_name($id), $line )->escaped() . '</span>';
+                                                                       break 4;
+                                                               default :
+                                                                       
$skipedTokens++; // Increments the counter skipped operators
+                                                                       break;
+                                                       }
+                                               } while( $token = next($tokens) 
);
+                                               if($is_debug) {
+                                                       $debug[] = '<span 
style="color:#969696" title="Skiped tokens: '.$skipedTokens.'"> ? ... </span>';
+                                               }
+                                               if( $token === false ) {
+                                                       $return .= $return .= 
'<br><span class="error" title="' . __LINE__ . '">' . wfMessage( 
'foxway-php-syntax-error-unexpected', '$end', $line )->escaped() . '</span>';
+                                                       break 2;
+                                               }
+                                               $id = ':';
+                                               next($tokens);
+                                               //just go further
+                                       }
+                                       break;
+                               case ':':
+                                       if( $expectTernarySeparators > 0 ) { // 
Yes, we waited this
+                                               // Here we need to find the end 
of the current ternary operator and skip other operators
+                                               $expectTernarySeparators--;
+                                               $skipedTokens = 0; // it for 
debug messages and check correct syntax
+                                               $token = current($tokens);
+                                               do {
+                                                       //\MWDebug::log( 
var_export($token, true) );
+                                                       if ( is_string($token) 
) {
+                                                               $id = $token;
+                                                       } else {
+                                                               list($id, 
$text, $line) = $token;
+                                                       }
+                                                       switch ($id) {
+                                                               case ':':
+                                                                       if( 
$expectTernarySeparators > 0 ) { // This ternary operator is nested and this 
separator owned by a parent
+                                                                               
$expectTernarySeparators--; // note that found it. is to control the syntax
+                                                                               
break;
+                                                                       } else {
+                                                                               
break 2; // is a violation of the syntax, exit the loop. After the loop has to 
go error
+                                                                       }
+                                                               case ',':
+                                                               case ';':
+                                                               case '?':
+                                                                       if( 
$skipedTokens > 0 ) {
+                                                                               
if($is_debug) {
+                                                                               
        $debug[] = '<span style="color:#969696" title="Skiped tokens: 
'.$skipedTokens.'"> : ... </span>';
+                                                                               
}
+                                                                               
/************************ EXIT HERE ***********************************/
+                                                                               
continue 4; // We found the end of the ternary operator, and now go further
+                                                                               
/************************ EXIT HERE ***********************************/
+                                                                       }
+                                                                       // 
break is not necessary here
+                                                               case T_IF:
+                                                                       $return 
.= $return .= '<br><span class="error" title="' . __LINE__ . '">' . wfMessage( 
'foxway-php-syntax-error-unexpected', is_string($id) ? "' $id '" : 
token_name($id), $line )->escaped() . '</span>';
+                                                                       break 4;
+                                                               case 
T_WHITESPACE:
+                                                               case T_COMMENT:
+                                                               case 
T_DOC_COMMENT:
+                                                                       break; 
// just ignore
+                                                               default :
+                                                                       
$skipedTokens++;
+                                                                       break;
+                                                       }
+                                               } while( $token = next($tokens) 
);
+                                               $return .= $return .= 
'<br><span class="error" title="' . __LINE__ . '">' . wfMessage( 
'foxway-php-syntax-error-unexpected', '$end', $line )->escaped() . '</span>';
+                                               break 2;
+                                       }
+                                       // If we are here, then we do not 
expect to find separator ternary
+                                       $return .= '<br><span class="error" 
title="' . __LINE__ . '">' . wfMessage( 'foxway-php-syntax-error-unexpected', 
$id, $line )->escaped() . '</span>';
+                                       break 2;
                                case T_INC: // ++
                                case T_DEC: // --
                                        if( $incrementVariable === false ) {
@@ -249,7 +355,7 @@
                                        } elseif( strcasecmp($text, 'false') == 
0 ) {
                                                $runtime->addParam( false );
                                        } else {
-                                               $return .= '<br><span 
class="error">' . wfMessage( 'foxway-php-syntax-error-unexpected', "'$text'", 
$line )->escaped() . '</span>';
+                                               $return .= '<br><span 
class="error" title="' . __LINE__ . '">' . wfMessage( 
'foxway-php-syntax-error-unexpected', "'$text'", $line )->escaped() . '</span>';
                                                break 2;
                                        }
                                        break;
@@ -257,6 +363,8 @@
                        if( $id != T_VARIABLE && $id != T_INC && $id != T_DEC ) 
{
                                $incrementVariable = false;
                        }
+
+                       /*****************   EXPECT   
*************************************/
 
                        switch ($id) {
                                case ';':
@@ -320,6 +428,8 @@
                                case T_IS_NOT_EQUAL: // !=
                                case T_IS_IDENTICAL: // ===
                                case T_IS_NOT_IDENTICAL: // !==
+                               case '?':
+                               case ':':
                                        $expected = array(
                                                T_CONSTANT_ENCAPSED_STRING, // 
"foo" or 'bar'
                                                T_ENCAPSED_AND_WHITESPACE, // " 
$a"
@@ -347,7 +457,7 @@
                                                $expectCurlyClose = true;
                                                $expected = array( T_VARIABLE );
                                        } else {
-                                               $return .= '<br><span 
class="error">' . wfMessage( 'foxway-php-syntax-error-unexpected', '\' { \'', 
$line )->escaped() . '</span>';
+                                               $return .= '<br><span 
class="error" title="' . __LINE__ . '">' . wfMessage( 
'foxway-php-syntax-error-unexpected', '\' { \'', $line )->escaped() . '</span>';
                                                break 2;
                                        }
                                        break;
@@ -364,7 +474,7 @@
                                                        '"',
                                                        );
                                        } else {
-                                               $return .= '<br><span 
class="error">' . wfMessage( 'foxway-php-syntax-error-unexpected', '\' } \'', 
$line )->escaped() . '</span>';
+                                               $return .= '<br><span 
class="error" title="' . __LINE__ . '">' . wfMessage( 
'foxway-php-syntax-error-unexpected', '\' } \'', $line )->escaped() . '</span>';
                                                break 2;
                                        }
                                        break;
diff --git a/includes/Runtime.php b/includes/Runtime.php
index 3ac793a..7340f34 100644
--- a/includes/Runtime.php
+++ b/includes/Runtime.php
@@ -39,7 +39,6 @@
                array('|'),
                array('&&'),
                array('||'),
-               array('?', ':'),
        );
 
        private function getOperatorPrecedence( $operator ) {
@@ -93,7 +92,7 @@
                        $this->mathMemory[$precedence] = 
array($this->lastOperator, $this->lastParam);
                        $this->lastOperator = false;
                } elseif( !is_null($this->lastParam) ) {
-                       $this->listParams[] = $this->lastParam;
+                       $this->listParams[] = $this->lastParam; // TODO:it 
seems that this is unnecessary
                }
                $this->lastParam = $param;
                $this->doMath(0);
@@ -138,7 +137,7 @@
                }
        }
 
-       private function doMath( $precedence = 12 ) { //12 = 
count($operatorsPrecedence)-1
+       private function doMath( $precedence = 11 ) { //11 = 
count($operatorsPrecedence)-1
                if( isset($this->mathMemory[0]) ) {
                        while( $mathZerroMemory = 
array_pop($this->mathMemory[0]) ) {
                                $this->doOperation($mathZerroMemory);
@@ -241,6 +240,13 @@
 //\MWDebug::log( "function doOperation('$operator', '$param') @ 
'$this->lastParam'");
        }
 
+       public function getMathResult() {
+               $this->doMath();
+               $return = $this->lastParam;
+               $this->lastParam = null;
+               return $return;
+       }
+
        public function getCommandResult( &$debug ) {
 //             \MWDebug::log('function getCommandResult()');
                $this->doMath();
diff --git a/tests/phpunit/includes/InterpreterTest.php 
b/tests/phpunit/includes/InterpreterTest.php
index 4ff2c6a..7cbba63 100644
--- a/tests/phpunit/includes/InterpreterTest.php
+++ b/tests/phpunit/includes/InterpreterTest.php
@@ -552,4 +552,53 @@
                                );
        }
 
+       public function testRun_echo_ternary_1() {
+               $this->assertEquals(
+                               Interpreter::run('echo true?"true":"false";'),
+                               'true'
+                               );
+       }
+       public function testRun_echo_ternary_2() {
+               $this->assertEquals(
+                               Interpreter::run('echo false?"true":"false";'),
+                               'false'
+                               );
+       }
+       public function testRun_echo_ternary_3() {
+               $this->assertEquals(
+                               Interpreter::run('echo 
true?"true":false?"t":"f";'),
+                               't'
+                               );
+       }
+       public function testRun_echo_ternary_4() {
+               $this->assertEquals(
+                               Interpreter::run('echo 
false?"true":false?"t":"f";'),
+                               'f'
+                               );
+       }
+       public function testRun_echo_ternary_5() {
+               $this->assertEquals(
+                               Interpreter::run('echo 
true?true?"true":false:false?"t":"f";'),
+                               't'
+                               );
+       }
+       public function testRun_echo_ternary_6() {
+               $this->assertEquals(
+                               Interpreter::run('echo 
true?true?false:false:false?"t":"f";'),
+                               'f'
+                               );
+       }
+       public function testRun_echo_ternary_7() {
+               $this->assertEquals(
+                               Interpreter::run('echo 
true?true?"true":false:"false";'),
+                               'true'
+                               );
+       }
+       public function testRun_echo_ternary_8() {
+               $this->assertEquals(
+                               Interpreter::run('echo 
false?true?false:false:"false";'),
+                               'false'
+                               );
+       }
+
 }

-- 
To view, visit https://gerrit.wikimedia.org/r/58657
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ic7b4b5092628ee2446f6ab6f75d4080a28c2bcc5
Gerrit-PatchSet: 4
Gerrit-Project: mediawiki/extensions/Foxway
Gerrit-Branch: master
Gerrit-Owner: Pastakhov <[email protected]>
Gerrit-Reviewer: Hashar <[email protected]>
Gerrit-Reviewer: Pastakhov <[email protected]>
Gerrit-Reviewer: jenkins-bot

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to