Я не думаю, что вы найдете простое решение для обработки этих типов ошибок синтаксического анализа в лексере.
Я бы хотел, чтобы лексер (flex / lex) был настолько тупым, насколько это возможно, он должен просто предоставлять поток базовых токенов (идентификаторы, ключевые слова и т. Д.) И иметь анализатор (yacc / bison) для обнаружения ошибок. , На самом деле это именно то, что вы хотите, с небольшой перестройкой вашего подхода ...
В лексере (parser.l) сделайте его простым (без обработки eol / newline), что-то вроде (не полная вещь):
}%
/* I don't recall if the backslashify is required below */
SINGLE_QUOTE_STRING \'.*\'
DOUBLE_QUOTE_STRING \".*\"
%%
{SINGLE_QUOTE_STRING} {
yylval.charstr = copy_to_tmp_buffer(yytext); // implies a %union
return STRING;
}
{DOUBLE_QUOTE_STRING} {
yylval.charstr = copy_to_tmp_buffer(yytext); // implies a %union
return STRING;
}
\n return NEWLINE;
Затем в вашем файле parser.y выполните всю настоящую обработку (не полная вещь):
command:
error NEWLINE
{ yyclearin; yyerrorok; print_the_next_command_prompt(); }
| chdir_command STRING NEWLINE
{ do_the_chdir($<charstr>2); print_the_next_command_prompt(); }
| ... and so on ...
Здесь следует отметить две вещи:
- Смещение таких вещей, как NEWLINE, в сторону yacc, чтобы вы могли определить, когда пользователь завершил работу с командой, затем вы можете очистить вещи и начать все сначала (при условии, что у вас где-то есть «
int yywrap() {return 1;}
»). Если вы попытаетесь обнаружить его слишком рано во флексе, когда вы узнаете, чтобы вызвать ошибку?
- chdir - это не одна команда (если она не была подчинена правилам, а вы ее просто не показывали), теперь она имеет chdir_command STRING (аргумент для chdir). Это делает так, что парсер может выяснить, что пошло не так, вы можете затем yyerror, если этот каталог не существует, и т. Д ...
Таким образом, вы должны получить что-то вроде (угадать, как может выглядеть chdir):
cd 'some_directory
синтаксическая ошибка
cd 'some_directory'
ты в чуваке some_directory!
И все это обрабатывается грамматикой yacc, а не токенизатором.
Я обнаружил, что максимально простое изгибание дает вам наибольшую гибкость. :)