| expr NE expr { code(ne); }
| expr AND expr { code(and); }
| expr OR expr { code(or); }
| NOT expr { $$ = $2; code(not); }
;
prlist: expr { code(prexpr); }
| STRING { $$ = code2(prstr, (Inst)$1); }
| prlist ',' expr { code(prexpr); }
| prlist ',' STRING { code2(prstr, (Inst)$3); }
;
defn: FUNC procname { $2->type=FUNCTION; indef=1; }
'(' ')' stmt { code(procret); define($2); indef=0; }
| PROC procname { $2->type=PROCEDURE; indef=1; }
'(' ')' stmt { code(procret); define($2); indef=0; }
;
procname: VAR
| FUNCTION
| PROCEDURE
;
arglist: /* nothing */ { $$ = 0; }
| expr { $$ = 1; }
| arglist expr { $$ = $1 + 1; }
;
%%
/* end of grammar */
...
С помощью правила для
Правило для 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;
}
Вильям Л Саймон , Вильям Саймон , Наталья Владимировна Макеева , Нора Робертс , Юрий Викторович Щербатых
Зарубежная компьютерная, околокомпьютерная литература / ОС и Сети, интернет / Короткие любовные романы / Психология / Прочая справочная литература / Образование и наука / Книги по IT / Словари и Энциклопедии