Het probleem voor mij is dat ik erg weinig ervaring heb met PHP, dus ik kan moeilijk jouw code gaan doorspitten. Ik weet alleen hoe je zo'n parser moet opbouwen, niet hoe je het precies in PHP moet doen. Maar als ik jouw code zie, dan zie ik 1 grote functie. Dat kan haast niet kloppen.
Ik kan wel een klein voorbeeldje geven. Stel je hebt een taal die er zo uitziet:
code:
1
2
3
4
5
| tekst :== [ identifier | whitespace ]*
identifier :== letter, [ letter | cijfer ]*
whitespace :== "alle whitespace karakters"
letter :== "de karakters a-zA-Z"
cijfer :== "de karakters 0-9" |
Dan zet je dat om in de volgende pseudocode:
C:
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
| bool einde_van_string_bereikt;
string de_string;
char huidig_karakter;
int i;
/////
// hulp-functies
/////
zet_volgend_karakter_in_huidig_karakter()
{
i++;
huidig_karakter = de_string[i];
if(i >= de_string.length)
{
einde_van_string_bereikt = true;
}
}
isWhitespace(char)
{
// zegt of de char whitespace is
}
isLetter(char)
{
// zegt of de char a-zA-Z is
}
isCijfer(char)
{
// zegt of de char 0-9 is
}
/////
// functies die de taal lezen
/////
leesTekst()
{
while(!einde_van_string_bereikt)
{
if(isWhitespace(huidig_karakter))
{
leesWhitespace();
}
else if(isLetter(huidig_karakter))
{
leesIdentifier();
}
else
{
error("syntax error: identifier verwacht");
}
}
}
leesIdentifier()
{
leesLetter();
while(!einde_van_string_bereikt && ! isWhitespace(huidig_karakter)
{
if(isLetter(huidig_karakter))
{
leesLetter();
}
else if(isCijfer(huidig_karakter))
{
leesCijfer();
}
else
{
error("syntax error: geen geldige identifier");
}
}
}
leesWhitespace()
{
if(isWhitespace(huidig_karakter))
{
zet_volgend_karakter_in_huidig_karakter();
}
else
{
error("syntax error: whitespace verwacht");
}
}
leesLetter()
{
if(isLetter(huidig_karakter))
{
zet_volgend_karakter_in_huidig_karakter();
}
else
{
error("syntax error: letter verwacht");
}
}
leesCijfer()
{
if(isCijfer(huidig_karakter))
{
zet_volgend_karakter_in_huidig_karakter();
}
else
{
error("syntax error: cijfer verwacht");
}
} |
Elke taal-regel heeft een aparte functie. Je kan de gelezen taal op elk van die punten manipuleren door code in de functies toe te voegen. Op dit moment doet het niks anders dan een error geven op het moment dat de taal niet klopt, of, als het wel klopt, zonder iets te doen door de string heen gaan.
Als je de grotere structuren wilt gaan manipuleren, dan zal je de functies van de kleinere structuren wel iets moeten laten returnen, zodat de aangepaste versie in de grotere structuur terechtkomt. Ik zou dat met classes doen (class Tekst, class Identifier, class Whitespace, class Letter, class Cijfer), maar je kan ook simpelweg de string returnen.
Jouw taal (BBcode) zal overigens nooit een error geven, omdat onbekende tags als tekst worden weergegeven. Ik weet niet of je dat met een LL-parser kan doen, aangezien je dan vrij ver vooruit moet kijken (voorgaande code kijkt 1 karakter vooruit (huidig_karakter), en kan op die ene karakter altijd beslissen wat er gedaan moet worden).
Wat je hierboven ziet met de afhandeling van individuele karakters is ook niet echt zinvol, ik zet het er alleen voor de volledigheid bij. Normaalgesproken wil je whitespace gewoon negeren, dus maak je een functie skipWhitespace(), en letters/cijfers kan je gewoon uitlezen, want je weet al welke van de twee het is in het niveau erboven.
Edit, als voorbeeld voor wat je zou kunnen manipuleren:
Je kan met die methodes voor individuele karakters natuurlijk wel logischerwijs dingen doen, zoals de letters allemaal eentje ophogen (a->b, b->c, etc.), de cijfers allemaal eentje lager maken (9->8, 8->7, etc.), en de whitespace allemaal veranderen in 'X'-karakters.
Vervolgens kan je in de leesIdentifier-methode alle karakters van de identifiers omdraaien, behalve als het laatste karakter een cijfer is. Of de identifier omringen met "<" en ">" karakters.
En op het niveau van de leesTekst-methode kan je de identifiers sorteren op alfabetische volgorde.
[
Voor 16% gewijzigd door
Verwijderd op 03-12-2008 22:12
]