Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

Основной признак 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.