Как назначить приоритеты двум перекрывающимся выражениям? (Ragel)
У меня есть 2 выражения:
ident = alpha . (alnum|[._\-])*;
string = (printable1)+;
# Printable includes almost all Windows-1252 characters with glyphs.
main := ( ident % do_ident | string % do_string )
# The do_* actions have been defined, and generate tokens.
Очевидно, любой идентификатор является строкой. Ragel имеет приоритетных операторов, чтобы преодолеть это. Но независимо от того, как я пытался установить приоритеты, либо некоторые идентификаторы выполняют оба действия, либо некоторые допустимые строки игнорируются (допустимые строки с действительным идентификатором в качестве префикса, например: ab$).
Я нашел один способ обойти это без использования приоритетов:
main := ( ident % do_ident | (string - ident) % do_string )
Но если у меня будет несколько перекрывающихся выражений, это станет громоздким. Это единственный практический способ?
Любая помощь с правильным способом сделать это будет принята с благодарностью.
2 ответа
Взгляните на раздел "6.3 Сканеры" в Руководстве по Ragel.
main := |*
ident => do_ident;
string => do_string;
*|;
Примечание: при использовании сканеров, имейте ts
, te
, а также act
определяется на принимающем языке.
Похоже, ваша проблема в том, что все действительные идентификаторы также являются допустимыми строками, вы просто хотите, чтобы они сначала интерпретировались как идентификатор, если это возможно. Вы можете сначала заставить его принять идентификатор, вставив приоритет в действие выхода для идентификатора, которое переопределяет все переходы для строки:
main := ( ident %(ident_vs_string, 1) % do_ident | string $(ident_vs_string, 0) % do_string )
Это обеспечит, чтобы выходной переход, следующий за допустимым выражением, останавливал работу машины, продолжая или оставляя строку.
Будьте осторожны с тем, как это объединенное выражение заканчивается. Какое бы выражение ни следовало за идентификатором / строкой, оно должно начинаться с символа, недопустимого ни в одном из них, чтобы переходы выхода были четко определены.