Разница между RegexpParsers, StandardTokenParsers и JavaTokenParsers в scala

17

Я изучаю Parser Combinators в scala и вижу разные способы парсинга. В основном я вижу три разных типа парсеров, т. е. RegexpParsers, StandardTokenParsers и JavaTokenParsers. Я новичок в разборе и не понимая, как мы выберем подходящий Parser в соответствии с нашим требованием. Может кто-нибудь объяснить, как работают эти разные парсеры и когда их использовать.

    
задан Byju Veedu 30.04.2010 в 12:32
источник

2 ответа

6

RegexpParsers позволяют использовать значения RE (обычно в форме "re pattern".r , но равно как и любой другой экземпляр Regex). Нет предопределенных лексических произведений (токенов).

JavaTokenParsers определяет лексические производные для токенов Java: decimalNumber , floatingPointNumber , stringLiteral , wholeNumber , ident (идентификатор).

StandardTokenParsers определяет лексические произведения «... для простого языка Scala, который анализирует ключевые слова и идентификаторы, числовые литералы (целые числа), строки и разделители». Его составляющие фактически определены в StdLexical .

    
ответ дан Randall Schulz 30.04.2010 в 15:57
22

Существует несколько различных признаков парсера и базовых классов для разных целей.

Основная черта - scala.util.parsing.combinator.Parsers . Это большинство основных комбинаторов, таких как opt , rep , elem , accept и т. Д. Определенно просматривайте документацию для этого, так как это большая часть того, что вам нужно знать. Фактический класс Parser определяется как внутренний класс здесь, и это тоже важно знать.

Другим важным признаком является scala.util.parsing.combinator.lexical.Scanners . Это базовая черта для парсеров, которые читают поток символов и создают поток токенов (также известных как лексеры). Чтобы реализовать этот признак, вам нужно реализовать анализатор whitespace , который читает пробельные символы, комментарии и т. Д. Вам также необходимо реализовать метод token , который читает следующий токен. Токены могут быть любыми, что вы хотите, но они должны быть подклассом Scanners.Token . Lexical extends Scanners и StdLexical extends Lexical . Первый содержит некоторые полезные базовые операции (например, digit , letter ), в то время как последний фактически определяет и лексет общие токены (например, числовые литералы, идентификаторы, строки, зарезервированные слова). Вам просто нужно определить delimiters и reserved , и вы получите что-то полезное для большинства языков. Определения токенов находятся в scala.util.parsing.combinator.token.StdTokens .

Как только у вас есть лексер, вы можете определить синтаксический анализатор, который читает поток токенов (созданных лексером) и генерирует абстрактное синтаксическое дерево. Разделение lexer и parser - хорошая идея, так как вам не нужно беспокоиться о пробелах или комментариях или других осложнениях в вашем синтаксисе. Если вы используете StdLexical , вы можете использовать scala.util.parsing.combinator.syntax.StdTokenPasers , в котором встроены парсеры для перевода токенов в значения (например, StringLit в String ). Я не уверен, в чем разница с StandardTokenParsers . Если вы определяете свои собственные классы токенов, вы просто должны использовать Parsers для простоты.

Вы специально задали вопрос о RegexParsers и JavaTokenParsers . RegexParsers - это черта, которая увеличивает Parsers с одним дополнительным комбинатором: regex , что делает именно то, что вы ожидаете. Смешайте в RegexParsers с вашим лексером, если вы хотите использовать регулярные выражения для соответствия токенам. JavaTokenParsers предоставляет некоторые парсеры, которые лекс-маркеры из синтаксиса Java (например, идентификаторы, целые числа), но без токенового багажа Lexical или StdLexical .

Подводя итог, вы, вероятно, захотите два синтаксических анализатора: один, который читает символы и выдает токены, а другой - принимает токены и выдает АСТ. Используйте что-то, основанное на Lexical или StdLexical для первого. Используйте что-то, основанное на Parsers или StdTokenParsers для второго, в зависимости от того, используете ли вы StdLexical .

    
ответ дан Jay Conrod 30.04.2010 в 20:35