[PHP]Legale if statement opbouwen

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • ZeroXT
  • Registratie: December 2007
  • Laatst online: 21:43
Ik ben voor mezelf een templateparser aan het maken in PHP (omdat het kan). Alle functies die ik erin wil hebben zitten er inmiddels in, echter kom ik met een volgend probleem.

Ik ga voor elke regel kijken of er een {if} statement in zit. De expressie haal ik eruit met preg_match en sla ik op in een variabele.

Die expressie moet alleen gevalideerd worden of er geen ongeldige karakters inzitten. Ik kan namelijk met eval() testen of de expressie true of false is maar dat kan problemen opleveren op moment dat er illegale karakters inzitten.

Ik zie dat sommige een wrapper functie gebruiken.

Ik was al eerder zoiets als dit aan het maken:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
private function validateIf($if, $regelnummer)
    {
        $statement = '';
        
        foreach(explode(' ', $if) as $stuk)
        {
            if(strlen($stuk) > 0)
            {
                //Not operator (!)
                if($stuk[0] == '!' && !in_array($stuk, array('!=', '!==')))
                {
                    $statement .= '!';
                    
                    if(strlen($stuk) > 1)
                    {
                        $stuk = substr($stuk, 1);
                    }
                }
                
                //Variabel
                if($stuk[0] == '$')
                {
                    $statement .= isset($this -> waardes[ltrim($stuk, '$')]) ? $this -> waardes[ltrim($stuk, '$')] . ' ' : 'false' . ' ';
                }
                //Functie
                elseif(preg_match('/([a-z_]+)\(\$(.*)\)/', $stuk, $functie))
                {
                    if(in_array($functie[1], $this -> functieLijst))
                    {
                        $statement .= isset($this -> waardes[$functie[2]]) ? call_user_func($functie[1], $this -> waardes[$functie[2]]) . ' ' : 'false' . ' ';
                    }
                    else
                    {
                        return $this -> error('Function "'. $functie[1] .'" not supported on line ' . ++$regelnummer);
                    }
                }
                //Numeric, gates, operator, boolean
                elseif(is_numeric($stuk) || preg_match('/(\|\||&&|OR|AND|NOT|NAND|NOR|EOR)+/i', $stuk) || in_array($stuk, $this -> operators) || in_array($stuk, array('true', 'false')))
                {
                    $statement .= $stuk . ' ';
                }
                //Constante
                elseif(preg_match('/^[a-z0-9_]+$/i', $stuk, $match))
                {
                    $statement .= defined($match[0]) ? $stuk . ' ' : 'false ';
                }
                //Error
                else
                {
                    return $this -> error('If tag is not valid on line ' . ++$regelnummer);
                }
            }
        }

        return $statement;
    }


Dit is het echter niet want dit controleert niet het een geldige if statement is. Het maakt geen onderscheid in "1 >= 1" of ">= 1 1"

Wat is nu de handigste manier om dit te testen/maken? :)

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 14-07 21:33

NMe

Quia Ego Sic Dico.

Eval misschien? Returnt false bij een parse-fout. Je moet dan wel bij if (1 == 1) je eval schrijven als $var = @eval('return (1 == 1);'); en vervolgens checken of $var = @eval('return !(1 == 1);'); (let op het uitroepteken) true geeft als de eerste eval false geeft omdat je natuurlijk ook gewoon false uit je expressie kan krijgen.

Dus de logica: eerst kijken of de eerste expressie true of false geeft. Is hij true, dan is 't sowieso valid. Is 'ie false, dan check je eerst of het omgekeerde van de expressie wél true is. Zo ja, dan is die ook valid, zo nee, dan niet.

De @ is nodig omdat een parse-error in de eval anders je hele script stopt in plaats van false te returnen.

[ Voor 9% gewijzigd door NMe op 05-10-2012 14:53 ]

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
ZeroXT schreef op vrijdag 05 oktober 2012 @ 13:52:
Wat is nu de handigste manier om dit te testen/maken? :)
Ik zou eens kijken naar een tokenizer.

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 14-07 21:33

NMe

Quia Ego Sic Dico.

Dat is sowieso een beter idee, maar daar wil je vervolgens in je hele engine gebruik van maken, niet alleen voor het checken van ifs.

En ja, Rob, ik wéét dat jij dat ook weet. :P

[ Voor 17% gewijzigd door NMe op 05-10-2012 14:20 ]

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Wolfboy
  • Registratie: Januari 2001
  • Niet online

Wolfboy

ubi dubium ibi libertas

Tokenizen is wel _de_ manier om dit op te lossen ja. Al zal je het op deze manier ook wel werkend krijgen, leesbaarder gaat het er niet van worden ;)

Blog [Stackoverflow] [LinkedIn]