[ Содержание ] [ Предыдущая ] [ Следующая ]
В этом примере дана полная спецификация 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 |