]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blobdiff - includes/cbt/CBTCompiler.php
MediaWiki 1.16.0
[autoinstallsdev/mediawiki.git] / includes / cbt / CBTCompiler.php
diff --git a/includes/cbt/CBTCompiler.php b/includes/cbt/CBTCompiler.php
deleted file mode 100644 (file)
index 7595579..0000000
+++ /dev/null
@@ -1,366 +0,0 @@
-<?php
-
-/**
- * This file contains functions to convert callback templates to other languages.
- * The template should first be pre-processed with CBTProcessor to remove static
- * sections.
- */
-
-
-require_once( dirname( __FILE__ ) . '/CBTProcessor.php' );
-
-/**
- * Push a value onto the stack
- * Argument 1: value
- */
-define( 'CBT_PUSH', 1 );
-
-/**
- * Pop, concatenate argument, push
- * Argument 1: value
- */
-define( 'CBT_CAT', 2 );
-
-/**
- * Concatenate where the argument is on the stack, instead of immediate
- */
-define( 'CBT_CATS', 3 );
-
-/**
- * Call a function, push the return value onto the stack and put it in the cache
- * Argument 1: argument count
- *
- * The arguments to the function are on the stack
- */
-define( 'CBT_CALL', 4 );
-
-/**
- * Pop, htmlspecialchars, push
- */
-define( 'CBT_HX', 5 );
-
-class CBTOp {
-       var $opcode;
-       var $arg1;
-       var $arg2;
-
-       function CBTOp( $opcode, $arg1, $arg2 ) {
-               $this->opcode = $opcode;
-               $this->arg1 = $arg1;
-               $this->arg2 = $arg2;
-       }
-
-       function name() {
-               $opcodeNames = array(
-                       CBT_PUSH => 'PUSH',
-                       CBT_CAT => 'CAT',
-                       CBT_CATS => 'CATS',
-                       CBT_CALL => 'CALL',
-                       CBT_HX => 'HX',
-               );
-               return $opcodeNames[$this->opcode];
-       }
-};
-
-class CBTCompiler {
-       var $mOps = array();
-       var $mCode;
-
-       function CBTCompiler( $text ) {
-               $this->mText = $text;
-       }
-
-       /**
-        * Compile the text.
-        * Returns true on success, error message on failure
-        */
-       function compile() {
-               $this->mLastError = false;
-               $this->mOps = array();
-
-               $this->doText( 0, strlen( $this->mText ) );
-
-               if ( $this->mLastError !== false ) {
-                       $pos = $this->mErrorPos;
-
-                       // Find the line number at which the error occurred
-                       $startLine = 0;
-                       $endLine = 0;
-                       $line = 0;
-                       do {
-                               if ( $endLine ) {
-                                       $startLine = $endLine + 1;
-                               }
-                               $endLine = strpos( $this->mText, "\n", $startLine );
-                               ++$line;
-                       } while ( $endLine !== false && $endLine < $pos );
-
-                       $text = "Template error at line $line: $this->mLastError\n<pre>\n";
-
-                       $context = rtrim( str_replace( "\t", " ", substr( $this->mText, $startLine, $endLine - $startLine ) ) );
-                       $text .= htmlspecialchars( $context ) . "\n" . str_repeat( ' ', $pos - $startLine ) . "^\n</pre>\n";
-               } else {
-                       $text = true;
-               }
-
-               return $text;
-       }
-
-       /** Shortcut for doOpenText( $start, $end, false */
-       function doText( $start, $end ) {
-               return $this->doOpenText( $start, $end, false );
-       }
-
-       function phpQuote( $text ) {
-               return "'" . strtr( $text, array( "\\" => "\\\\", "'" => "\\'" ) ) . "'";
-       }
-
-       function op( $opcode, $arg1 = null, $arg2 = null) {
-               return new CBTOp( $opcode, $arg1, $arg2 );
-       }
-
-       /**
-        * Recursive workhorse for text mode.
-        *
-        * Processes text mode starting from offset $p, until either $end is
-        * reached or a closing brace is found. If $needClosing is false, a
-        * closing brace will flag an error, if $needClosing is true, the lack
-        * of a closing brace will flag an error.
-        *
-        * The parameter $p is advanced to the position after the closing brace,
-        * or after the end. A CBTValue is returned.
-        *
-        * @private
-        */
-       function doOpenText( &$p, $end, $needClosing = true ) {
-               $in =& $this->mText;
-               $start = $p;
-               $atStart = true;
-
-               $foundClosing = false;
-               while ( $p < $end ) {
-                       $matchLength = strcspn( $in, CBT_BRACE, $p, $end - $p );
-                       $pToken = $p + $matchLength;
-
-                       if ( $pToken >= $end ) {
-                               // No more braces, output remainder
-                               if ( $atStart ) {
-                                       $this->mOps[] = $this->op( CBT_PUSH, substr( $in, $p ) );
-                                       $atStart = false;
-                               } else {
-                                       $this->mOps[] = $this->op( CBT_CAT, substr( $in, $p ) );
-                               }
-                               $p = $end;
-                               break;
-                       }
-
-                       // Output the text before the brace
-                       if ( $atStart ) {
-                               $this->mOps[] = $this->op( CBT_PUSH, substr( $in, $p, $matchLength ) );
-                               $atStart = false;
-                       } else {
-                               $this->mOps[] = $this->op( CBT_CAT, substr( $in, $p, $matchLength ) );
-                       }
-
-                       // Advance the pointer
-                       $p = $pToken + 1;
-
-                       // Check for closing brace
-                       if ( $in[$pToken] == '}' ) {
-                               $foundClosing = true;
-                               break;
-                       }
-
-                       // Handle the "{fn}" special case
-                       if ( $pToken > 0 && $in[$pToken-1] == '"' ) {
-                               $this->doOpenFunction( $p, $end );
-                               if ( $p < $end && $in[$p] == '"' ) {
-                                       $this->mOps[] = $this->op( CBT_HX );
-                               }
-                       } else {
-                               $this->doOpenFunction( $p, $end );
-                       }
-                       if ( $atStart ) {
-                               $atStart = false;
-                       } else {
-                               $this->mOps[] = $this->op( CBT_CATS );
-                       }
-               }
-               if ( $foundClosing && !$needClosing ) {
-                       $this->error( 'Errant closing brace', $p );
-               } elseif ( !$foundClosing && $needClosing ) {
-                       $this->error( 'Unclosed text section', $start );
-               } else {
-                       if ( $atStart ) {
-                               $this->mOps[] = $this->op( CBT_PUSH, '' );
-                       }
-               }
-       }
-
-       /**
-        * Recursive workhorse for function mode.
-        *
-        * Processes function mode starting from offset $p, until either $end is
-        * reached or a closing brace is found. If $needClosing is false, a
-        * closing brace will flag an error, if $needClosing is true, the lack
-        * of a closing brace will flag an error.
-        *
-        * The parameter $p is advanced to the position after the closing brace,
-        * or after the end. A CBTValue is returned.
-        *
-        * @private
-        */
-       function doOpenFunction( &$p, $end, $needClosing = true ) {
-               $in =& $this->mText;
-               $start = $p;
-               $argCount = 0;
-
-               $foundClosing = false;
-               while ( $p < $end ) {
-                       $char = $in[$p];
-                       if ( $char == '{' ) {
-                               // Switch to text mode
-                               ++$p;
-                               $this->doOpenText( $p, $end );
-                               ++$argCount;
-                       } elseif ( $char == '}' ) {
-                               // Block end
-                               ++$p;
-                               $foundClosing = true;
-                               break;
-                       } elseif ( false !== strpos( CBT_WHITE, $char ) ) {
-                               // Whitespace
-                               // Consume the rest of the whitespace
-                               $p += strspn( $in, CBT_WHITE, $p, $end - $p );
-                       } else {
-                               // Token, find the end of it
-                               $tokenLength = strcspn( $in, CBT_DELIM, $p, $end - $p );
-                               $this->mOps[] = $this->op( CBT_PUSH, substr( $in, $p, $tokenLength ) );
-
-                               // Execute the token as a function if it's not the function name
-                               if ( $argCount ) {
-                                       $this->mOps[] = $this->op( CBT_CALL, 1 );
-                               }
-
-                               $p += $tokenLength;
-                               ++$argCount;
-                       }
-               }
-               if ( !$foundClosing && $needClosing ) {
-                       $this->error( 'Unclosed function', $start );
-                       return '';
-               }
-
-               $this->mOps[] = $this->op( CBT_CALL, $argCount );
-       }
-
-       /**
-        * Set a flag indicating that an error has been found.
-        */
-       function error( $text, $pos = false ) {
-               $this->mLastError = $text;
-               if ( $pos === false ) {
-                       $this->mErrorPos = $this->mCurrentPos;
-               } else {
-                       $this->mErrorPos = $pos;
-               }
-       }
-
-       function getLastError() {
-               return $this->mLastError;
-       }
-
-       function opsToString() {
-               $s = '';
-               foreach( $this->mOps as $op ) {
-                       $s .= $op->name();
-                       if ( !is_null( $op->arg1 ) ) {
-                               $s .= ' ' . var_export( $op->arg1, true );
-                       }
-                       if ( !is_null( $op->arg2 ) ) {
-                               $s .= ' ' . var_export( $op->arg2, true );
-                       }
-                       $s .= "\n";
-               }
-               return $s;
-       }
-
-       function generatePHP( $functionObj ) {
-               $fname = 'CBTCompiler::generatePHP';
-               wfProfileIn( $fname );
-               $stack = array();
-
-               foreach( $this->mOps as $op ) {
-                       switch( $op->opcode ) {
-                               case CBT_PUSH:
-                                       $stack[] = $this->phpQuote( $op->arg1 );
-                                       break;
-                               case CBT_CAT:
-                                       $val = array_pop( $stack );
-                                       array_push( $stack, "$val . " . $this->phpQuote( $op->arg1 ) );
-                                       break;
-                               case CBT_CATS:
-                                       $right = array_pop( $stack );
-                                       $left = array_pop( $stack );
-                                       array_push( $stack, "$left . $right" );
-                                       break;
-                               case CBT_CALL:
-                                       $args = array_slice( $stack, count( $stack ) - $op->arg1, $op->arg1 );
-                                       $stack = array_slice( $stack, 0, count( $stack ) - $op->arg1 );
-
-                                       // Some special optimised expansions
-                                       if ( $op->arg1 == 0 ) {
-                                               $result = '';
-                                       } else {
-                                               $func = array_shift( $args );
-                                               if ( substr( $func, 0, 1 ) == "'" &&  substr( $func, -1 ) == "'" ) {
-                                                       $func = substr( $func, 1, strlen( $func ) - 2 );
-                                                       if ( $func == "if" ) {
-                                                               if ( $op->arg1 < 3 ) {
-                                                                       // This should have been caught during processing
-                                                                       return "Not enough arguments to if";
-                                                               } elseif ( $op->arg1 == 3 ) {
-                                                                       $result = "(({$args[0]} != '') ? ({$args[1]}) : '')";
-                                                               } else {
-                                                                       $result = "(({$args[0]} != '') ? ({$args[1]}) : ({$args[2]}))";
-                                                               }
-                                                       } elseif ( $func == "true" ) {
-                                                               $result = "true";
-                                                       } elseif( $func == "lbrace" || $func == "{" ) {
-                                                               $result = "{";
-                                                       } elseif( $func == "rbrace" || $func == "}" ) {
-                                                               $result = "}";
-                                                       } elseif ( $func == "escape" || $func == "~" ) {
-                                                               $result = "htmlspecialchars({$args[0]})";
-                                                       } else {
-                                                               // Known function name
-                                                               $result = "{$functionObj}->{$func}(" . implode( ', ', $args ) . ')';
-                                                       }
-                                               } else {
-                                                       // Unknown function name
-                                                       $result = "call_user_func(array($functionObj, $func), " . implode( ', ', $args ) . ' )';
-                                               }
-                                       }
-                                       array_push( $stack, $result );
-                                       break;
-                               case CBT_HX:
-                                       $val = array_pop( $stack );
-                                       array_push( $stack, "htmlspecialchars( $val )" );
-                                       break;
-                               default:
-                                       return "Unknown opcode {$op->opcode}\n";
-                       }
-               }
-               wfProfileOut( $fname );
-               if ( count( $stack ) !== 1 ) {
-                       return "Error, stack count incorrect\n";
-               }
-               return '
-                       global $cbtExecutingGenerated;
-                       ++$cbtExecutingGenerated;
-                       $output = ' . $stack[0] . ';
-                       --$cbtExecutingGenerated;
-                       return $output;
-                       ';
-       }
-}