yacc, применяю правило только один раз
Вопрос
Я пытаюсь написать оболочку, используя yacc и lex, и у меня возникают проблемы с перенаправителями ввода-вывода.В настоящее время я могу использовать операторы < и > в любом порядке, но моя проблема в том, что я могу перенаправить дважды без ошибок, например «ls > log > log2».
Мой код правила приведен ниже. Может ли кто-нибудь дать мне несколько советов, как это исправить?Спасибо!
io_mod:
iomodifier_opt io_mod
|
;
iomodifier_opt:
GREAT WORD {
printf(" Yacc: insert output \"%s\"\n", $2);
Command::_currentCommand._outFile = $2;
}
|
LESS WORD {
printf(" Yacc: insert input \"%s\"\n", $2);
Command::_currentCommand._inputFile = $2;
}
| /* can be empty */
;
РЕДАКТИРОВАТЬ:Поговорив со своим ассистентом, я узнал, что на самом деле мне не обязательно иметь только один модификатор для моей команды и что я действительно могу иметь несколько копий одного и того же перенаправления ввода-вывода.
Решение
Есть два подхода:
(1) Измените грамматику так, чтобы можно было использовать только один модификатор каждого типа:
io_mod_opt: out_mod in_mod | in_mod out_mod | in_mod | out_mod | ;
(2) Измените обработчик предложения, чтобы он подсчитывал модификаторы и сообщал об ошибке, если их больше одного:
GREAT_WORD { if (already_have_output_file()) { error("too many output files: \"%s\"\n", $2) } else { /* record output file */ } }
Вариант (2), вероятно, приведет к улучшению сообщений об ошибках и упрощению грамматики.
Другие советы
Есть и третий подход – не волнуйтесь.Bash (под Cygwin) не генерирует ошибку для:
ls > x > y
Он создает x, а затем y и в конечном итоге записывает в y.
Я понимаю, что это может быть просто упражнение для изучения lexx и yacc, но в остальном первый вопрос - задать почему ты хочешь использовать lexx и yacc?Любой обычный командный язык оболочки имеет довольно простую грамматику;что вы получаете от использования генератора LALR?
Ну, я имею в виду не только сложность, сложность генерации хороших сообщений об ошибках и объем кода.