Лекция 13 13 ноября 2015 г. Опр. 1: Lex (и его аналоги) – генератор лексических анализаторов, который по регулярному описанию языка генерирует код на языке C лексического анализатора. Опр. 2: Генератор – программа, которая генерирует код другой программы (как правило, на языке того же уровня). Формат описания ЯП для Lex Декларации C, заголовочные файлы и макросы lex %% Шаблоны и действия %% Функции на языке C, используемые действиями lang.l … %% … %% … lex.yy.c int yylex() flex.exe lex.yy.c – программа на языке C, определяющая функцию лексического анализатора yylex() (аналог функции getNextLexem() с прошлых лекций) Секция №1 %{ #include “header.h” #define MAX 1000 char c; %} Все, что заключено в %{ … %}, без изменений вставляется в код генератора или MAC ab*c имя значение hello{MAC} helloab*c Секция №2 Регулярные выражения шаблон1 действие1 шаблон2 действие2 … шаблонN действиеN Куски кода на языке C, вызываемые, когда срабатывает соответствующий шаблон Расширенный синтаксис регулярных выражений c Символ c “c” Символ “c”, даже если это спецсимвол \c То же, что и “c” [cd] Символ c или символ d [a-z] Любой один символ из диапазона a-z [^c] Любой символ, кроме c . Любой символ, кроме переноса строки ^x Шаблон x, если он начинается с начала строки x$ Шаблон x, если им заканчивается строка x? 0 или 1 вхождение x x+ Положительное замыкание шаблона x x* Замыкание шаблона x xy Конкатенация шаблонов x и y x|y x или y (x) Скобки <S>x Шаблон x, когда lex находится в состоянии S {X} Имя макроса из секции №1 x{m} m повторений шаблона x x{m,n}повторение шаблона x от m до n раз Секция №3 int yywrap(){ return 1; } int main(){ while(yylex()); } Любой вспомогательный код на C INT [0-9]+ EXP ([eE][+-]?{INT}) %{ int i; float f; %} %% {INT} {INT}\.{INT}?{EXP}? . %% int main () { yylex(); } int yywrap () { } {sscanf cout << {sscanf cout << ; (yytext, “%d”, &i); "Int" << endl;} (yytext, “%lf”,&f); "Float" << endl;} INT [0-9]+ IDENT [a-zA-Z][a-zA-Z0-9]* %{ #include <iostream> using namespace std; int i; %} %% -?{INT} { sscanf_s (yytext, "%d", &i); cout << "[num, " << i << "]" << endl; return 1; } \'[^\']\' { cout << "[chr, " << yytext << "]" << endl; return 1; } \"[^\"]+\" { cout << "[str, " << yytext << "]" << endl; return 1; } if int char if else switch case while for return in out { { { { { { { { { { { { cout cout cout cout cout cout cout cout cout cout cout cout << << << << << << << << << << << << "[kwif]" << endl; return 1; } "[kwint]" << endl; return 1; } "[kwchar]" << endl; return 1; } "[kwif]" << endl; return 1; } "[kwelse]" << endl; return 1; } "[kwswitch]" << endl; return 1; } "[kwcase]" << endl; return 1; } "[kwwhile]" << endl; return 1; } "[kwfor]" << endl; return 1; } "[kwreturn]" << endl; return 1; } "[kwin]" << endl; return 1; } "[kwout]" << endl; return 1; } "=" "+" "-" "*" { { { { cout cout cout cout << << << << "[opassign]" << endl; return 1; } "[opplus]" << endl; return 1; } "[opminus]" << endl; return 1; } "[opmult]" << endl; return 1; } "==" "!=" "<" ">" "<=" "!" "||" "&&" { { { { { { { { cout cout cout cout cout cout cout cout << << << << << << << << "[opeq]" << endl; return 1; } "[opne]" << endl; return 1; } "[oplt]" << endl; return 1; } "[opgt]" << endl; return 1; } "[ople]" << endl; return 1; } "[opnot]" << endl; return 1; } "[opor]" << endl; return 1; } "[opand]" << endl; return 1; } "(" ")" "{" "}" "[" "]" ";" "," ":" { { { { { { { { { cout cout cout cout cout cout cout cout cout << << << << << << << << << "[lpar]" << endl; return 1; } "[rpar]" << endl; return 1; } "[lbrace]" << endl; return 1; } "[rbrace]" << endl; return 1; } "[lbracket]" << endl; return 1; } "[rbracket]" << endl; return 1; } "[semicolon]" << endl; return 1; } "[comma]" << endl; return 1; } "[colon]" << endl; return 1; } [a-zA-Z][a-zA-Z0-9_]* { cout << "[id, " << yytext << "]" << endl; return 1; } [ \t\n] ; . ; %% int yywrap(){ cout << "[eof]" << endl; return 1; } int main(){ while(yylex()); }