The website "dmilvdv.narod.ru." is not registered with uCoz.
If you are absolutely sure your website must be here,
please contact our Support Team.
If you were searching for something on the Internet and ended up here, try again:

About uCoz web-service

Community

Legal information

7.4 Стратегия реализации

7.4 Стратегия реализации

Предыдущая  Содержание  Следующая V*D*V

Мы знаем, что должен делать ooc. Как написать препроцессор? По соображениям эффективности нам, возможно, в конце концов, придётся прибегнуть к платформе, подобной lex и yacc, но первая реализация будет намного дешевле, если мы используем строковый язык программирования, подобный awk или perl. Если это заработает, мы будем знать необходимые алгоритмы и структуры данных, и должно быть легко переписать их в более эффективной реализации; для выполнения работы можно было бы даже использовать что-то вроде транслятора из awk в C. С дешёвой первой реализацией мы, однако, прежде всего сможем убедиться, что наша идея осуществима и в первую очередь удобна.

ooc разбирает описания классов и создаёт базу данных. Параметры командной строки с учётом базы данных решают, что будет сгенерировано. Как мы уже видели, генерация может быть основана на каком-то шаблоне со словами для непосредственной печати и словами, которые будут заменены информацией из базы данных. Однако, наши шаблоны содержали циклы, так что кажется, что шаблон действительно является функцией awk со структурами управления  и переменными.

Первая реализация ooc действительно работала таким образом, но оказалась трудной для изменения. Существует гораздо лучший способ: простой язык отчётов с заменой текста, циклами и условиями, который используется, чтобы выразить шаблон, и который интерпретируется ooc для создания вывода.

Более подробно данная реализация поясняется  в приложении B. Язык отчёта определяется как часть руководства ooc в приложении C. Язык отчёта содержит около двадцати пяти замен, десять циклов, два условных оператора и способ вызова отчёта в виде части другого отчёта. В качестве примера показано, как могли бы быть сгенерированы селекторы:

 

`{if `newmeta 1

  `{%-

    `result `method ( `{() `const `type `_ `name `}, ) { `n

`t      const struct `meta * class = classOf(self); `n

       `%casts

`t     assert(class -> `method ); `n

`t     `{ifnot `result void return `} \

           class -> `method ( `{() `name `}, ); `n

    } `n

  `}

`}

 

Внутри отчётов ooc считает интересными все те слова, которые начинаются с обратного апострофа; группы начинаются с `{ и заканчиваться `} и являются либо циклами или условными операторами; вызов отчёта начинается с `%; все другие слова, начинающиеся с обратного апострофа, заменяются информацией из базы данных.

`{if использует следующие два слова и выполняет остальную часть группы, если слова равны. `newmeta будет заменяться на 1, если ooc работает с описанием класса, который определяет новый метакласс. Поэтому селекторы генерируются только для нового метакласса.

`{%- это цикл по динамически компонуемым методам в описании класса. `method заменяется текущим именем метода; `result — текущий тип результата.

`{() представляет собой цикл по параметрам текущего метода. Назначение `const, `type и `name должно быть достаточно очевидно: это части описания текущего параметра. `_ подчеркивание, если текущий параметр является объектом текущего класса. `} это маленькая хитрость: создаётся запятая, если есть ещё один параметр, и завершается цикл, как и в случае с любым другим маркером, начинающимся с `}.

`%casts вызывает другой отчёт, casts, который отвечает за импорт параметров объектов. На данный момент этот отчёт выглядит примерно следующим образом:

 

% casts            // оператор %casts

`{()               // импорт

  `{if `_ _

`t  `const struct `cast * `name = _ `name ; `n

  `}

`}n

`{if `linkage %    // если компоновка статическая, необходимо проверить

  `%checks

`}

 

Строка, начинающаяся с %, предшествует отчётам в файле отчёта и привносит имя отчёта. Остальная часть отчёта casts должна быть понятна: `cast относится к имени класса объекта параметра, а `linkage тип компоновки текущего метода, то есть один из символов разделов в описании класса. Мы создаём локальную переменную чтобы разыменовать параметр, если он является объектом в текущем классе. `}n ещё одна хитрость: создаётся символ новой строки, если для группы было что-либо сгенерировано.

%casts также несёт ответственность за проверку всех объектов, поставляемых в качестве параметров в метод со статической компоновкой. Так как селекторы имеют подобную проблему, мы используем самостоятельные проверки отчётов, которые могут быть вызваны из отчёта для генерации селекторов:

 

% checks        // проверяем все объектные параметры

`{()

  `{ifnot `cast `

`t assert( `name ); `n

  `}fi

`}n

 

До следующей главы мы можем защититься от нулевых указателей по крайней мере вызовом assert(). Для объектов необходим этот тест: ` заменяется пустотой, то есть мы генерируем assert(), если видим объект параметра из произвольного класса.

Два слова ещё не были объяснены: `t генерирует табуляцию, а `n генерирует символ новой строки. Мы хотим генерировать удобочитаемые программы C; Таким образом, надо внимательно следить, сколько генерируется пробелов. Чтобы можно было идентифицировать отчёты, основанные на их собственных структурах управления в группах, ooc не будет генерировать начальные пробелы и подряд будет генерироваться только одна пустая строка. `t следует использованы для получения отступа, а для того, чтобы разбить вывод на строки, следует использовать `n. (* Эксперименты со средствами форматирования исходного кода cb и indent не дали приемлемых результатов. Слова 't и 'n доставляют лишь незначительное неудобство и мониторинг генерации начальных пробелов и последовательных переводов строк не сильно усложняют генератор отчетов.)

 

Предыдущая  Содержание  Следующая