АнглийскийФранцузскийИспанский

Значок OnWorks

leg - Интернет в облаке

Запустите ногу в бесплатном хостинг-провайдере OnWorks через Ubuntu Online, Fedora Online, онлайн-эмулятор Windows или онлайн-эмулятор MAC OS

Это командная часть, которую можно запустить в бесплатном хостинг-провайдере OnWorks, используя одну из наших многочисленных бесплатных онлайн-рабочих станций, таких как Ubuntu Online, Fedora Online, онлайн-эмулятор Windows или онлайн-эмулятор MAC OS.

ПРОГРАММА:

ИМЯ


peg, leg - генераторы парсеров

СИНТАКСИС


колышек [-hvV -выход] [имя файла ...]
нога [-hvV -выход] [имя файла ...]

ОПИСАНИЕ


колышек и нога инструменты для создания парсеров рекурсивного спуска: программы, выполняющие
сопоставление с образцом в тексте. Они обрабатывают грамматику синтаксического анализа (PEG) [Ford 2004], чтобы
создать программу, которая распознает законные предложения этой грамматики. колышек обрабатывает ПЭГ
написано с использованием оригинального синтаксиса, описанного Фордом; нога обрабатывает PEG, написанные с использованием
немного другой синтаксис и соглашения, которые призваны сделать его привлекательным
замена парсеров, построенных с закон(1) и Yacc(1). В отличие от закон и Yacc, колышек и нога
поддержка неограниченного поиска с возвратом, предоставление упорядоченного выбора в качестве средства устранения неоднозначности и
может объединить сканирование (лексический анализ) и синтаксический анализ (синтаксический анализ) в единый
деятельность.

колышек читает указанный имя файлаs, или стандартный ввод, если нет имя файлаs даны, для
грамматика, описывающая синтаксический анализатор, который нужно сгенерировать. колышек затем генерирует исходный файл C, который
определяет функцию yyparse (). Этот исходный файл C может быть включен или скомпилирован, а затем
связана с клиентской программой. Каждый раз, когда клиентская программа вызывает yyparse() парсер
потребляет вводимый текст в соответствии с правилами синтаксического анализа, начиная с первого правила в
грамматика. yyparse() возвращает ненулевое значение, если ввод может быть проанализирован в соответствии с
грамматика; он возвращает ноль, если вход не может быть проанализирован.

Префикс «yy» или «YY» добавляется ко всем видимым извне символам в сгенерированном
парсер. Это предназначено для снижения риска загрязнения пространства имен в клиентских программах.
(Выбор yy является историческим; см. закон(1) и Yacc(1), например.)

ДОПОЛНИТЕЛЬНЫЕ ОПЦИИ


колышек и нога предоставьте следующие варианты:

-h печатает сводку доступных опций и закрывается.

-выход
записывает сгенерированный парсер в файл выходной вместо стандартного вывода.

-v записывает подробную информацию в стандартную ошибку во время работы.

-V записывает информацию о версии в стандартную ошибку и завершает работу.

A ПРОСТО ПРИМЕР


Следующие колышек input определяет грамматику с одним правилом (называемым "начало"), которое
удовлетворяется, когда ввод содержит строку «имя пользователя».

start <- "имя пользователя"

(Кавычки часть совпадающего текста; они служат для обозначения буквального
строка для сопоставления.) Другими словами, yyparse() в сгенерированном источнике C вернет
ненулевое значение, только если следующие восемь символов читают слово «имя пользователя».
Если вход содержит что-то еще, yyparse() возвращает ноль, и ввод не будет
потребляется. (Последующие звонки yyparse() также вернет ноль, поскольку синтаксический анализатор
эффективно заблокирован поиск строки "имя пользователя".) Чтобы обеспечить прогресс, мы можем добавить
альтернативное предложение к правилу "начало", которое будет соответствовать любому одиночному символу, если "имя пользователя"
не найден.

start <- "имя пользователя"
/.

yyparse() теперь всегда возвращает ненулевое значение (кроме самого конца ввода). Делать
что-то полезное мы можем добавить к правилам. Эти действия выполняются после
найдено полное совпадение (начиная с первого правила) и выбираются согласно
'путь', пройденный через грамматику, чтобы соответствовать вводу. (Лингвисты назвали бы этот путь
'фразовый маркер'.)

start <- "имя пользователя" {printf ("% s \ n", getlogin ()); }
/ <. > {путчар (yytext [0]); }

Первая строка инструктирует синтаксический анализатор печатать логин пользователя всякий раз, когда он видит
"имя пользователя" во входных данных. Если это совпадение не удается, вторая строка сообщает синтаксическому анализатору эхо
следующий символ на входе стандартный вывод. Наш парсер теперь выполняет полезные
работа: он копирует ввод в вывод, заменяя все вхождения "username" на
имя учетной записи пользователя.

Обратите внимание на угловые скобки ('<' и '>'), которые были добавлены ко второй альтернативе. Эти
не влияют на значение правила, но служат для ограничения текста, доступного для
следующее действие в переменной yyтекст.

Если указанная выше грамматика помещена в файл имя пользователя.peg, запустив команду

привязка -o имя пользователя.c имя пользователя.peg

сохранит соответствующий парсер в файл имя пользователя.c. Чтобы создать полную программу
этот синтаксический анализатор может быть включен программой на C следующим образом.

#включают / * printf (), putchar () * /
#включают / * getlogin () * /

#include "username.c" / * yyparse () * /

int main ()
{
while (yyparse ()) / * повторять до EOF * /
;
0 вернуться;
}

PEG ГРАММАТИКИ


Грамматика состоит из набора именованных правил.

имя <- шаблон

В описания содержит один или несколько из следующих элементов.

имя Элемент обозначает весь шаблон в правиле с заданным имя.

"символы"
Символ или строка, заключенные в двойные кавычки, соответствуют буквально. Стандарт ANSI C
escape-последовательности распознаются внутри символы.

'символы'
Символ или строка, заключенные в одинарные кавычки, сопоставляются буквально, как указано выше.

[символы]
Набор символов, заключенный в квадратные скобки, соответствует любому одиночному символу из
набор с escape-символами, распознаваемыми, как указано выше. Если набор начинается с
uparrow (^), то набор инвертируется (элемент соответствует любому символу в
установленный). Любая пара символов, разделенных тире (-), представляет диапазон
символы с первого по второй включительно. Один буквенный символ
или подчеркивание соответствует следующему набору.

[а-я-я_]

Точно так же следующее соответствует любому одиночному нецифровому символу.

[^ 0-9]

. Точка соответствует любому символу. Обратите внимание, что это не удается только в конце
файл, в котором нет символа для сопоставления.

( описания )
Круглые скобки используются для группировки (изменения приоритета операторов
описано ниже).

{ действие }
Фигурные скобки окружают действия. Действие - произвольный исходный код C, который должен быть
выполняется в конце сопоставления. Все фигурные скобки в действии должны быть правильно
вложенные. Любой вводимый текст, который был сопоставлен до действия и разделен углом
скобки (см. ниже) доступны в действии как содержимое
массив символов yyтекст. Длина (количество символов в) yyтекст is
доступно в переменной Yyleng. (Эти имена переменных являются историческими; см.
закон(1)).

< Открывающая угловая скобка всегда совпадает (без ввода данных) и вызывает синтаксический анализатор
чтобы начать накапливать совпадающий текст. Этот текст будет доступен для действий в
переменная yyтекст.

> Закрывающая угловая скобка всегда совпадает (без ввода данных) и вызывает синтаксический анализатор
прекратить накапливать текст для yyтекст.

Приведенные выше элементs можно сделать необязательными и / или повторяемыми со следующими суффиксами:

элемент ?
Элемент не является обязательным. Если присутствует на входе, он потребляется, и совпадение
удается. Если его нет на входе, текст не используется и совпадение завершается успешно.
так или иначе.

элемент +
Элемент повторяемый. Если присутствует на входе, одно или несколько вхождений
элемент потребляются, и матч считается успешным. Если нет элемент
присутствует на входе, совпадение не выполняется.

элемент *
Элемент является необязательным и повторяемым. Если присутствует на входе, один или несколько
появления элемент потребляются, и матч считается успешным. Если нет
элемент присутствуют на входе, совпадение все равно будет успешным.

Вышеупомянутые элементы и суффиксы могут быть преобразованы в предикаты (соответствующие произвольным
ввести текст и впоследствии успешно или неуспешно без потребляя этот ввод) с
следующие префиксы:

& элемент
Предикат успешен, только если элемент можно сопоставить. Вводимый текст отсканирован, пока
согласование элемент не расходуется на входе и остается доступным для
последующее сопоставление.

! элемент
Предикат успешен, только если элемент не может быть сопоставлено. Вводимый текст отсканирован, пока
согласование элемент не расходуется на входе и остается доступным для
последующее сопоставление. Популярная идиома

!.

что соответствует концу файла, после того, как последний символ ввода уже
был потреблен.

Предусмотрена специальная форма предиката '&':

&{ выражение }
В этом предикате простой C выражение ( заявление) оценивается немедленно
когда синтаксический анализатор достигает предиката. Если выражение дает ненулевое значение (истина)
«совпадение» завершается успешно, и синтаксический анализатор переходит к следующему элементу в шаблоне.
Если же линия индикатора выражение дает ноль (ложь), совпадение не выполняется, и парсер выполняет резервное копирование до
ищите альтернативный синтаксический анализ ввода.

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

Последовательности могут быть разделены на непересекающиеся альтернативы оператором чередования '/'.

последовательность-1 / последовательность-2 / ... / последовательность-N
Каждая последовательность проверяется по очереди до тех пор, пока одна из них не совпадет, и в это время совпадение
для общей картины удается. Если ни одна из последовательностей не соответствует, то совпадение
общей картины не удается.

Наконец, знак фунта (#) вводит комментарий (отбрасывается), который продолжается до конца.
линии.

Подводя итог вышесказанному, синтаксический анализатор пытается сопоставить вводимый текст с шаблоном
содержащие литералы, имена (представляющие другие правила) и различные операторы (записанные как
префиксы, суффиксы, сопоставление для упорядочивания и оператора чередования инфиксов), которые
изменить способ сопоставления элементов в шаблоне. Совпадения делаются слева направо
справа, «по убыванию» в именованные подправила по мере их появления. Если процесс сопоставления
терпит неудачу, синтаксический анализатор "отслеживает" ("перематывает" ввод соответствующим образом в процессе), чтобы
найти ближайший альтернативный «путь» по грамматике. Другими словами, парсер
выполняет поиск в глубину слева направо для первого успешно совпадающего пути
через правила. При обнаружении выполняются действия по успешному пути (в
порядок, в котором они встречались).

Обратите внимание, что предикаты оцениваются немедленно во время поиска удачного совпадения,
поскольку они способствуют успеху или неудаче поиска. Действия, однако,
оценивается только после того, как найдено успешное совпадение.

PEG ГРАММАТИКА Для PEG ГРАММАТИКИ


Грамматика для колышек грамматики показана ниже. Это проиллюстрирует и формализует
выше описание.

Грамматика <- Определение интервала + EndOfFile

Определение <- Идентификатор LEFTARROW Выражение
Выражение <- Последовательность (последовательность слэш) *
Последовательность <- Префикс *
Префикс <- И действие
/ (И | НЕ)? Суффикс
Суффикс <- Основной (ЗАПРОС / ЗВЕЗДА / ПЛЮС)?
Первичный <- Идентификатор! СТРЕЛКА ВЛЕВО
/ OPEN Выражение CLOSE
/ Буквальный
/ Класс
/ ТОЧКА
/ Действие
/ НАЧИНАТЬ
/ КОНЕЦ

Идентификатор <- <IdentStart IdentCont *> Интервал
IdentStart <- [a-zA-Z_]
IdentCont <- IdentStart / [0-9]
Литерал <- ['] <(! ['] Char) *> ['] Интервал
/ ["] <(! ["] Char) *> ["] Интервал
Класс <- '[' <(! ']' Диапазон) *> ']' Интервал
Диапазон <- Char '-' Char / Char
Char <- '\\' [abefnrtv '"\ [\] \\]
/ '\\' [0-3][0-7][0-7]
/ '\\' [0-7] [0-7]?
/ '\\' '-'
/! '\\'.
LEFTARROW <- '<-' Интервал
SLASH <- '/' Интервал
И <- '&' Интервал
НЕ <- '!' Интервал
ЗАПРОС <- '?' Интервал
ЗВЕЗДА <- '*' Интервал
PLUS <- '+' Интервал
OPEN <- '(' Интервал
ЗАКРЫТЬ <- ')' Интервал
ТОЧКА <- '.' Интервал
Интервал <- (Пробел / Комментарий) *
Комментарий <- '#' (! EndOfLine.) * EndOfLine
Пробел <- '' / '\ t' / EndOfLine
EndOfLine <- '\ r \ n' / '\ n' / '\ r'
EndOfFile <-!.
Действие <- '{' <[^}] *> '}' Интервал
BEGIN <- '<' Интервал
END <- '>' Интервал

LEG ГРАММАТИКИ


нога это вариант колышек что добавляет некоторые особенности закон(1) и Yacc(1). Он отличается от
колышек следующими способами.

%{ текст... %}
Раздел объявления может появиться везде, где ожидается определение правила. В
текст между разделителями '% {' и '%}' копируется дословно в сгенерированный C
код парсера до код, реализующий сам парсер.

имя = описания
Оператор присваивания заменяет стрелку влево «<-».

имя-правила
Дефисы могут отображаться как буквы в названиях правил. Каждый дефис преобразуется в
подчеркивание в сгенерированном исходном коде C. Одиночный дефис '-' - это
юридическое название правила.

- = [\ t \ n \ r] *
число = [0-9] + -
name = [a-zA-Z _] [a-zA_Z_0-9] * -
l-paren = '(' -
r-paren = ')' -

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

последовательность-1 | последовательность-2
Оператор чередования - вертикальная черта '|' вместо косой черты '/'. В
колышек править

имя <- последовательность-1
/ последовательность-2
/ последовательность-3

поэтому написано

имя = последовательность-1
| последовательность-2
| последовательность-3
;

in нога (последняя точка с запятой необязательна, как описано далее).

ехр ~ { действие }
Постфиксный оператор ~{ действие } может быть помещен после любого выражения и будет вести себя
как обычное действие (произвольный код C), за исключением того, что оно вызывается только тогда, когда ехр
терпит неудачу. Он связывает менее жестко, чем любой другой оператор, за исключением чередования и
секвенирования и призван упростить обработку ошибок и код восстановления.
записывать. Обратите внимание, что yyтекст и Yyleng недоступны внутри этих действий, но
указатель переменной yy доступен, чтобы предоставить коду доступ к любому определенному пользователем
члены состояния синтаксического анализатора (см. «НАСТРОЙКА ПАРАМЕТРА» ниже). Отметим также, что
ехр всегда одно выражение; вызвать действие при ошибке для любого сбоя в
последовательность, круглые скобки должны использоваться, чтобы сгруппировать последовательность в один
выражение.

rule = e1 e2 e3 ~ {error ("e [12] ok; e3 не удалось"); }
| ...

rule = (e1 e2 e3) ~ {error ("один из e [123] отказал"); }
| ...

описания ;
Знак пунктуации точка с запятой может опционально завершать описания.

%% текст...
Двойной процент '%%' завершает раздел правил (и объявлений)
грамматика. Все текст следующий '%%' дословно копируется в сгенерированный код синтаксического анализатора C
после код реализации парсера.

$$ = ценностное
Подправило может возвращать семантическое ценностное из действия, назначив его
псевдопеременная '$$'. Все семантические значения должны иметь один и тот же тип (по умолчанию
в 'int'). Этот тип можно изменить, указав YYSTYPE в разделе объявлений.

идентификатор:имя
Семантическое значение, возвращаемое (путем присвоения '$$') из подправила. имя is
связано с идентификатор и на него можно будет ссылаться в последующих действиях.

Пример настольного калькулятора ниже иллюстрирует использование «$$» и «:».

LEG Пример: A СТОЛ КАЛЬКУЛЯТОР


Расширения в нога описанные выше позволяют использовать полезные синтаксические анализаторы и оценщики (включая
декларации, правила грамматики и вспомогательные функции C, такие как 'main'), которые должны оставаться в пределах
единый исходный файл. Чтобы проиллюстрировать это, мы показываем простой настольный калькулятор, поддерживающий
четыре общих арифметических оператора и именованные переменные. Промежуточные итоги
арифметические вычисления будут накапливаться в неявном стеке, возвращая их как
семантические значения из подправил.

%{
#включают / * printf () * /
#включают / * atoi () * /
int vars [26];
%}

Stmt = - e: Expr EOL {printf ("% d \ n", e); }
| (! EOL.) * EOL {printf ("ошибка \ n"); }

Expr = i: ID ASSIGN s: Sum {$$ = vars [i] = s; }
| s: Сумма {$$ = s; }

Sum = l: Продукт
(ПЛЮС r: Продукт {l + = r;}
| МИНУС r: Продукт {l - = r; }
) * {$$ = l; }

Product = l: значение
(РАЗ r: значение {l * = r;}
| РАЗДЕЛИТЬ r: значение {l / = r; }
) * {$$ = l; }

Значение = i: ЧИСЛО {$$ = atoi (yytext); }
| i: ID! НАЗНАЧЕНИЕ {$$ = vars [i]; }
| ОТКРЫТЬ i: Выражение ЗАКРЫТЬ {$$ = i; }

НОМЕР = <[0-9] +> - {$$ = atoi (yytext); }
ID = <[az]> - {$$ = yytext [0] - 'a'; }
НАЗНАЧЕНИЕ = '=' -
ПЛЮС = '+' -
МИНУС = '-' -
ВРЕМЯ = '*' -
РАЗДЕЛИТЬ = '/' -
ОТКРЫТЬ = '(' -
ЗАКРЫТЬ = ')' -

- = [\ t] *
EOL = '\ n' | '\ r \ n' | '\ r' | ';'

%%

int main ()
{
в то время как (yyparse ())
;
0 вернуться;
}

LEG ГРАММАТИКА Для LEG ГРАММАТИКИ


Грамматика для нога грамматики показана ниже. Это проиллюстрирует и формализует
выше описание.

грамматика = -
(декларация | определение) +
трейлер? конец файла

декларация = '% {' <(! '%}'.) *> RPERCENT

трейлер = '%%' <. *>

определение = идентификатор EQUAL выражение SEMICOLON?

выражение = последовательность (последовательность BAR) *

последовательность = ошибка +

error = prefix (действие ТИЛЬДЫ)?

префикс = действие И
| (И | НЕ)? суффикс

суффикс = основной (ЗАПРОС | ЗВЕЗДА | ПЛЮС)?

primary = идентификатор COLON идентификатор! EQUAL
| идентификатор! EQUAL
| ОТКРЫТЬ выражение ЗАКРЫТЬ
| буквальный
| класс
| ТОЧКА
| действие
| НАЧИНАТЬ
| КОНЕЦ

идентификатор = <[-a-zA-Z _] [- a-zA-Z_0-9] *> -

literal = ['] <(! ['] char) *> ['] -
| ["] <(! ["] символ) *> ["] -

class = '[' <(! ']' диапазон) *> ']' -

диапазон = char '-' char | символ

char = '\\' [abefnrtv '"\ [\] \\]
| '\\' [0-3][0-7][0-7]
| '\\' [0-7] [0-7]?
| ! '\\'.

action = '{' <фигурные скобки *> '}' -

фигурные скобки = '{' фигурные скобки * '}'
| ! '}'.

РАВНО = '=' -
COLON = ':' -
SEMICOLON = ';' -
BAR = '|' -
И = '&' -
НЕ = '!' -
ЗАПРОС = '?' -
ЗВЕЗДА = '*' -
ПЛЮС = '+' -
ОТКРЫТЬ = '(' -
ЗАКРЫТЬ = ')' -
DOT = '.' -
НАЧАТЬ = '<' -
КОНЕЦ = '>' -
ТИЛЬДА = '~' -
RPERCENT = '%}' -

- = (пробел | комментарий) *
пробел = '' | '\ t' | конец линии
комментарий = '#' (! конец строки.) * конец строки
конец строки = '\ r \ n' | '\ n' | '\р'
конец файла =!.

НАСТРОЙКА ПАРСЕР


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

ГИСТИП
Тип семантического значения. Псевдопеременная "$$" и идентификаторы, "привязанные" к
результаты правила с оператором двоеточия ':' следует рассматривать как объявленные
иметь этот тип. Значение по умолчанию - int.

YYPARSE
Имя основной точки входа в парсер. Значение по умолчанию - yyparse.

YYPARSEFROM
Имя альтернативной точки входа в парсер. Эта функция ожидает одного
аргумент: функция, соответствующая правилу, по которому выполняется поиск совпадения
должно начаться. По умолчанию - yyparsefrom. Обратите внимание, что yyparse () определяется как

int yyparse () {вернуть yyparsefrom (yy_foo); }

где «foo» - это имя первого правила грамматики.

YY_INPUT (ЬиЕ, результат, макс_размер)
Этот макрос вызывается анализатором для получения большего количества входного текста. ЬиЕ указывает на
область памяти, которая может вместить не более макс_размер символы. Макрос должен копировать
введите текст в ЬиЕ а затем присвоить целочисленную переменную результат указать на
количество скопированных символов. Если больше нет доступных входных данных, макрос должен
присвоить 0 результат. По умолчанию макрос YY_INPUT определяется следующим образом.

#define YY_INPUT (buf, result, max_size) \
{\
int yyc = getchar (); \
результат = (EOF == yyc)? 0: (* (buf) = yyc, 1); \
}

Обратите внимание, что если YY_CTX_LOCAL определен (см. Ниже), то дополнительный первый аргумент,
содержащий контекст парсера, передается в YY_INPUT.

ГГ_DEBUG
Если эти символы определены, то в парсер будет включен дополнительный код,
выводит огромное количество тайной информации до стандартной ошибки, в то время как синтаксический анализатор
бежит.

ГГ_BEGIN
Этот макрос вызывается, чтобы отметить начало ввода текста, который будет доступен
в действиях как yytext. Это соответствует появлению символа «<» в грамматике.
Они преобразуются в предикаты, которые, как ожидается, будут успешными. По умолчанию
определение

#define YY_BEGIN (yybegin = yypos, 1)

поэтому сохраняет текущую позицию ввода и возвращает 1 ('истина') в результате
сказуемое.

ГГ_END Этот макрос соответствует ">" в грамматике. Опять же, это предикат, поэтому
определение по умолчанию сохраняет позицию ввода перед «успехом».

#define YY_END (yyend = yypos, 1)

YY_PARSE (T)
Этот макрос объявляет точки входа парсера (yyparse и yyparsefrom) как имеющие тип
T. Определение по умолчанию

#define YY_PARSE (T) T

оставляет yyparse () и yyparsefrom () с глобальной видимостью. Если их не должно быть
видимый извне в других исходных файлах, этот макрос можно переопределить, чтобы объявить
они «статичны».

#define YY_PARSE (T) static T

ГГ_CTX_LOCAL
Если этот символ определяется при компиляции сгенерированного парсера, то глобальный
состояние парсера будет храниться в структуре типа yycontext, которую можно объявить
как локальная переменная. Это позволяет сосуществовать нескольким экземплярам парсеров и
быть потокобезопасным. Функция синтаксического анализа yyparse() будет объявлен ожидающим первого
аргумент типа 'yycontext *', экземпляр структуры, содержащей глобальный
состояние для парсера. Этот экземпляр должен быть выделен и инициализирован нулем с помощью
клиент. Тривиальный, но полный пример выглядит следующим образом.

#включает в себя

# определить YY_CTX_LOCAL

#include "the-generated-parser.peg.c"

int main ()
{
yycontextctx;
memset (& ctx, 0, sizeof (yycontext));
while (yyparse (& ctx));
0 вернуться;
}

Обратите внимание, что если этот символ не определен, то скомпилированный синтаксический анализатор будет статически
выделить свое глобальное состояние и не будет ни реентерабельным, ни поточно-ориентированным. Обратите внимание также
что структура yycontext парсера инициализируется автоматически в первый раз
yyparse() называется; эта структура должен поэтому должным образом инициализироваться нулем
перед первым звонком yyparse().

YY_CTX_MEMBERS
Если YY_CTX_LOCAL определен (см. Выше), то может быть определен макрос YY_CTX_MEMBERS
для расширения до любых дополнительных объявлений полей-членов, которые клиент хотел бы
включены в объявление структурного типа yycontext. Эти дополнительные
в противном случае члены игнорируются сгенерированным синтаксическим анализатором. Экземпляр yycontext
связанный с активным в данный момент синтаксическим анализатором, доступен в действиях как
указатель переменной yy.

ГГ_BUFFER_SIZE
Начальный размер текстового буфера в байтах. По умолчанию 1024 и буфер
размер увеличивается вдвое, когда это необходимо для удовлетворения спроса во время синтаксического анализа. Приложение
который обычно анализирует гораздо более длинные строки, может увеличить это, чтобы избежать ненужных
перераспределение буфера.

ГГ_STACK_SIZE
Начальный размер стека переменных и действий. По умолчанию 128, то есть
удваивается всякий раз, когда требуется для удовлетворения спроса во время синтаксического анализа. Приложения, у которых есть
глубокие стеки вызовов со многими локальными переменными или которые выполняют много действий после
единственное успешное совпадение, может увеличить это, чтобы избежать ненужного буфера
перераспределение.

YY_MALLOC (YY, РАЗМЕР)
Распределитель памяти для всей памяти, связанной с анализатором. Параметры - это
текущая структура yycontext и количество выделяемых байтов. По умолчанию
определение: malloc (РАЗМЕР)

YY_REALLOC (YY, PTR, РАЗМЕР)
Перераспределитель памяти для динамически увеличиваемого хранилища (например, текстовых буферов и
переменные стеки). Параметры - это текущая структура yycontext,
ранее выделенное хранилище и количество байтов, в которое должно это хранилище
расти. Определение по умолчанию: realloc (PTR, РАЗМЕР)

ГГ_БЕСПЛАТНО (YY, PTR)
Освободитель памяти. Параметры - это текущая структура yycontext и
память, которую нужно освободить. Определение по умолчанию: бесплатно (PTR)

ГОДРЕЛИЗ
Имя функции, которая освобождает все ресурсы, удерживаемые структурой yycontext.
Значение по умолчанию - «yyrelease».

В действиях можно ссылаться на следующие переменные.

колесница * yybuf
Эта переменная указывает на входной буфер анализатора, используемый для хранения входного текста,
еще не найдено.

Int юпос
Это смещение (в yybuf) следующего символа, который должен быть сопоставлен и использован.

колесница * yytext
В этой переменной сохраняется самый последний совпавший текст, разделенный '<' и '>'.

Int Yyleng
Эта переменная указывает количество символов в yytext.

yycontext * уу
Эта переменная указывает на экземпляр yycontext, связанный с
активный в данный момент парсер.

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

yyrelease (yycontext*yy)
Возвращает все выделенное парсером хранилище, связанное с yy в систему. Хранилище
будет перераспределен при следующем вызове в yyparse().

Обратите внимание, что хранилище для самой структуры yycontext никогда не выделяется и не освобождается.
неявно. Приложение должно разместить эти структуры в автоматическом хранилище или использовать
каллок() и бесплатно() для явного управления ими. Пример в следующем разделе
демонстрирует один подход к управлению ресурсами.

LEG Пример: РАСШИРЕНИЕ ПАРЗЕР КОНТЕКСТ


В yy переменная, передаваемая в действия, содержит состояние парсера плюс любые дополнительные
поля, определенные YY_CTX_MEMBERS. Эти поля могут использоваться для хранения специфичных для приложения
информация, которая является глобальной для конкретного вызова yyparse(). Тривиальный, но полный нога
пример, в котором структура yycontext расширена с помощью считать из числа
символы новой строки, видимые во вводе до сих пор (в противном случае грамматика потребляет и игнорирует
весь ввод). Звонивший yyparse() использует считать напечатать количество строк
ввод, который был прочитан.

%{
# определить YY_CTX_LOCAL 1
# определить YY_CTX_MEMBERS \
счет;
%}

Char = ('\ n' | '\ r \ n' | '\ r') {yy-> count ++}
| .

%%

#включает в себя
#включают

int main ()
{
/ * создаем локальный контекст парсера в автоматическом хранилище * /
yyконтекст yy;
/ * контекст * должен * быть инициализирован нулем перед первым использованием * /
memset (& yy, 0, sizeof (yy));

а (ггпарс (& гг))
;
printf ("% d новых строк \ n", yy.count);

/ * освобождаем все ресурсы, связанные с контекстом * /
yyrelease (& yy);

0 вернуться;
}

ДИАГНОСТИКИ


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

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

править 'фу' использовал но определенный
Грамматика ссылается на правило с именем «foo», но не дает ему определения.
Попытка использовать сгенерированный синтаксический анализатор, скорее всего, приведет к ошибкам компоновщика.
из-за неопределенных символов, связанных с отсутствующим правилом.

править 'фу' определенный но использовал
Грамматика определила правило с именем «foo», а затем проигнорировала его. Код, связанный
с правилом включается в сгенерированный синтаксический анализатор, который во всех остальных отношениях
быть здоровым.

возможное бесконечный оставил рекурсия in править 'фу'
Существует по крайней мере один путь в грамматике, ведущий от правила 'foo'.
вернуться к (рекурсивному вызову) того же правила без ввода каких-либо данных.

Левая рекурсия, особенно та, что встречается в стандартных документах, часто бывает «прямой» и
подразумевает банальное повторение.

# (6.7.6)
прямой абстрактный-декларатор =
LPAREN аннотация-декларатор RPAREN
| прямой абстрактный декларатор? LBRACKET assign-expr? RBRACKET
| прямой абстрактный декларатор? LBRACKET STAR RBRACKET
| прямой абстрактный декларатор? LPAREN список типов параметров? RPAREN

Рекурсию легко устранить, преобразовав части шаблона, следующие за
рекурсия в повторяемый суффикс.

# (6.7.6)
прямой абстрактный-декларатор =
директ-абстрактный-декларатор-руководитель?
прямой абстрактный-декларатор-хвост *

Директ-абстрактный-декларатор-голова =
LPAREN аннотация-декларатор RPAREN

прямой абстрактный-декларатор-хвост =
LBRACKET присвоить-выражение? КРОНШТЕЙН
| КРОНШТЕЙН LBRACKET STAR RBRACKET
| LPAREN список типов параметров? RPAREN

Пещеры


Парсер, принимающий пустой ввод, будет всегда преуспевать. Рассмотрим следующий пример,
нетипично для первой попытки написать синтаксический анализатор на основе PEG:

Программа = Выражение *
Выражение = "что угодно"
%%
int main () {
в то время как (yyparse ())
кладет («успех!»);
0 вернуться;
}

Эта программа зацикливается бесконечно, независимо от того, какой ввод (если он есть) предоставлен на stdin. Много
возможны исправления, проще всего настаивать на том, чтобы парсер всегда потреблял
непустой ввод. Изменение первой строки на

Программа = Выражение +

выполняет это. Если предполагается, что синтаксический анализатор потребляет весь ввод, то явно
Также настоятельно рекомендуется требовать конец файла:

Программа = Выражение +!.

Это работает, потому что синтаксический анализатор вообще не сможет сопоставить (предикат "!") Какой-либо символ.
("." выражение), когда он пытается прочитать за пределами конца ввода.

Используйте leg онлайн с помощью сервисов onworks.net


Бесплатные серверы и рабочие станции

Скачать приложения для Windows и Linux

Команды Linux

Ad