Lex
У рачунарству, lex је рачунарски програм који генерише лексички анализатор. Lex се обично користи са yacc-ом. Lex, који су написали Ерик Шмит (енгл. Eric Schmidt) и Мајк Леск (енгл. Mike Lesk), постао је стандардни генератор за лексички анализатор на многим јуникс системима, а понашање lex-а одређено је правилима у POSIX стандарду.
Lex чита улазни ток и враћа код који имплементира lexer у програмском језику C.
Верзије Lex-а базиране на АТ&Т коду су доступне као софтвер отвореног кода, као део OpenSolaris-а и Plan 9 from Bell Labs-а. Друга популарна верзија Lex-а отвореног кода је Flex, тј. брзи лексички анализатор (енгл. fast lexical analyzer).
Структура lex програма
[уреди | уреди извор]Структура lex програма је намерно направљена да буде слична структури yacc програма; програми су подељени на три дела, одвојена линијама које садрже само два процентна знака (%%), тј.:
Део за дефиниције %% Део за правила %% Део за C код
- Дефиницијски део је место где се дефинишу макрои и позива датотека написана на C-у. Овде је такође могуће написати било какав C код који ће дословно бити копиран у генерисану изворну датотеку.
- Део за правила је најважнији део; он повезује обрасце са С-овским исказима. Обрасци су регуларни изрази. Када lexer види неки текст на улазу који одговара датом обрасцу, онда он извршава одговарајући део С кода. Ово је основно у раду lex-а.
- Део за С код садржи С исказе и функције које се дословно копирају у генерисану изворну датотеку. Ови С искази садрже позиве правила из дела за правила. У великим програмима много је лакше овај део кода записати у одвојеној датотеци и онда је повезати за време компајлирања.
Пример lex програма
[уреди | уреди извор]Овај пример lex програма је за Flex верзију lex-а. Препознаје ниске целих бројева са улаза и само их штампа на излаз:
/*** Део за дефиниције ***/ %{ /* C код ће да буде копиран дословно */ #include <stdio.h> %} /* Ово говори flex-у да чита само једау улазну датотеку */ %option noyywrap %% /*** Део за правила***/ /* [0-9]+ представља ниске које имају једну или више цифара */ [0-9]+ { /* yytext је ниска која садржи одговарајући препознати текст. */ printf("Primecen ceo broj: %s\n", yytext); } . { /* Игнориши све друге карактере. */ } %% /*** Део за С код***/ int main(void) { /* Позове lexer и онда прекине */ yylex(); return 0; }
Ако овај улаз дамо flex-у, он ће бити конвертован у C програм, lex.yy.c. Када се ово комајлира и покрене биће препознаване и исписиване ниске целих бројева. На пример, за дати улаз:
abc123z.!&*2ghj6
програм ће иштампати:
Primecen ceo broj: 123 Primecen ceo broj: 2 Primecen ceo broj: 6
Коришћење Lex-а са Yacc-ом
[уреди | уреди извор]Lex и Yacc се обично користе заједно. Yacc користи формалну граматику да рашчлани улазни ток, а то Lex не може да уради користећи само регуларне изразе. Са друге стране, Yacc не може да чита обични улазни ток, њему требају низови токена. Lex се често користи да обезбеди Yacc са овим токенима.
Lex и make
[уреди | уреди извор]Make може да се користи да одржава програме који користе lex. Make претпоставља да датотека са екстензијом .l
представља lex програм. Make зна како такву датотеку треба да обради да би се направила одговарајућа објектна датотека.
Претпоставимо да листа зависности у make датотеци садржи име датотеке x.o
, а постоји датотека x.l
. Ако је x.l
модификован после датотеке x.o
(или ако x.o
не постоји), онда ће make покренути x.l
, и онда ће објектни фајл x.o
бити креиран од lex.yy.c
.