[ALG] Vragen over principes template parser

Pagina: 1
Acties:

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Enthousiast ben ik een paar dagen geleden begonnen met het schrijven van een eigen template parsertje. Hoever ben ik nu:

• al mijn php functies die beginnen met "macro_" kunnen geven de gebruiker van het cms'je (=ik ;)) de mogelijkheid dynamische content toe te voegen aan de website, bijvoorbeeld:
PHP:
1
2
3
4
5
6
function macro_time($intro) {
  return $intro.': '.time();
}

/* als je in het template bestand (of in een post op de website) de macro 
[time|Het is nu] zet, wordt dit geparsed naar "Het is nu: 1113942557" */

• de hele website draait op een template bestand waar macro-tags op bovenstaande manier worden vervangen door de echte content:
code:
1
2
3
4
5
6
7
8
9
10
/* template (komt uit database of van filesystem): */

<html>
  <body>
    <div id="menu">[menu]</div>
    <div id="content">[content]</div>
  </body>
</html>

/* [menu] wordt vervangen door de output van de functie macro_menu(), etc */

• de macros worden vervangen door de functie output door een regel als $text = str_replace($macro, $expaned_macro, $text);

Mijn grootste probleem: als iemand een [content]-macro in bijvoorbeeld een comment of guestbook entry zet, slaat de webserver op hol (immers: eeuwige loop). Nu kan ik wel per macro gaan aangeven "deze macro kan/mag alleen gebruikt worden in de template zelf, niet in content-delen", maar er moet toch een intelligentere manier zijn om dat eeuwige-loop probleem te voorkomen?

Ik heb gezocht op de search op "template parser", en kwam veel topics tegen over recursieve en stackbased parsers. Wellicht ligt het aan mijn nog te beperkte php kennis, maar ik kwam er niet uit wat nu:

• de principes zijn waar elke parser aan moet voldoen
• wat een stackbased parser is
• of mijn probleem common is en hoe het opgelost kan worden

Graag enige aanwijzingen in deze richting :)

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


  • Daos
  • Registratie: Oktober 2004
  • Niet online
Ik zal proberen je 2e punt te beantwoorden. Het is voor mij ook weer een tijdje geleden dat ik het heb moeten leren.

Parsen heeft iets met een compiler te maken. Een parser is het deel van de compiler dat van tokens een boom (soort linked list) maakt.
De tokens worden gemaakt door lexical analyser. Dat ding herkent keywords, string constanten, identifiers enz... en maakt er een getal van. (0 - 255 zijn losse characters. Eerste token is 256).

Neem als grammar bijvoorbeeld:
BoolExpr = NOT BoolExpr | FALSE | TRUE

"NOT NOT FALSE" wordt door parser in zo'n soort boom gezet:
code:
1
2
3
4
5
6
7
BoolExpr 
soort = Not
arg = --------> BoolExpr 
                soort = Not
                arg = --------> BoolExpr 
                                soort = False
                                arg = 0



Parsers zijn in twee soorten te verdelen: de top-down en bottom-up parsers.
- De top-down parser (LL(1)) is de recursieve. Als de herkenBoolExpr de token NOT in het voorbeeld tekenkomt, dan roept deze functie zichzelf weer aan om het argument van de NOT te herkennen.

- De bottom-up parser (LR(1) of LALR(1) (yacc/bison)) is de stackbased parser. De parser zet alle tokens op een soort stack totdat hij iets helemaal herkend heeft. De stack ziet er ongeveer zo uit.
1 NOT
2 NOT NOT
3 NOT NOT FALSE
4 NOT NOT BoolExpr
5 NOT BoolExpr
6 BoolExpr
Voor stap 1, 2, 3 is niets herkend en daarom wordt er een extra token gelezen (Shift). Na stap 3, 4, 5 wordt er iets herkend (Reduce).


Als je zoiets wilt gebruiken, dan moet je het hele html bestand parsen. Daarbij moet je rekening houden met de uitbreidingen (bv [menu]) die jij hebt gemaakt op html.

"$text = str_replace($macro, $expaned_macro, $text);" lijkt mij goed genoeg voor een paar macro's.

Verwijderd

Even als reactie op je voorbeeld:

Is het niet een beetje overbodig om de macro_time functie de parameter $intro te geven?

Kun je in plaats van:

code:
1
[time|Het is nu]

niet veel beter:
code:
1
Het is nu [time]

schrijven?

(Ik ga nu de rest van je post lezen... ;))

-- 8< -- later --
Reveller schreef op dinsdag 19 april 2005 @ 22:47:
Mijn grootste probleem: als iemand een [content]-macro in bijvoorbeeld een comment of guestbook entry zet, slaat de webserver op hol (immers: eeuwige loop).
Zou je dit verder toe kunnen lichten? Ik zie de "immers" niet per sé; grote kans dat je je implementatie aan kunt passen zodat het wel werkt.

[ Voor 45% gewijzigd door Verwijderd op 20-04-2005 00:33 ]


  • Michali
  • Registratie: Juli 2002
  • Laatst online: 22-03 18:12
Je zou per macro alle output kunnen opvangen met ob_ functies en dan de inhoud daarop controleren. Dat zou je dan binnen de marco functie zelf kunnen doen. Overigens is het automatisch aanroepen van functies op deze manier wel linke soep hoe dan ook. Ik zou dit echt alleen bewaren voor simpele waarden en niet voor de gehele content of menu oid.

Noushka's Magnificent Dream | Unity


  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Verwijderd schreef op woensdag 20 april 2005 @ 00:30:
Is het niet een beetje overbodig om de macro_time functie de parameter $intro te geven?
Natuurlijk, maar het was slechts om een voorbeeld te geven. Ik kon zo snel geen kleine functie met nuttige parameter verzinnen :)
Zou je dit verder toe kunnen lichten? Ik zie de "immers" niet per sé; grote kans dat je je implementatie aan kunt passen zodat het wel werkt.
Stel, iemand vult het volgende bericht in in het gastenboek: "Dat is een mooie [body]!". De template van de website is als volgt:
code:
1
2
3
4
5
6
<html>
  <body>
  <h3>[title]</h3>
  [body]
  </body>
</html>

Ik zoek nu in de template naar macros en zal op een bepaald moment [body] vinden. De [body] tag dient vervangen te worden door de inhoud op die pagina, bijvoorbeeld bovenstaande gastenboek-entry: "Dat is een mooie [body]!". Mijn code komt weer de [body]-macro tegen, en vult deze in met de body, etc. etc.

Nu is de oplossing natuurlijk om alleen macros te parsen die in de template staan, zodat de [body]-macro uit de gastenboek-post niet geparts wordt, maar in diezelfde vorm naar de client gestuurd wordt. Echter, ik kan met voorstellen dat je best andere macro's wel beschikbaar wil maken voor het gastenboek: [time] bijvoorbeeld. Mijn vraag is nu hoe ik het beste kan definieren welke macro's wel en welke niet, op een bepaalde plek geparsed mogen worden.

Ik hoop dat dit eea verduidelijkt :)

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Verwijderd

Reveller schreef op woensdag 20 april 2005 @ 18:48:
Nu is de oplossing natuurlijk om alleen macros te parsen die in de template staan, zodat de [body]-macro uit de gastenboek-post niet geparts wordt, maar in diezelfde vorm naar de client gestuurd wordt. Echter, ik kan met voorstellen dat je best andere macro's wel beschikbaar wil maken voor het gastenboek: [time] bijvoorbeeld. Mijn vraag is nu hoe ik het beste kan definieren welke macro's wel en welke niet, op een bepaalde plek geparsed mogen worden.
Ik denk dat je geen templatefuncties voor de bezoekers van je website beschikbaar wilt maken. Zelfs [time] niet. Is dat de tijd op het moment dat de message opgestuurd wordt, of de tijd op het moment dat de message getoond wordt? En waarom zou je een bericht op een gastenboek plaatsen met:

code:
1
Het is nu [time].


Erin?

Als je voor de toepassing zit te denken aan tags als [b], [i] en [url] (bbcode dus), dan denk ik dat je dat beter kunt scheiden van je template-engine.

  • Alex)
  • Registratie: Juni 2003
  • Laatst online: 12-12-2025
Is het niet handiger om een unieke naam voor een functie te gebruiken (mijntemplateparser_*) ipv (macro_*), dan voorkom je in grote lijnen dubbele functies.

We are shaping the future

Pagina: 1