Язык программирования Си




Сложные объявления - часть 2


(объявитель) собственно-объявитель() собственно-объявитель [необязательный размер]

Говоря простым языком, объявитель есть собственно-объявитель, перед которым может стоять * (т. е. одна или несколько звездочек), где собственно- объявитель есть имя, или объявитель в скобках, или собственно-объявитель с последующей парой скобок, или собственно-объявитель с последующей парой квадратных скобок, внутри которых может быть помещен размер.

Эту грамматику можно использовать для грамматического разбора объявлений. Рассмотрим, например, такой объявитель:

(*pfa[])()

Имя pfa будет классифицировано как имя и, следовательно, как собственно- объявитель. Затем pfa[] будет распознано как собственно-объявитель, а *pfa[] - как объявитель и, следовательно, (*pfa[]) есть собственно-объявитель. Далее, (*pfa[])() есть собственно-объявитель и, таким образом, объявитель. Этот грамматический разбор можно проиллюстрировать деревом разбора, приведенным на следующей странице (где собственно-объявитель обозначен более коротко, а именно собств.-объяв.).

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

/* dcl: разбор объявителя */ void dcl(void) { int ns;

for (ns = 0, gettoken() == '*';) /* подсчет звездочек */ ns++;

dirdcl(); while(ns-- > 0) strcat(out, "указ. на”); }

/* dirdcl: разбор собственно объявителя */ void dirdcl(void) { int type;

if (tokentype == '(') { dcl(); if (tokentype != ')') printf("oшибкa: пропущена )\n"); } else if (tokentype == NAME) /* имя переменной */ strcpy(name, token); else printf("ошибка: должно быть name или (dcl)\n");

while((type = gettoken()) == PARENS || type == BRACKETS) if (type == PARENS) strcat(out, "функц. возвр."); else { strcat(out, " массив"); strcat(out, token); strcat(out, " из"); } }




Содержание  Назад  Вперед