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