File

33 отговора 1173 прегледа
#1

File

Привет.

От къде мога да прочета как да направя лексален и синтактичен анализатор за работа с файлове? Имам програмка която ползва няколко конфигурационни файла но искам те да не са фиксирани а да се променят в следствие на промяна в програмата

Отговор
в отговор на Hoвaтop #2

Potencialen emigrant беше пуснал

по емейлите на доста народ лекциите на Добрев (за транслатори). Ако мислиш, че ще ти свършат работа свиркай.

НАЙ-добрия клуб ТУК
Отговор
в отговор на Hoвaтop #3

:)

Мисля, че ако ти имаш визможност да определиш синтаксиса на файла, лесно ще се справиш -- от движение. Избери по-прост синтаксис. Например конфигурационните файлове в UNIX-ите нямат много сложен синтаксис и вършат работа.

Ако синтаксиса ти е много сложен . . . това не е работа за един ден. Трябва да прочетеш някоя книга по транслатори и компилатори. Книгата за която говори Xipodilec е добра. Може и да използваш помощтни програмъ като lex и yacc които ги има в UNIX-ите. В Linux има един bison който в същност е yacc. Резултата от lex и yacc е код на C и после можеш да го използваш и във Windows, т. е. не зависи от компилатора или ОС.

В случая, ако решиш да пишеш директно за някой по-прост синтаксис, . . . мога да ти покажа как аз съм го правил. По долу ти давам един мой source с който можеш да анализираш по-прости неща.
Можеш да получавак терми, като keyword (като идентификатор в език за програмиране), специални знаци като *, !=, /, или числа.
Това е само лексически анализ, разбирасе.

Програмата по-долу може и да не е най-умното нещо, но на мен веднъж ми свърши работа. Използвах я за да анализирам мат. изерази с числа, аритметични операции, функции, променливи, ...

Ако в синтаксиса има вложени скоби, като (, ) или {, } или begin, end . . . по-нататък в синтактическия анализатор може да използваш нещо като стек . . .

Съжалявам, че няма достатъчно коментари в source но се надявам да се справиш. Под програмата съм дал малко обяснения.

Ето програмата.
Използвай я както искаш, стига да ти върши работа.




/* lexi.c
Written by Boiko Angelov
Fri May 19 15:20:21 GMT-0200 1995
*/

#include <ctype.h>
#include <string.h>

#define MAXC 64

static int C;

static char single_puncts[] = ";()=-+*/^:!#";
static char *double_puncts[] =
{
":",
":"
};

static
void nextword(char *term, int(*nextchar)(int))
{
int c,i;
while( isspace(nextchar(0)) ) nextchar(1);
i = 0;
if( ++C >= MAXC ) return;
term[i++] = (c = nextchar(1));
if( isalpha(c) )
{ /* ID */
c = nextchar(0);
while( isalpha(c) || isdigit(c) )
{
if( ++C >= MAXC ) return;
term[i++] = nextchar(1);
c = nextchar(0);
}
}
else if( isdigit(c) )
{ /* Number */
while( isdigit(nextchar(0)) )
{
if( ++C >= MAXC ) return;
term[i++] = nextchar(1);
}
}
else
{ /* Other */
}
term = '\0';
}

int
nextterm(char *term, int(*nextchar)(int))
{
int retval;
int n;
int c;
C = 0;
nextword(term, nextchar);
if( C >= MAXC ) return -1;
if( (term[0]=='.') && isdigit(nextchar(0)) )
{
nextword(&term[1], nextchar);
goto get_exp;
}
if( isdigit(term[0]) )
{ /* read tail of a Number */
if( nextchar(0)=='.' )
{
n = strlen(term);
if( ++C >= MAXC ) return -1;
term[n++] = nextchar(1);
if( isdigit( nextchar(0) ) ) nextword(&term[n], nextchar);
if( C >= MAXC ) return -1;
}
get_exp:
retval = 0;
if( toupper(nextchar(0))=='E' )
{
n = strlen(term);
if( ++C >= MAXC ) return -1;
term[n++] = nextchar(1);
c = nextchar(0);
if( (c=='+') || (c=='-') )
{
if( ++C >= MAXC ) return -1;
term[n++] = nextchar(1);
}
if( isdigit(nextchar(0)) )
nextword(&term[n], nextchar);
else
retval = -1; /* illegal char */
if( C >= MAXC ) return -1;
}
}
else if( isalpha(term[0]) )
retval = 1; /* ID */
else
{
for( n=0; double_puncts[0][n]!='\0'; n++ )
if( double_puncts[0][n]==term[0] )
if( double_puncts[1][n]==nextchar(0) )
{
term[1]=nextchar(1);
term[2]='\0';
return 3; /* two char punct */
}
if( strchr(single_puncts, term[0]) )
retval = 2; /* single char */
else
retval = -1; /* illegal char */
}
return retval;
}

/* End of File lexi.c */


.


Интерфейса е чрез функцията

int nextterm(char *term, int(*nextchar)(int))

Параметъра term е буфер където ще ти се запише прочетебия терм.
Параметъра nextchar е функция, която се повиква за да доставя поредните символи от основния текст. Ако се повика чрез nextchar(0) трябва само да върне следващия символ, като да не преминава напред в текста. Ако се извика чрез nextchar(1) пак връща следващия символ, но се премества напред, така че при следващите повиквание да чете по-нататък във входния текст. Ти сам си пишеш тази функция -- така, че можеш да четеш както от стринг, така и от файл.
Функцията връща цяло число, показващо какъв е бил прочетения терм в буфера term. Възможните стойности са -1 за грешка, 0 за реално число като 1.45e-6, 1 за идентификатор като begin или alpha, 2 за единичен знак като + или -, 3 за двоен знак, като ++ или !=.

Надявам се това да ти помогне.

/b33
b33@dir.bg

Отговор
в отговор на b33 #4

Re: :)

Lele-male :>
macrosa isalpha() ne work correct s cyr :>
a upotrebata na goto f slu4aq.....

rgdz
curly
Отговор
в отговор на curly #5

Re: :)

Ако ти трябва кирилица, написши си свое isalpha.

Иначе, . . . goto не е за тъпи програмисти.
Онова дето го пише в книгите, че goto е вреден и не бива да се използва . . . е само заблуда за beginer-и. Мога да ти напиша дълъг код само с if(...) goto ..., без никакви while-if-then-else и ще изглежда ясно и разбрано. Важен е модела на програмата.
Оператора goto е бърз. А ако имаш идея как се компилира програма до Assembler ще знаеш, че може да бъде полезен.

Отговор
в отговор на b33 #6

Re: :)

Vlizash s goto v if-chastta na if-then-else!!! Povedenieto e nestandartizirano i tova dali else-yt shte se izpylni zavisi ot kompilatora.

Отговор
в отговор на Hoвaтop #7

Re: File

Ima li prichina, po koqto INI i XML formatite, registry-to i DAO-to da ne ti varshat rabota (a za tqh ima gotovi API/software) i trqbva da izmislish nov format?

Отговор
в отговор на Architect #8

една причина за INI-то да не върши работа

Oграничен е откъм размер ако ще се ползват "вградените" функции за работа с INI. Ако няма да се ползват => няма смисъл от точно такова INI.

НАЙ-добрия клуб ТУК
Отговор
в отговор на Xypodilec #9

Re: една причина за INI-то да не върши работа

64K sa dosta za configuracionni parametri, osobeno ako se predpolaga da se modificirat s textov redaktor.
Ako ne, togava XML ili MDB trqbva da svarshat rabota.

Отговор
в отговор на Xypodilec #10

Re: Potencialen emigrant беше пуснал

Някой може ли да сложи въпросните лекции някъде по web-а?

Отговор
в отговор на Architect #11

Re: една причина за INI-то да не върши работа

Osobeno ako se nalaga celiyat fayl da se chete za vsyako poiskano entry :-)
BTW, koyto iska, imam prenosim modul za ala-Win INI faylove, koyto moje dori i da gi modificira.

Отговор
в отговор на Penguin #12

Re: Potencialen emigrant беше пуснал

[линк]
Tova mi e temp dir, ta ako nyakoy den go iztriya - da ne se syrdite.

Отговор
в отговор на Potencialen emigrant #13

Re: една причина за INI-то да не върши работа

Toi windowsa uzh gi keshirashe edno vreme - ne che preporachvam da si darzhite bazite danni v INI failove :)

Отговор
в отговор на Potencialen emigrant #14

ANSI C, ISO/IEC 9899: 1990

Официалния стандарт за C е ISO/IEC 9899: 1990

Може да се използва goto по този начин както аз съм го използвал (не зависимо дали на някой му харесва или не).

За да не съм голословен, ето доказателство:

3.6.2 Compound statement, or block

The Committee considered proposals for forbidding a goto into a block from outside, since such a restriction would make possible much easier flow optimization and would avoid the whole issue of initializing auto storage (see §3.1.2.4). The Committee rejected such a ban out of fear of invalidating working code (however undisciplined) and out of concern for those producing machine-generated C.


Горния текст може да се види в Интернет на адреса:

[линк]

Допълнително, ако някой се интересува от ANSI C, може да погледне какво има на адреса:

[линк]

От горния адрес, меже да се изтегли като pdf една Draft-версия на стандарта, която се предполага, че ще бъде бъдещия стандарт за C.

Може също да се вземe код за yacc и lex дефиниращ цялото ANSI C от адресите:

[линк]
[линк]

/b33

Отговор
в отговор на b33 #15

Re: ANSI C, ISO/IEC 9899: 1990

Ne stava yasno shte se izpylni li else chastta ili ne?
Problemyt tuk ne e sintaktichen, a zavisi ot generiraneto na obektniya kod, i dori ot procesora, vErvay mi :-)

Отговор
в отговор на Potencialen emigrant #16

Re: ANSI C, ISO/IEC 9899: 1990

Не ми е необходимо да ти Вервам :)

Естествено, че няма да се изпълни часта else. Точно пък това, . . . изобщо не е проблем, за кото и да е компилатор. Ако си прочел добре цитата, единствената мотивация да се забрани такъв код е заради оптимизации или за случайте когато в блока се променя контекста на функцията (например когато в блока се обявяват променливи). Но въпреки това, стандарта не забранява такъв код; така, че всеки компилатор трябва да се съобразява с това и се съобразява.

Стандартите ANSI и ISO са за това, че всички да ги спазват -- и програмистите и фирмите които правят компилатори.

Защо да ти Вервам точно на теб? -- В стандарта пише, че такъв код е допустим, аз съм компилирал този код и съм се убедил, че наистина работи както се очаква.
Това за мен е истината.

/b33

Отговор
в отговор на b33 #17

Re: :) -- note

Не, че някой го интересува, . . . но заради точността:

Забелязах, че в програмата са изчезнали три символа. Получило се е, понеже случайно това е метакомандата за включване не италик.
Става дума за края на функцията nextword(...), където се вижда реда:

term = '\0';

Това трябва да бъде:

term[i] = '\0';

/b33

Отговор
в отговор на b33 #19

Re: ANSI C, ISO/IEC 9899: 1990

Tova, che e pozvoleno, ne znachi, che ne e vredno. Eto ti drugo pozvoleno primerche:

char *str;
str = (char *)rand ();
printf ("%s", str);

Kvo shte kajesh? Syvsem pozvoleno e!

Отговор
в отговор на b33 #20

Re: :)

Unf
ne se zaqvdah, prosto oto4nqfah za cyr.

A poradi pri4inata 4e razbiram ot ASM komentirah i goto
kogato imash goto nai-malkoto imash break na optimizaciite na compilatora.
koda koito se generira mnogo zafisi kakto ot compilatora, taka i ot optizaciite koito sa pusnati.
Nafremeto fidqh na WC v10.+ and v11 se obyrkfat registrofite optimizacii.
F smi ne se skapfa koda, a prosto ne se izpozfat. Ako pogledash nekoq druga godinka asm-to generirano ot C, shte razberesh za kfo staa duma.
Da syglasen 4e f nqkoi slu4ai goto e nai-usefull. Ili pone taka izglevda.
F tozi slu4ai bih ti kazal da si poglednesh logikata na programata.

du -hs /home/cvs/curly/projects
6.7G
grep -r goto /home/cvs/curly/projects/*

(pattern not found)

rgdz
curly
Отговор