Разделение зарезервированных идентификаторов во flex

У меня есть язык, для которого я делаю парсер, содержащий вызовы функций. Несколько имен функций зарезервированы, и я хотел бы обрабатывать их по-другому в своем грамматике. В EBNF это будет выглядеть так

FunctionCall ::= FunctionName '(' ')'
SpecialFunctionCall :: SpecialName '(' ')'

FunctionName ::= VariableName - SpecialFunctionName

SpecialFunctionName ::= "special_function_a" | "special_function_b"

Моя проблема заключается в переводе оператора exception из EBNF в flex.

FunctionName    {Letter}{LetterOrDigit}

Является супернабором SpecialFunctionName, который представляет собой жестко запрограммированную строку.

SpecialFunctionName   "special_function_a" | "special_function_b"

Поэтому я получаю предупреждение от bison о том, что SpecialFunction никогда не будет сопоставлено. Должен ли я объединить токены и сравнить строки в синтаксическом анализаторе, или есть рекомендуемый способ разрешить эту двусмысленность во flex?


person Akusete    schedule 12.11.2010    source источник


Ответы (2)


Обычный способ справиться с этим, когда лексический анализатор распознает специальные имена и возвращает правильный тип токена (SpecialName) для специальных имен и токен обычного идентификатора (очевидно, FunctionName) для других токенов.

Однако обычно требуется чрезмерная предусмотрительность со стороны лексического анализатора, чтобы сказать, что конкретное (незарезервированное, неспециальное) слово является именем функции, а не простым идентификатором (который также может быть простой переменной — если только вы не пошли по пути Perl, используя сигилы для идентификации переменных из функций).

person Jonathan Leffler    schedule 12.11.2010
comment
обычно это требует чрезмерной степени предвидения, не могли бы вы уточнить? - person Akusete; 15.11.2010
comment
@Akusete: во многих грамматиках нет лексической разницы между идентификатором, используемым для переменной, и идентификатором, используемым для функции (Perl является исключением со своими сигилами). Итак, чтобы лексический анализатор определил, что то или иное имя является переменной или функцией, он должен иметь доступ к некоторой нелексической информации (информации таблицы символов). Если все переменные и функции должны быть объявлены/определены перед использованием, тогда необходимая информация может быть доступна - и вы избегаете необходимости предвидения. Такие языки, как C, традиционно несколько небрежны в этом отношении. [...продолжение...] - person Jonathan Leffler; 15.11.2010
comment
@Akusete: альтернатива состоит в том, что лексический анализатор просматривает некоторое количество токенов и определяет из контекста, что имя, которое он просматривает, должно быть именем функции, а не идентификатором, но обычно вы изо всех сил пытаетесь избежать такого большого знания грамматики. в лексический анализатор. - person Jonathan Leffler; 15.11.2010
comment
Спасибо, мне удалось устранить двусмысленность, заставив лексер использовать контекст предыдущего токена (в этом языке оператору должен предшествовать взаимоисключающий набор имен переменных). - person Akusete; 15.11.2010

Пока вы помещаете правило SpecialFunction ПЕРВЫМ в файл lexer:

{SpecialFunctionName}    { return SpecialName; }
{FunctionName}           { return FunctionName; }

любой идентификатор, соответствующий обоим шаблонам, активирует первое правило и, таким образом, вернет SpecialName вместо FunctionName.

person Chris Dodd    schedule 06.05.2013