Заставить CL-Lex прочитать слово целиком - PullRequest
4 голосов
/ 28 марта 2012

Я использую CL-Lex для реализации лексера (как ввод для CL-YACC), и в моем языке есть несколько ключевых слов, таких как «let» и «in». Однако, хотя лексер распознает такие ключевые слова, он делает слишком много. Когда он находит такие слова, как «init», он возвращает первый токен как IN, а должен возвращать токен «CONST» для слова «init».

Это простая версия лексера:

(define-string-lexer lexer
     (...)
     ("in"   (return (values :in $@)))
     ("[a-z]([a-z]|[A-Z]|\_)"  (return (values :const $@))))

Как заставить лексера полностью прочитать все слово, пока не появится пробел?

Ответы [ 2 ]

8 голосов
/ 21 ноября 2012

Это и исправление ошибок Kaz, и вотум доверия для ОП.

В своем первоначальном ответе Каз утверждает порядок приоритета Unix lex точно в обратном порядке.Из документации lex:

Lex может справиться с неоднозначными спецификациями.Когда более чем одно выражение может соответствовать текущему вводу, Лекс выбирает следующее:

  1. Предпочтительнее самое длинное совпадение.

  2. Среди правил, которые соответствуюттакое же количество символов, правило, данное первым, является предпочтительным.

Кроме того, Kaz не прав, чтобы критиковать решение OP, заключающееся в использовании сопоставления границ слов в Perl-regex.Когда это происходит, вам разрешается (без мучительной вины) сопоставлять слова любым способом, который будет поддерживать ваш генератор лексеров.CL-LEX использует регулярные выражения Perl, которые используют \b в качестве удобного синтаксиса для более громоздкого lex приблизительного значения:

%{
#include <stdio.h>
%}

WC      [A-Za-z']
NW      [^A-Za-z']

%start      INW NIW

{WC}  { BEGIN INW; REJECT; }
{NW}  { BEGIN NIW; REJECT; }

<INW>a { printf("'a' in wordn"); }
<NIW>a { printf("'a' not in wordn"); }

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

Несмотря на то, что Каз хотел ударить его, ОП правильно ответил на свой вопрос, придумав решение, которое использует гибкость выбранного им генератора лексера.

1 голос
/ 28 марта 2012

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

В классическом Unix lex, если оба правила соответствуют одинаковой длине ввода, приоритет имеетк правилу, которое встречается первым в спецификации.В противном случае доминирует максимально возможное совпадение.

(Хотя без RTFM я не могу сказать, что именно так и происходит в CL-LEX, он делает правдоподобную гипотезу о том, что происходит в этом случае.)

Похоже, вам не хватает оператора регулярных выражений Клини, чтобы соответствовать более длинному токену во втором правиле.

...