Глава 6. Обработка пробелов

Аннотация

Публикация
Учебник библиотеки FParsec
Дата
Ссылки

FParsec обрабатывает пробелы (пробелы, табуляции, новые строки и т. д.) Так же, как и любой другой ввод, поэтому наш синтаксический анализатор floatList еще не умеет работать с пробелами:

> test floatBetweenBrackets "[1.0, 2.0]";;
Failure: Error in Ln: 1 Col: 5
[1.0, 2.0]
    ^
Expecting: ']'

Если мы хотим, чтобы синтаксический анализатор игнорировал пробелы, нам нужно сделать это явным образом.

Во-первых, нам нужно определить, что мы хотим принять в качестве пробела. Для простоты мы просто используем встроенный синтаксическим анализатором spaces, который пропускает любую (возможно, пустую) последовательность символов ' ', '\t' , '\r' или '\n'.

let ws = spaces

Затем нам нужно добавить синтаксический анализатор ws во все места, где мы хотим игнорировать пробелы. В общем случае удобно пропустить пробелы после вхождения отдельного элемента, т.е. Пропускать конечные, а не ведущие пробелы, потому что это уменьшает необходимость в обратной трассировке (подробнее см. ниже). В результате мы добавляем ws в два места, чтобы пропустить любые пробелы после скобок или цифр:

let str_ws s = pstring s .>> ws
let float_ws = pfloat .>> ws
let numberList = str_ws "[" >>. sepBy float_ws (str_ws ",") .>> str_ws "]"

Простой тест показывает, что numberList игнорирует пробелы:

> test numberList @"[ 1 ,
                          2 ] ";;
Success: [1.0; 2.0]

Если мы привнесем ошибку во второй строке, то увидим, что FParsec автоматически отслеживает текущее положение столбца и строки синтаксического анализа текста:

> test numberList @"[ 1,
                         2; 3]";;

Failure: Error in Ln: 2 Col: 27
                         2; 3]
                          ^
Expecting: ',' or ']'

Наш синтаксический анализатор numberList прежнему не пропускает ведущие пробелы, потому что это необязательно, когда мы сопоставляем его с другими синтаксическими анализаторами, которые пропускают все конечные пробелы. Если бы мы хотели разобрать весь поток ввода только с числами с плавающей запятой, мы могли бы использовать следующий синтаксический анализатор:

let numberListFile = ws >>. numberList .>> eof

Синтаксический анализатор конца файла eof будет генерировать ошибку, если конец потока не был достигнут. Это полезно для обеспечения того, чтобы весь входной поток был потреблен. Без анализатора eof следующий тест будет работать без ошибки:

> test numberListFile " [1, 2, 3] [4]";;
Failure: Error in Ln: 1 Col: 12
 [1, 2, 3] [4]
           ^
Expecting: end of input