Захватывать имена, содержащие - но не заканчивающиеся - в тире - PullRequest
2 голосов
/ 13 марта 2020

Я пытаюсь захватить имена (не начинающиеся с цифры) , которые могут содержать тире , например hello-world. Моя проблема в том, что у меня также есть правила для одиночных штрихов и символов, которые конфликтуют с ним:

[A-Za-z][A-Za-z0-9-]+     { /* capture "hello-world" */ }
"-"                       { return '-'; }
">"                       { return '>'; }

Когда лексер читает hello-world->, предыдущие правила дают hello-world- и >, тогда как я ожидал hello-world, - и > для захвата по отдельности. Чтобы решить эту проблему, я исправил это следующим образом:

[A-Za-z][A-Za-z0-9-]*[A-Za-z0-9]+     { /* ensure final dash is never included at the end */ }

Это работает, за исключением однобуквенных слов, поэтому, наконец, я реализовал это:

[A-Za-z][A-Za-z0-9-]*[A-Za-z0-9]+     { /* ensure final dash is never included at the end */ }
[A-Za-z][A-Za-z0-9]*                  { /* capture possible single letter words */ }

Вопрос : Есть ли более элегантный способ сделать это?

1 Ответ

2 голосов
/ 13 марта 2020
[A-Za-z][A-Za-z0-9-]*[A-Za-z0-9]+
[A-Za-z][A-Za-z0-9]*

Обратите внимание, что, как вы сказали, первое правило уже охватывает все, что не является одной буквой. Таким образом, второе правило должно соответствовать только одной букве и может быть сокращено до [A-Za-z]:

[A-Za-z][A-Za-z0-9-]*[A-Za-z0-9]+
[A-Za-z]

Теперь второе правило является простым префиксом первого, поэтому мы можем объединить это в одно правило сделав часть после первой буквы необязательной:

[A-Za-z]([A-Za-z0-9-]*[A-Za-z0-9]+)?

+ в последнем бите не требуется, поскольку все, кроме последнего символа, также может быть сопоставлено средней частью, поэтому самая простая версия :

[A-Za-z]([A-Za-z0-9-]*[A-Za-z0-9])?
...