Zdravím
Ako semestrálny projekt z algoritmizácie som si vybral konvertor cčka do html+ zvyraznovač syntaxe. Trošku som sa však zasekol. Súbor s čkovským kodom chcem načitavat po riadkoch a po riadkoch to aj prevádzat. S čim mám však problem je ako čo najvhodnejšie implementovat slovnik klučových slov. Totiž ked bude už riadok načitaný do nejakého bufferu budem potrebovat načitavat po jednotlivých znakoch vytvárať slova a potom ich porovnat zo slovami v slovníku. Kvôli zvýraznovaniu je asi potrebné mať rozličné slovniky na datove typy, operatory .... Preto by som pri hladaní či je slovo klučové prehladat všetky tieto "polia", čo by trvalo asi pomerne dlho. Napadlo ma ešte to uložit do hashovacej tabulky ale pre +- 50 slov neviem či sa mi to oplatí. Nejaký napad? Pravdou je aj to že nie som s hash tabulkou moc kamarát, preto hladám nejaké iné riešenie. Ďakujem
Fórum › C / C++
Štruktúra na uloženie klúčových slov
Načítání po řádcích je správně, zpracovávat to po znacích je v podstatě nutnost. Dobře se to dělá stavovým automatem. Jenom 2 poznámky: prohledávání různých polí na klíčová, rezervovaná a jiná slova nebude pomalé. Toho se opravdu neboj ... tedy pokud nemáte dostat výsledek za 15ps :smile1: . A druhá poznámka ... často se stává, že předchozí řádek ovlivňuje předchozí (víceřádkové definice, víceřádkový komentář apod.), takže je potřeba přenášet stav z předchozího řádku na další.
> Zdravím
Ako semestrálny projekt z algoritmizácie som si vybral konvertor cčka do html+ zvyraznovač syntaxe. Trošku som sa však zasekol. ...
V zjednodušenom podaní, sa to obvikle robi tak, ze sa vstup nacita po
znakoch a časť programu nazývana lexikálny analyzátor načítavanú
postupnosť mení na symboly jazyka (klúčové slová, reťazce, premenné,
numerické hodnoty, a pod.). Tieto informácie sa následne spracúvajú
syntaktickým analyzátorom. Principiálne sa môže lexikálny analyzátor
chovať nejako takto:
lexical_analyzer
{
open(input_stream); // asociuje vstupny prud s analyzátorom
(súbor, pamäť, ...)
token next(); // vráti následujúci token
}
V najjednoduchšom prípade môže štruktúra token vypadať napr. takto:
enum e_type
{
string, // retazec
identifier, // identifikator
inumeber, // cele cislo
dnumber, // realne cislo
symbol, // symboly (=, <, >, ...)
kword // klucove slova jazyka
}
token
{
e_type type;
union
{
string s_val;
double d_val;
int i_val;
char c_val;
}
}
Funkcia lexical_analyzer::next() potom napr. v pripade takehoto kódu:
for (int i = 0; i < 5; i++)
postupne vracia toto:
token t;
1 volanie: t = {keyword, c_val=FOR_ID}
2 volanie: t = {symbol, c_val=LEFT_PARENTH_ID}
3 volanie: t = {identifier, s_val="i"}
4 volanie: t = {symbol, c_val=EQU_ID}
5 volanie: t = {inumber, i_val=0}
...
n volanie: t = {symbor, c_val=RIGHT_PARENTH_ID}
Jednotlivé symboly jazyka si už potom môžte v dalšej časti programu
ofarbovať podľa ľubosti.
Pokiaľ sa chcete dozvedieť viac, tak napr. v tejto knihe 'nikolaus
wirth - algoritmy a datove struktury' je vytvoreny jednotuchý
lexikálny aj syntakticky analyzátor ukážkového jazyka.
Druhou a jednoduchšiou možnosťou je použitie tzv. regular expressions
kde si najpr. vytvoríte pravidlá pre jednotlivé symboly jazyka, potom
načítate požadovaný súbor do pamete a tieto pravidlá naň budete
postupne aplikovať (napr. tak ako to je riešené v txtovom editore vim).
Ďakujem, pekné vysvetlenie :) presne niečo také som potreboval ;) Avšak asi mi to trošku nedochádza napr. tá funkcia next() mohli by ste mi ju trošku viac rozpísať? Ako stále mi uchodí pointa ako proste bude vediet ten program že sa jedna o napr. to klučové slovo proste v tom ma trošku hmlisto..:( ďakujem
> ... tá funkcia next() mohli by ste mi ju trošku viac rozpísať? ...
Za predpokladu, že parsujete bezkontextovu gramatiku čo v prípade, že
chcete iba ofarbovať klúčové slová jazyka C++ je splnené, funkcia
lexical_analyzer::next môže fungovať následujúco. Postupne čítate
jednotlivé znaky zo vstupu a na základe týchto znakov potom určujte o
aký symbol jazyka sa jedná, napr. ak prečítaným znakom je číslica
[0-9], potom
token lexical_analyzer::next()
{
// prečítam znak
currch = read_char();
int number;
if (isdigit(currch))
{
number = read_number();
return token(inumber, nuember);
}
...
}
int lexical_analyzer::read_number()
{
// prvu cislicu uz mame precitanu v currch a teraz precitame dalsie
int count = 0;
char snum[1024] = {0};
do
{
snum[count++] = currch;
currch = read_char();
}
while (isdigit(currch));
return atoi(snum); // skonvertujeme retazec na cislo, ktoré vrátime
}
Podobným spôsobom identifikujeme aj ostatné symboly jazyka. Ešte jeden
príklad, predpokladajme, že identifikátor jazyka je definovaný ako
postupnosť alfanumerickych znakov [0-9a-zA-Z] a znaku '_', a prečítaný
symbol bol znak, nie číslo, potom lexical_analyzer::next() môže
vypadať napr takto:
token lexical_analyzer::next()
{
// prečítam znak
currch = read_char();
int number;
if (isdigit(currch))
{
number = read_number();
return token(inumber, nuember);
}
else if (isalpha(currch) || currch == '_')
{
char ident[1024];
read_ident(ident);
return token(identifier, ident);
}
...
}
lexa::read_ident(ident)
{
do
{
ident += currch;
currch = read_char();
}
while (isalpha(currch) || currch == '_' || isdigit(currch));
}
Ako som už ale napísal v predchádzajúcom príspevku, podrobnejšie si
otom môžte prečítať v 'Niklaus E. Wirth; Algoritmy a Datove Struktury'
v ktorej je tvorve syntaktického analyzátora venovaná posledná
kapitola.
Přidej příspěvek
Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku
×Vložení zdrojáku
×Vložení obrázku
×Vložení videa
Uživatelé prohlížející si toto vlákno
Podobná vlákna
Výpis vět s počtem slov větším než je průměr slov ve větě — založil alex
Ulozenie ratazca v XDATA — založil Warchangel
Ulozenie Int[][][] do suboru — založil Miro1701
Uloženie obrázku návštevníkom — založil Anonym
Ulozenie metadat zo streamu — založil playman22
Moderátoři diskuze