[ Содержание ] [ Предыдущая ] [ Следующая ]

Приложение A. Простой пример

    В этом примере дана полная спецификация Yacc-а для небольшого настольного калькулятора; у настольного калькулятора 26 регистров, маркированных от "a" до "z", он воспринимает арифметические выражения, составленные из операторов +, -, *, /, % (оператор mod), & (побитовый AND), | (побитовый OR) и = (присваивание). Если выражение на верхнем уровне есть присваивание, то значение не печатается; в противном случае - печатается. Как и в С, целое значение, начинающееся с 0 (нуль) считается записанным в восьмеричной системе счисления; в противном случае - в десятичной.

    В качестве примера спецификации Yacc-а, настольный калькулятор проделывает достаточную работу, показывая использование приоритетов и двусмысленностей и демонстрируя простое восстановление после ошибок. Главное упрощение в том, что фаза лексического анализа значительно проще, чем для большинства приложений, и выходные данные печатаются сразу же, строка за строкой. Заметьте, каким способом грамматическими правилами читаются десятичные и восьмеричные целые; Это, вероятно, лучше делать лексическому анализатору.

%{ # include # include int regs[26]; int base; %} %start list %token DIGIT LETTER %left '|' %left '&' %left '+' '-' %left '*' '/' '%' /* обеспечивает приоритет для унарного минуса */ %left UMINUS %% /* начало секции правил */ list : /* пусто */ | list stat '\n' | list error '\n' { yyerrok; } ; stat : expr { printf( "%d\n", $1 ); } | LETTER '=' expr { regs[$1] = $3; } ; expr : '(' expr ')' { $$ = $2; } | expr '+' expr { $$ = $1 + $3; } | expr '-' expr { $$ = $1 - $3; } | expr '*' expr { $$ = $1 * $3; } | expr '/' expr { $$ = $1 / $3; } | expr '%' expr { $$ = $1 % $3; } | expr '&' expr { $$ = $1 & $3; } | expr '|' expr { $$ = $1 | $3; } | '-' expr %prec UMINUS { $$ = - $2; } | LETTER { $$ = regs[$1]; } | number ; number : DIGIT { $$ = $1; base = ($1==0) ? 8 : 10; } | number DIGIT { $$ = base * $1 + $2; } ; %% /* начало программ */ yylex() { /* подпрограмма лексического анализа возвращает LETTER для строчных букв, yylval = 0-25 возвращает DIGIT для цифр, yylval = от 0 до 9 все остальные символы возвращаются как есть */ int c; /* пропуск пробелов */ while( (c=getchar()) == ' ' ) { } /* c теперь не пробел */ if( islower( c ) ) { yylval = c - 'a'; return ( LETTER ); } if( isdigit( c ) ) { yylval = c - '0'; return( DIGIT ); } return( c ); }

[ Содержание ] [ Предыдущая ] [ Следующая ]



c 1998-2000 SoloTony (Antonio Solo) solotony@mail.ru