[PHP] Preg_replace voor if/else condition

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik ben bezig met een hele kleine template engine voor mezelf. (Er zijn er al heel veel, ik doe het dus ook vooral om ervan te leren.)
Er is al heel veel gelukt, maar nu ben ik toch al een paar uur bezig met dit probleem:
Ik heb dus een .html bestand dat 'geparsed' moet worden, dit gebeurt met de volgende regex:
PHP:
1
$parsed=preg_replace_callback('/<!--\{if(\s)([a-zA-Z0-9_\[\]]*)\}-->(.+)<!--\{endif\}-->/isx',array(&$this,'whatif'),$parsed);
de functie 'whatif' kijkt ofdat de var bestaat, en returned de code indien ja, en returned null indien die niet bestaat.
En een html bestand ziet er dan zo uit:
HTML:
1
2
3
<!--{if get_regerror}-->
...code...
<!--{endif}-->
Dit werkt prefect, totdat je meerdere if conditions in het html bestand zet.

VB:
HTML:
1
2
3
4
5
6
<!--{if get_regerror}-->
...code1...
<!--{endif}-->
<!--{if anderevar}-->
...code2...
<!--{endif}-->


Dan gaat de regex vanaf code 1 t.e.m code2 (dus alles ertussen ook) meegeven aan de functie, en dan krijg je uiteraard errors.Ik heb al geprobeerd te kijken naar andere template engines (smarty,..) maar die zijn zo uitgebreid dat ik nooit het juiste stukje code vindt.
Hoe los ik dit op?

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-09 21:24

.oisyn

Moderator Devschuur®

Demotivational Speaker

Hoe los ik dit op?
Niet met een regex. Je template taal is namelijk niet regulier, dus reguliere expressies zijn niet toerijkend.

Wat ik zou doen is met preg_match_all je template opdelen in stukjes content en stukjes commando's. Vervolgens kun je met een vrij simpele stack based parser door de commando's heen lopen en die interpreteren.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Je template taal is namelijk niet regulier, dus reguliere expressies zijn niet toerijkend.
Kan ik hem dan regulier maken?
Want ik vrees dat ik bij dat opsplitsen en stack based parser een voorbeeldje nodig heb.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ok, ik heb al iets meer gelezen over wat je bedoelt, maar ik snap nog steeds niet hoe ik het zou opdelen met preg_match_all, als je zelf zegt dat het niet regulier is.

Acties:
  • 0 Henk 'm!

  • RobertMe
  • Registratie: Maart 2009
  • Laatst online: 10:28
Je probleem is dat PCRE standaard greedy is, en jij wil hem ungreedy hebben, dat ungreedy maken kun je doen door het toevoegen van de U modifier, maar dat is ook nog niet alles, want als je dan gaat nesten, heb je alsnog een probleem. Dan moet je hem al recursief maken, zie php.net voor hoe dat moet (was iets met (?R) dacht ik). Zelf heb ik ook een tijdje gewerkt aan een template parser, en op bovenstaande manier is het mij ook gelukt (dus ook met preg_replace_callback en dan een recursieve match/search)

Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
Waarom gebruik je geen .php files ervoor? Of include je ze in php. Dan kun je gewoon php statements gebruiken in je views.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Cartman! schreef op zondag 28 juni 2009 @ 20:29:
Waarom gebruik je geen .php files ervoor? Of include je ze in php. Dan kun je gewoon php statements gebruiken in je views.
Omdat ik php en presentatie volledig wil scheiden.

Bedankt, RobertMe, die 'U' heeft het gedaan. Als ik nested nodig heb zal ik eens gaan kijken naar die recursive, maar zolang ik het niet nodig heb, implementeer ik het nog niet.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-09 21:24

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op zondag 28 juni 2009 @ 18:57:
Ok, ik heb al iets meer gelezen over wat je bedoelt, maar ik snap nog steeds niet hoe ik het zou opdelen met preg_match_all, als je zelf zegt dat het niet regulier is.
Het feit dat er nestings zijn maakt dat het niet regulier is. Maar als je 'm gewoon opdeelt in stukjes is er geen nesting en wordt het daarmee wel regulier

Iets als
code:
1
2
3
4
5
a
<!--{b}-->
c
<!--{d}-->
e

Kun je dus met een regex opdelen zodat je alles los hebt (dus a, b, c, d, e, waarbij je bovendien weet dat b en d commando's zijn), en vervolgens loop je daar overheen met een stack-based parser.
Verwijderd schreef op zondag 28 juni 2009 @ 21:29:
[...]
Omdat ik php en presentatie volledig wil scheiden.
Nutteloos argument. De wilt de presentatie scheiden van het domein, niet van de taal waar je dat domein hebt geïmplementeerd. Er is niets op tegen om de presentatie ook met PHP te doen. Je template engine kan dan ipv een file parsen zoals je nu doet simpelweg een include doen van een template die in PHP is geschreven. Dan is het sneller én featurecompleet.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • prototype
  • Registratie: Juni 2001
  • Niet online

prototype

Cheer Bear

Je weet dat PHP voor PHP Hypertext Preprocessor staat he? Wat eigenlijk erop neer komt dat PHP zelf een soort template taal al is ;-)...

Acties:
  • 0 Henk 'm!

  • 4Real
  • Registratie: Juni 2001
  • Laatst online: 14-09-2024
PHP:
1
2
3
4
5
<?php

$regex_advanced = '/([a-z|A-Z|0-9|\.|_]+)( )(\>|\<|\=\=)( )([a-z|A-Z|0-9]+)/s';

?>


Werkt met:
code:
1
2
3
4
5
6
7
8
{var1 == var2?}ja het is waar *O*{;}
{var1 == var2?}ja het is waar *O*{:} nee het is niet waar :( {;}

{var1 == var2?a}
    {var2 == var3?b}
        jeej het is allemaal waar *O* *O*
    {;b}
{;a}


Test het met een preg_match en kijk maar wat je krijgt :P

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-09 21:24

.oisyn

Moderator Devschuur®

Demotivational Speaker

Wat wil je nou eigenlijk zeggen met die imho vrij nutteloze regex?

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
.oisyn schreef op zondag 28 juni 2009 @ 22:09:
.. Dan is het sneller én featurecompleet.
Ik wil juist niet dat het featurecompleet is, en sneller wordt opgelost met caching.

Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Ik zou persoonlijk toch gewoon gaan voor iets als
code:
1
/<!--\{if ([a-z0-9_[\]]*+)}-->((?:[^<]|(?R)|<(?!!--\{endif}-->))*+)<!--\{endif}-->/i

En dan recursief dat pattern toepassen in de callback-functie. Test maar uit met http://www.alexnj.com/regexlab/ anders. Voorbeeld dat werkt:
code:
1
2
3
4
5
6
7
<!--{if get_regerror}-->
...code...
<!--{if get_regerror}-->
...code2...
<!--{endif}-->
...code3...
<!--{endif}-->


Zie hier voor uitleg over (?R). *+ wordt helaas niet bij PHP zelf uitgelegd, hier bijvoorbeeld wel. Het is belangrijk om backtracking geen kans te geven, aangezien anders zomaar je server vast kan lopen op dit soort zaken.

Het is trouwens niet helemaal ideaal, omdat je dezelfde tekst met dezelfde reguliere expressie meerdere keren door moet. Vooral bij lange 'code', en/of veel nesting zal een stack-based parser daarom sneller zijn. Bij vrij weinig code is dit sneller verwacht ik. Aangezien ik vrij weinig code verwacht tussen if-endif, zou ik hiervoor gaan. Als je complete pagina's tussen if en endif hebt, dan wordt het tijd voor benchmarking. Aan de andere kant zal caching simpel zijn en boeit het niet zoveel.. ;)

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Verwijderd schreef op woensdag 01 juli 2009 @ 00:41:
[...]
Ik wil juist niet dat het featurecompleet is
Waarom wil je het niet feature compleet hebben? Ben je bang voor misbruik?
en sneller wordt opgelost met caching.
En waarom zou dat niet met PHP templates kunnen?

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”

Pagina: 1