2010-11-16 2 views
3

При попытке разобрать many p, я не получить «р», ожидающее сообщения:Парсеки - «много» и сообщений об ошибках

> parse (many (char '.') >> eof) "" "a" 
Left (line 1, column 1): 
unexpected 'a' 
expecting end of input 

Сравнить с

> parse (sepBy (char '.') (char ',') >> eof) "" "a" 
Left (line 1, column 1): 
unexpected 'a' 
expecting "." or end of input 

который сообщает». " как я ожидал. many1 p <|> return [] работает также.

Все эти функции принимают пустой ввод, так почему же many сообщить, что он ожидает? Это ошибка или функция?

ответ

3

В нескольких поверхностном смысле, причина различия в поведении, что many является primitive parser тогда sepBy строится in a similar manner на ваш переписана many. В последнем случае сообщение «ожидающее ...» построено на основе альтернатив, которые были доступны по пути, который привел к сбою синтаксического анализа; с many таких выборов не было, это просто безуспешно.

Я не знаю, что я бы описал это как ошибку или, это всего лишь причуда того, как работает Parsec. Обработка ошибок не является сильной стороной Parsec, и это действительно не похоже на первое, о чем я бы беспокоился в этом отношении. Если это вас беспокоит, вам может быть лучше, если вы изучите другие библиотеки разбора. Например, я хорошо слышал о uu-parsinglib.

+1

Не должно быть скрытой детализацией реализации? 'many' также можно определить с помощью' <|> ', и из того, что я вижу, он не был определен таким образом по соображениям производительности. – hmp

+0

@hmp: Наверное, должно быть, да. Хотя я ожидаю, что вам будет лучше подавать собственное сообщение с '()' в любом случае. –

1

От haddock

многих р применяет синтаксический анализатор P Zero или несколько раз. Возвращает список возвращаемых значений .

Таким образом, пустая строка является допустимым значением для комбинации many.

[Добавлено]

Ах, теперь я вижу свою точку зрения. expecting a or b сообщается, когда используется <|> (комбинатор выбора). many реализован без использования <|>, но sepBy использует его внутри.

+0

Это не точка. Пустая строка также является допустимым вводом для sepBy, но sepBy сообщает об ошибках из своего аргумента. – hmp

+0

см. Обновленный ответ – Yuras

+0

Да, это кажется правильным. Мне было интересно, не злоупотребляю ли я библиотекой, если вы хотите этого поведения, или если это ошибка в Parsec. – hmp

7

Вы получите лучшие сообщения об ошибках с manyTill:

> parse (manyTill (char '.') eof) "" "a" 
Left (line 1, column 1): 
unexpected 'a' 
expecting end of input or "." 

Это просто из-за того, как вы цепь с >>. Если первый синтаксический анализатор завершится успешно, то второй будет запущен. many преуспевает, поэтому проверяется eof. eof не работает, поэтому вы получаете сообщение об ошибке eof.

С помощью manyTill он пытается как синтаксические анализаторы (во-первых, так и первые), и если оба они не работают, сообщения об ошибках объединяются (это связано с тем, что он использует внутри себя <|>).

В целом, хотя, это легче определить свои собственные ошибки с <?>:

> parse (many (char '.') >> eof <?> "lots of dots") "" "a" 
Left (line 1, column 1): 
unexpected 'a' 
expecting lots of dots 
+0

Это не связано с тем, как я цепочки парсеров, потому что другие синтаксические анализаторы (которые используют '<|>') также преуспевают на пустом вводе и собирают ошибки. (Проблема заключалась в 'between (sym" {") (sym"} ") $ many stmt', и я хотел увидеть« ожидающий »} или оператор« при ошибках ».) – hmp

+0

В этом суть, сообщения об ошибках только для текущего синтаксического анализатора - единственная причина, по которой вы получаете сообщения «x» или «y», состоит в том, что комбинатор '<|>' специально собирает сообщения от обоих пар-парсеров. 'между 'просто цепочки с' >> ', как ваш пример. Поэтому, если вы пишете версию между тем, что использует ошибки '<|>', вы можете получить "} или инструкцию". :) – porges

+0

Например, см. Реализацию '<|>' для того, как он объединяет сообщения об ошибках: http://hackage.haskell.org/packages/archive/parsec/3.0.0/doc/html/src/Text-Parsec-Prim .html # parserPlus – porges

0

Это ошибка введена в пс-3.1. Если тест с предыдущими версиями, вы должны получить сообщение об ошибке, как это:

> parse (many (char '.') >> eof) "" "a" 
Left (line 1, column 1): 
unexpected 'a' 
expecting "." or end of input 

По крайней мере, это то, что я получаю после исправления ошибки :-)

+0

Вот что я получаю с 'sepBy'. Проблема заключалась в 'many'. – hmp

+0

Я получаю то же сообщение об ошибке для обоих парсеров в моей взломанной копии parsec 3.1 и в parsec-3.0 - поведение, о котором вы упоминаете, только в parsec-3.1. Я редактировал свой комментарий. –

Смежные вопросы