Вход/Регистрация
UNIX — универсальная среда программирования
вернуться

Керниган Брайан Уилсон

Шрифт:

}

Функция main обращается к

yyparse
для разбора входного потока. Переход в цикле от одного выражения к другому происходит в рамках грамматики с помощью последовательности правил вывода для списка. Приемлемо также обращаться в цикле к
yyparse
из функции
main
, если действия для списка предполагают печать значения и немедленный возврат.

Функция

yyparse
в свою очередь многократно обращается за лексемами из входного потока к функции
yylex
. Наша функция
yylex
проста: в ее задачи входят пропуск пробелов и символов табуляции, преобразование цифровых строк в числовое значение и подсчет входных строк для вывода сообщений об ошибках. Поскольку грамматика допускает только
+
,
–
,
*
,
/
,
(
,
)
и
\n
, при появлении любого другого символа
yyparse
выдает сообщение об ошибке. Получение 0 означает для
yyparse
"конец файла".

/* Продолжение hoc.y */

yylex /* hoc1 */

{

 int с;

 while ((c=getchar) == ' ' || с == '\t')

;

 if (c == EOF)

return 0;

 if (c == '.' || isdigit(c)) {

/* number */

ungetc(c, stdin);

scanf("%lf", &yylval);

return NUMBER;

 }

 if (c == '\n')

lineno++;

 return с;

}

Переменная

yylval
используется для связи между синтаксическим и лексическим анализаторами; она определена в
yyparse
и имеет тот же тип, что стек
yacc
. Функция
yylex
возвращает тип лексемы, равно как и ее функциональное значение, и приравнивает
yylval
значению лексемы (если оно есть). Например, число с плавающей точкой имеет тип
NUMBER
и значение, скажем, 12.34. Для некоторых лексем, прежде всего состоящих из одного символа, таких, как
'+'
или
'\n'
, в грамматике используется только тип. В этом случае
yylval
не нужно определять.

Определение

%token NUMBER
из входного файла для
yacc
преобразуется в оператор
#defin
e в выходном файле
y.tab.c
, поэтому
NUMBER
можно использовать в качестве константы в любом месте Си программы.
Yacc
выбирает такие значения, которые не будут смешиваться с символами ASCII.

При наличии синтаксической ошибки

yyparse
обращается к
yyerror
со строкой, содержащей загадочное сообщение: "syntax error" ("синтаксическая ошибка"). Предполагается, что функцию
yyerror
предоставляет пользователь: в нашей функции строка просто передается другой функции —
warning
, которая выдает некоторую дополнительную информацию. В последующих версиях
hoc
функция
warning
будет применяться непосредственно.

yyerror(s) /* called for yacc syntax error */

 char *s;

{

 warning(s, (char*)0);

}

warning(s, t) /* print warning message */

 char *s, *t;

{

 fprintf(stderr, "%s: %s", progname, s);

 if (t)

fprintf(stderr, " %s", t);

 fprintf(stderr, " near line %d\n", lineno);

}

Этим завершаются процедуры файла

hoc.y
. Трансляция программы для
yacc
происходит в два этапа:

$ yacc hoc.y
Выходной поток попадает в y.tab.c

$ сс y.tab.c -о hoc1
Выполняемая программа попадает в hoc1

$ hoc1

2/3

 0.66666667

– 3-4

hoc1: syntax error near line 1

$

Упражнение 8.1

Исследуйте структуру файла

y.tab.c
(для
hoc1
это составляет около 300 строк текста).

Внесение изменений — унарный минус

Ранее мы утверждали, что, работая с

yacc
, легко менять язык. В качестве примера добавим к
hoc1
унарный минус, чтобы выражения типа

– 3-4

вычислялись, а не отвергались как синтаксические ошибки. Всего две строки нужно дополнительно включить в

hoc.y
. Добавляется новая лексема
UNARYMINUS
в ту часть грамматики, где задаются приоритеты, чтобы унарный минус имел наивысший приоритет:

%left '+' '-'

%left '*' '/'

%left UNARYMINUS /* новая лексема */

Грамматика увеличивается на одно правило для

expr
:

expr: NUMBER ($$= $1;}

 | '-' expr %prec UNARYMINUS {$$=- $2} /* новое */

Определение

%prec
"говорит", что символ унарного минуса (т.е. знак
"-"
перед выражением) имеет тот же приоритет, что и
UNARYMINUS
(наивысший); действие заключается в изменении знака. Приоритет минуса между двумя выражениями устанавливается по умолчанию.

  • Читать дальше
  • 1
  • ...
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: