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

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

Шрифт:

Правило для опред вводит новое свойство языка

yacc
: встроенное действие. Оказывается, можно поместить действие посредине правила, так, чтобы оно выполнялось в процессе распознавания последнего. Мы воспользовались этой возможностью, чтобы запомнить, что сейчас распознается: определение функции или процедуры. (В качестве альтернативного решения можно было бы ввести новый символ типа
begin
, который распознавался бы в соответствующее время.) Функция
defnonly
печатает предупреждающее сообщение, если вопреки синтаксису какая-либо конструкция окажется вне определения функции или процедуры. Обычно вам предоставляется выбор: обнаруживать ошибку синтаксически или семантически. Перед нами уже стояла такая задача ранее, при диагностике неопределенных переменных. Функция
defnonly
хорошо иллюстрирует ситуацию, когда семантическая проверка легче синтаксической.

defnonly(s) /* warn if illegal definition */

 char *s;

{

 if (!indef)

execerror(s, "used outside definition");

}

Переменная

indef
определена в
hoc.y
и принимает значения в действиях для опред.

К лексическому анализатору добавлены средства проверки аргументов: символ

$
, за которым следует чисто для строки в кавычках. Последовательности в строках, начинающиеся с обратной дробной черты, например
\n
, обрабатываются функцией
backslash
:

yylex /* hoc6 */

 ...

 if (c == '$') { /* argument? */

int n = 0;

while (isdigit(c=getc(fin)))

n = 10 * n + c — '0';

ungetc(с, fin);

if (n == 0)

execerror("strange $...", (char*)0);

yylval.narg = n;

return ARG;

 }

 if (c == '"') { /* quoted string */

char sbuf [100], *p, *emalloc;

for (p = sbuf; (c=getc(fin)) != '"'; p++) {

if (с == '\n' || c == EOF)

execerror("missing quote", "");

if (p >= sbuf + sizeof (sbuf) - 1) {

*p = '\0';

execerror("string too long", sbuf);

}

*p = backslash(c);

}

*p = 0;

yylval.sym = (Symbol*)emalloc(strlen(sbuf)+1);

strcpy(yylval.sym, sbuf);

return STRING;

 }

 ...

backslash(c) /* get next char with \'s interpreted */

 int c;

{

 char *index; /* 'strchr' in some systems */

 static char transtab[] = "b\bf\fn\nr\rt\t";

 if (c != '\\')

return c;

 c = getc(fin);

 if (islower(c) && index(transtab, c))

return index(transtab, с)[1];

 return c;

}

Лексический анализатор является примером конечного автомата независимо от того, написан ли он на Си или получен с помощью порождающей программы типа

lex
. Наша первоначальная версия Си программы стала весьма сложной, и поэтому для всех программ, больших ее по объему, лучше использовать
lex
, чтобы максимально упростить внесение изменений.

Остальные изменения сосредоточены главным образом в файле

code.c
, хотя несколько имен функций добавляется к файлу
hoc.h
. Машина остается той же, но с дополнительным стеком для хранения последовательности вложенных вызовов функций и процедур (проще ввести второй стек, чем загружать больший объем информации в существующий). Начало файла
code.c
выглядит так:

$ cat code.c

#include "hoc.h"

#include "y.tab.h"

#include <stdio.h>

#define NSTACK 256

static Datum stack[NSTACK]; /* the stack */

static Datum *stackp; /* next free spot on stack */

#define NPROG 2000

Inst prog[NPROG]; /* the machine */

Inst *progp; /* next free spot for code generation */

Inst *pc; /* program counter during execution */

  • Читать дальше
  • 1
  • ...
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • ...

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

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

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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