Ответ 1
Это зависит от того, насколько сложным является язык, с которым вы имеете дело.
Нарезка
Это замечательно, когда оно работает, но работает только тогда, когда есть без экранирования. Это не работает для CSV, например, потому что запятые внутри цитируемых строк не являются правильными точками разделения.
Foo, бар, Баз
можно разбить, но
Foo, "бар, Баз"
не может.
Обычный
Регулярные выражения отлично подходят для простых языков с "обычной грамматикой" . Регулярные выражения Perl 5 немного более мощные из-за обратных ссылок, но общее правило:
Если вам нужно сопоставить скобки (
(...)
,[...]
) или другие вложенные как HTML-теги, то регулярных выражений сами по себе недостаточно.
Вы можете использовать регулярные выражения для разбиения строки на известное количество фрагментов - например, вытягивая месяц/день/год с даты. Это неправильная работа для синтаксического анализа сложных арифметических выражений.
Очевидно, если вы пишете регулярное выражение, уходите за чашкой кофе, возвращайтесь и не можете легко понять, что вы только что написали, тогда вам следует искать более четкий способ выразить то, что вы делаете. Адреса электронной почты, вероятно, находятся на пределе того, что можно корректно и с готовностью обрабатывать с помощью регулярных выражений.
Контекст без
Генераторы Parser и парсеры с ручным кодированием /PEG отлично подходят для более сложного ввода, когда вам нужно обрабатывать вложенность, чтобы вы могли построить дерево или иметь дело с приоритет оператора или ассоциативность.
Контекстные бесплатные парсеры часто используют регулярные выражения, чтобы сначала разбивать входные данные на куски (пробелы, идентификаторы, пунктуации, цитируемые строки), а затем использовать грамматику, чтобы превратить этот поток кусков в древовидную форму.
Эмпирическое правило для CF-грамматик
Если регулярные выражения недостаточны, но все слова на языке имеют одинаковое значение независимо от предшествующих объявлений, тогда работает CF.
Без контекста
Если слова на вашем языке меняют смысл в зависимости от контекста, вам нужно более сложное решение. Это почти всегда ручные решения.
Например, в C,
#ifdef X
typedef int foo
#endif
foo * bar
Если foo
- тип, то foo * bar
- это объявление указателя foo
с именем bar
. В противном случае это умножение переменной с именем foo
на переменную с именем bar
.