Обычно LEPL работает с потоком символов в том виде, в котором они находятся на входе.Это просто, но, как вы видели, вам нужно было бы использовать множество избыточных правил, чтобы игнорировать, например, пробел, где бы это ни было законно, но игнорируется.
Эта проблема имеет общее решение, а именно: сначала запустить входную строку, хотя и относительно простоавтомат, который заботится об этом и других отвлечениях.Он разбивает входные данные на части (например, числа, идентификаторы, операторы и т. Д.) И удаляет игнорируемые части (например, комментарии и пробелы).Это делает остальную часть синтаксического анализатора проще, но в модели по умолчанию LEPL нет места для этого автомата, который, кстати, называется токенизатором или лексическим анализатором (для краткости лексером).
Каждый тип токена обычно определяется как обычныйвыражение, которое описывает, что входит в каждый токен, например, [+-][0-9]+
для целых чисел.Вы можете (а иногда и должны) сделать это с помощью Token()
, например, Token('a+b+')
дает парсер, который потребляет столько входных данных, сколько соответствует регулярному выражению, а затем возвращает его в виде одной строки.По большей части эти синтаксические анализаторы работают так же, как и все остальные, что наиболее важно, они могут комбинироваться одинаково.Например, Token('a+') & Token('b+')
работает и эквивалентно предыдущему, за исключением того, что создает две строки, а Token('a+') + Token('b+')
точно эквивалентно.Пока что это просто более короткая запись для некоторых основных строительных блоков некоторых грамматик.Вы также можете использовать некоторые классов LEPL с Token()
, чтобы преобразовать его в эквивалентное регулярное выражение и использовать его в качестве токена - например, Token(Literal('ab+'))
равен Token(r'ab\+')
.
Один важныйРазница и огромное преимущество в том, что, используя токены, вы также можете задавать шаблоны, которые выпадают и отбрасывают некоторые входные данные, если нет другого токена, который бы соответствовал - по умолчанию отбрасывается пробел, который очень легко игнорирует пробел (хотя все еще позволяет парсеру требоватьпробел в некоторых местах).Недостатком является то, что вы должны обернуть все сопоставители без токенов в токены или написать эквивалентные правила вручную, если они не могут быть преобразованы автоматически.