Я беру курс по построению компилятора, и мое текущее задание - написать лексер для языка, который мы реализуем. Я не могу понять, как удовлетворить требование, чтобы лексер должен распознавать сцепленные маркеры. То есть, токены не разделяются пробелами. Например: строка 39if
должна быть признана цифрой 39
и ключевым словом if
. Одновременно лексер должен также exit(1)
, когда он встречает недействительный ввод.Как сделать лекс/flex распознать маркеры, не разделенные пробелами?
упрощенная версия кода у меня есть:
%{
#include <stdio.h>
%}
%option main warn debug
%%
if |
then |
else printf("keyword: %s\n", yytext);
[[:digit:]]+ printf("number: %s\n", yytext);
[[:alpha:]][[:alnum:]]* printf("identifier: %s\n", yytext);
[[:space:]]+ // skip whitespace
[[:^space:]]+ { printf("ERROR: %s\n", yytext); exit(1); }
%%
Когда я запускаю этот (или мою полную версию), и передать его на вход 39if
, правило об ошибке сопоставляется и выход ERROR: 39if
, когда Я хотел бы, чтобы это было:
number: 39
keyword: if
(т.е. такой же, как если бы я вошел 39 if
как вход.)
Going by the manual, у меня есть догадка, что причина в том, что правило ошибки соответствует более длинному возможному вводу, чем правила числа и ключевых слов, и Flex предпочтет его. Тем не менее, я понятия не имею, как разрешить эту ситуацию. Представляется невозможным написать явное regexp, которое отклонит все входные данные без ошибок, и я не знаю, как еще написать правило «catch-all» для обработки ошибок lexer.
UPDATE: Я полагаю, я мог бы просто сделать всеохватывающее правило быть . { exit(1); }
, но я хотел бы получить более хороший отладочный вывод, чем «я запутался в строке 1».
a) Вы используете упрощенную версию? б) Что делает это неправильно? –
@IraBaxter Извините, кажется, я забыл быть явным о своем тестовом случае, проиграв в спекуляциях в последнем абзаце. Ответы: ** a) ** да; и ** b) ** сообщает об ошибке лексера вместо двух токенов. (Я также добавил их в вопрос.) – millimoose
Ах.Хорошо, да, ваше правило «^ space» будет употреблять любую последовательность не-пробелов и, следовательно, потреблять «39if». Секрет: избегайте правил, чьи регулярные выражения перекрываются, если только более длинное правило не вступит в первую очередь. В вашем случае я бы использовал (я не lex-pert) что-то заменить:^space: это было «не цифра, не буква, а не пробел». ... –