Jump to content

User:AzaToth/Logic

From Meta, a Wikimedia project coordination wiki

Documentation

[edit]

Purpose

[edit]

A simple, probably fast computation engine for wiki

Functions

[edit]
  • if
  • switch
  • map
  • join
  • par
  • pars
  • npars

String Operators

[edit]
  • eq
  • ne

Arithmetic operators

[edit]
  • add
  • sub
  • mul
  • div
  • mod
  • sl
  • sr

Boolean operators

[edit]
  • and
  • or
  • xor
  • nand
  • nor
  • nxor
  • not

Examples

[edit]

Some test examples I made that worked as expected:

{{test|E|d|F|ddd|c|r|e|b|d}}
{{test|A}}
{#add|2|5#}
{#sub|2|5#}
{#mul|2|5#}
{#div|2|5#}
{#div|2|0#}
{#mod|7|3#}
{#sl|16|2#}
{#sr|16|2#}

----
{#par|*#}
----
{#npars#}

and it using template test containing

:''Main page{#if|{#gt|{#npars#}|1#}|s#}: {#[!]map!![[!]]!, !{#[!]pars!*#}#}''

resulted in (mark copy):

    Main pages: E, d, F, ddd, c, r, e, b, d 

    Main page: A 

7 -3 10 0.4 NaN 1 64 4

0

{#[long idiotic delimiter]switch
  long idiotic delimiterbar
  long idiotic delimitercase foo: hello
  long idiotic delimitercase bar: world
  long idiotic delimiterdefault: nooo
#}

gives "world"

Code

[edit]

Add this after array_push( $this->mArgStack, $args ); in Parser::replaceVariables

        if($this->mOutputType == OT_HTML) {
            $l = new Logic();
            $text = $l->processText($args, $text);
        }

The main code is:

<?php
    class Logic {
        var $args;
        var $text;

        function Logic() {
        }

        function processText($args, $text) {
            $this->args = $args;
            $this->text = $text;

            // Replace until we are "done".
            while(strstr($text,'{#')) {
                $old_text = $text;
                $text = preg_replace_callback('|\{#(?:(?!.*?\{#))(.*?)#\}|s',array(&$this, 'replaceFunctions'), $text);
                if($old_text == $text) { // We are stuck in a while loop, scream out loud and halt...
                $text .= "'''Error''': Stuck in a while loop, aborting!";
                break;
                }
            }
            return $text;
        }
        function replaceFunctions($matches) {
            $block = $matches[1];
            static $counter;
            $delimiter = '|'; // What to split on, | per default, specified as {#[delimiter]function...#}
            if(preg_match('/^\[(.+?)\]/s',$block,$m)) {
                $block = preg_replace('/^\[.+?\]/s','',$block); // remove the delimiter specification now.
                $delimiter = $m[1];
            }
            $array = explode($delimiter, $block);
            $operand = $array[0];
            $rest = array_slice($array,1);

            switch(trim($operand)) {
                /* Logic Operators */
            case 'eq': // arg 1 is equal arg 2
                if(trim($rest[0]) == trim($rest[1])) return 1;
                else return '';
                break;
            case 'ne': // arg 1 is not equal arg 2
                if(trim($rest[0]) != trim($rest[1])) return 1;
                else return '';
                break;
            case 'ge': // value of arg 1 is greater than or equal to arg 2
                if(trim($rest[0]) >= trim($rest[1])) return 1;
                else return '';		
                break;
            case 'le': // value of arg 1 is lesser than or equal to arg 2
                if(trim($rest[0]) <= trim($rest[1])) return 1;
                else return '';	
                break;
            case 'gt': // value of arg 1 is greater than arg 2
                if(trim($rest[0]) > trim($rest[1])) return 1;
                else return '';		
                break;
            case 'lt': // value of arg 1 is lesser than arg 2
                if(trim($rest[0]) < trim($rest[1])) return 1;
                else return '';	
                break;
            case 'not': // return 1 if arg 1 is null, else return null
                if(trim($rest[0]) != '') return '';
                else return 1;	
                break;
            case 'and': // boolean and
                if(trim($rest[0]) != '' and trim($rest[1]) != '') return 1;
                else return '';
                break;
            case 'or': // boolean or
                if(trim($rest[0]) != '' or trim($rest[1]) != '') return 1;
                else return '';
                break;
            case 'xor': // boolean exclusive or
                if(trim($rest[0]) != '' xor trim($rest[1]) != '') return 1;
                else return '';
                break;
            case 'nand': // boolean not and
                if(trim($rest[0]) != '' and trim($rest[1]) != '') return '';
                else return 1;
                break;
            case 'nor': // boolean not or
                if(trim($rest[0]) != '' or trim($rest[1]) != '') return '';
                else return 1;
                break;
            case 'nxor': // boolean not exclusive or
                if(trim($rest[0]) != '' xor trim($rest[1]) != '') return '';
                else return 1;
                break;
                /* End Logic Operators */
                /* Arthimentic Operators */
            case 'add': // add arg 2 to arg 1
                return trim($rest[0]) + trim($rest[1]);
                break;
            case 'sub': // substract arg 2 from arg 1
                return trim($rest[0]) - trim($rest[1]);
                break;
            case 'mul': // multiply arg 2 with arg 1
                return trim($rest[0]) * trim($rest[1]);
                break;
            case 'div': // divide arg 2 from arg 1
                if(trim($rest[1]) == 0) return 'NaN';
                return trim($rest[0]) / trim($rest[1]);
                break;
            case 'mod': // return the rest of integer division of arg 1 / arg 2
                return trim($rest[0]) % trim($rest[1]);
                break;
            case 'sl': // binary shift left arg 1 with arg 2
                return trim($rest[0]) << trim($rest[1]);
                break;
            case 'sr':// binary shift right arg 1 with arg 2
                return trim($rest[0]) >> trim($rest[1]);
                break;
                /* End Arthimentic Operators */
                /* Functional Operators */
            case 'if': // if arg 1 is not null return arg 2, else return arg 3
                if(trim($rest[0]) != '') return $rest[1];
                else return $rest[2];
                break;
            case 'switch': // if case arg 1: is found in arglist, return it's value, else return default
                $values = array();
                $var = 'case '.trim($rest[0]);
                /**/
                foreach(array_slice($rest,1) as $r) {
                    list($key, $value) = explode(':', $r,2);
                    $values[trim($key)] = $value;
                }
                if(array_key_exists(trim($var), $values)) 
                return trim($values[$var]);
                else
                return trim($values['default']);
                break;

                /**
                * @brief map - Map array to a complex string, ignore empty strings
                * 
                * @param glue - glues keys to values, null if not.
                * @param lwrap - left hand side wrap
                * @param hwrap-  right hand side wrap
                * @param separator - string to separate entities with
                * $param data - and array of data to map
                *
                * @return a mapped string of the input data
                */
            case 'map':                 
                $tmp = array();
                foreach (array_slice($rest,4) as $k => $v)
                {
                    if($v != '') {
                        $tmp[] = ($rest[0] == '' ? '' : ($k . $rest[0])) . $rest[1] . $v . $rest[2];
                    }
                }
                return implode($rest[3], $tmp);
                break;           
                /**
                * @brief a simple join
                * 
                * @param separator - the string to separate the entities
                * @param data - the data to join
                *
                * @return the joined string
                */

            case 'join': 
                return join ($rest[0],array_slice($rest,1));
                break;
                /*
                * @brief return the parameter
                *
                * @param key - the parameter to return
                *
                * @return the parameter
                */
            case 'par':
                if(array_key_exists(trim($rest[0]), $this->args)){
                    return $this->args[trim($rest[0])];
                }
                break;
                /*
                * @brief return a separated list of parameters, if arg1 is '*' then all parameters is returned
                *
                * @param arg1 - offset of parameters
                * @param arg2 - length of parameters
                *
                * @return joined list of parameters
                */
            case 'pars':
                if(is_numeric($rest[0]) and is_numeric($rest[1])){
                    return join($delimiter,array_slice($this->args,$rest[0],$rest[1]));
                } elseif(trim($rest[0]) == '*') {
                    return join($delimiter, $this->args);
                }
                break;

                /*
                * @brief the number of params
                *
                * @return the number of parameters
                */
            case 'npars':
                return sizeof($this->args);
                break;

            default: // highlight illegal code
                return '<span style="color: red;">{#'.strtr($block,'|','|').'#}</span>';
                break;
            }
        }
    }
?>

See also

[edit]

History

[edit]
Created
AzaToth 04:06, 17 December 2005 (UTC)