<?php
/**************************************************
 *                 Kalkulator RPN                 *
 **************************************************
 * Ostatnia modyfikacja: 01.11.2012 (wersja 1.0)  *
 * Autor: Jacek Kowalski (http://jacekk.info)     *
 *                                                *
 * Strona WWW: http://jacekk.info/scripts/rpn     *
 *                                                *
 * Utwór rozprowadzany na licencji                *
 * http://creativecommons.org/licenses/by-nc/2.5/ *
 **************************************************/

/* Kodowanie znaków UTF-8 */

function test($wyr) {
    if(
substr_count($in'(')!==substr_count($in')')) {
        return 
FALSE;
    }
    return 
trim($wyr'+-*/^ 0123456789.,()')==='';
}

$test test($_GET['wyrazenie']);

if(!
$_GET['wyrazenie'] OR strlen($_GET['wyrazenie'])>60 OR !$test) {
?>
<form action="" method="get">
<?php if(!$test) {echo '<p><strong>Błąd w wyrażeniu</strong></p>'.$test."\n";} ?>
<input type="text" name="wyrazenie"/> <input type="submit" value="Oblicz"/>
<hr/>
<ul>
<li>Dostępne operatory: + - * / ^ ( )</li>
<?php if(strlen($_GET['wyrazenie'])>100) {echo '<li><strong>Maksymalna ilość znaków: 60</strong></li>'."\n";}
else {echo 
'<li>Maksymalna ilość znaków: 60</li>'."\n";} ?>
<li>Algorytm: Odwrotna Notacja Polska</li>
<li>Autor: <a href="http://jacekk.info">Jacek Kowalski</a></li>
</ul>
</form>
<?php
    
die(0);
}

function 
prior($op) {
    
$prior = array('+' => 1'-' => 1'*' => 2'/' => 2'^' => 3);

    return 
$prior[$op];
}

function 
error($msg$code) {
    echo 
'<p>Błąd '.$code.': '.$msg.'</p>';
}

function 
onp_1($in) {
    
$err = array('10' => 'Nierozpoznany znak''11' => 'Nieprawidłowa ilość nawiasów');

    
$out = array();
    
$stos = array();
    
$tmp '';

    
$in str_split($in);

    foreach(
$in as $v) {
        if(
is_numeric($v) OR $v==',' OR $v=='.') {
            if(
$v==','$v '.';
            
$tmp .= $v;
        }
        elseif(
$v=='(') {
            if(!empty(
$tmp)) {
                
$out[] = $tmp;
                
$tmp '';
            }

            
array_push($stos'(');
        }
        elseif(
$v==')') {
            if(!empty(
$tmp)) {
                
$out[] = $tmp;
                
$tmp '';
            }

            while(
TRUE) {
                
$wyr array_pop($stos);

                if(
$wyr==NULL) {
                    
error($err['11'], 11);
                    die(
11);
                }
                if(
$wyr!=='(') {
                    
$out[] = $wyr;
                }
                else
                {
                    break;
                }
            }
        }
        elseif(
$v=='+' OR $v=='-' OR $v=='*' OR $v=='/') {
            
$tmp_prior prior($v);

            if(!empty(
$tmp)) {
                
$out[] = $tmp;
                
$tmp '';
            }

            while(
TRUE) {
                
$wyr array_pop($stos);

                if(
$wyr==NULL) {
                    
array_push($stos$v);
                    break;
                }
                elseif(
prior($wyr)<$tmp_prior) {
                    
array_push($stos$wyr$v);
                    break;
                }
                else
                {
                    
$out[] = $wyr;
                }
            }
        }
        elseif(
$v=='^') {
            if(!empty(
$tmp)) {
                
$out[] = $tmp;
                
$tmp '';
            }

            
array_push($stos$v);
        }
        elseif(
$v==' ') {
            continue;
        }
        else
        {
            
error($err['10'].': \''.$v.'\', kod: '.ord($v), 10);
        }
    }

    if(!empty(
$tmp)) {
        
$out[] = $tmp;
        
$tmp '';
    }

    while(
TRUE) {
        
$wyr array_pop($stos);

        if(
$wyr==NULL) {
            break;
        }
        else
        {
            
$out[] = $wyr;
        }
    }

    return 
$out;
}

function 
onp_2($in) {
    
$stos = array();

    foreach(
$in as $val) {
        if(
is_numeric($val)) {
            
array_push($stos$val);
        }
        else
        {
            
$a array_pop($stos);
            
$b array_pop($stos);
            switch(
$val) {
                case 
'+':
                    
array_push($stosbcadd($b$a10));
                break;
                case 
'-':
                    
array_push($stosbcsub($b$a10));
                break;
                case 
'*':
                    
array_push($stosbcmul($b$a10));
                break;
                case 
'/':
                    
array_push($stosbcdiv($b$a10));
                break;
                case 
'^':
                    
array_push($stosbcpow($b$a10));
                break;
                default:
                    
error('Nierozpoznany znak: '.$val10);
                break;
            }
        }
    }

    return 
array_pop($stos);
}

$res1 onp_1($_GET['wyrazenie']);
$res2 onp_2($res1);

?>
<form action="" method="get">
<input type="text" name="wyrazenie"/> <input type="submit" value="Oblicz"/>
<hr/>
<pre><?php echo htmlspecialchars($_GET['wyrazenie']).' = '.implode(' '$res1).' = '.$res2?></pre>
<hr/>
<ul>
<li>Dostępne operatory: + - * / ^ ( )</li>
<li>Maksymalna ilość znaków: 60</li>
<li>Algorytm: Odwrotna Notacja Polska</li>
<li>Autor: <a href="http://jacekk.info">Jacek Kowalski</a></li>
</ul>
</form>