Что Эдвард в комментариях и я оба пытаемся сделать, так это мысленно запустить ваш синтаксический анализатор, и это немного сложно без продолжения парсера. Я собираюсь сделать некоторые предположения здесь, и, возможно, они помогут вам уточнить ваш вопрос.
Угадай 1) : Вы попытались GHCI> parse expr "(input)" "(a,b) -> \"b\"
, и он вернул Left …
. Было бы полезно узнать, в чем была ошибка.
Угадай 2) : Вы также попытались GHCI> parse lambda "(input)" "(a,b) -> \"b\"
, и он вернул Right …
. основываясь на этом Эдварде, я и сделал вывод, что где-то в вашем синтаксическом анализаторе term
или, возможно, в сгенерированном синтаксическом анализаторе expr
существует конфликт. То, что какой-то фрагмент синтаксического анализатора преуспел в сопоставлении начала строки и возврате значение, но то, что остается, больше не действует. Было бы полезно, если бы вы попробовали GHCI> parse term "(input)" "(a,b) -> \"b\"
, поскольку это позволило бы нам узнать, была ли проблема в term
или expr
.
Guess 3) : Строка "(a,b)"
сама по себе является допустимым выражением в грамматике, как вы ее запрограммировали. (Хотя, возможно, не так, как вы намеревались запрограммировать ;-). Попробуйте отправить это через анализатор expr и посмотрите, что произойдет.
Угадай 4) : Ваша грамматика оставлена рекурсивной. Это то, что заставляет его застрять и зациклить навсегда. Parsec - это LL (k) парсер. Если вы привыкли к Yacc и семейству, которые являются парсерами LR (1) или LR (k), правила рекурсии в точности обратные. Если вы не поняли это последнее предложение, это нормально, но дайте нам знать.
Угадай 5) : код в построителе выражений выглядит так, как будто он взят из документации функции. Я думаю, что вы, возможно, также нашли выражение term
. Если это так, вы указываете, откуда это произошло. если нет, то не могли бы вы объяснить в нескольких предложениях, как, по вашему мнению, term
должно работать.
Общие советы : Большое количество try
утверждений в конечном итоге (сейчас) может вызвать у вас горе. Они полезны в некоторых случаях, но и немного непослушны. Если следующий персонаж может определить, какой выбор должен быть успешным, он не нужен. Если вы просто пытаетесь получить что-то запущенное, большое количество возвратов сократит количество промежуточных форм, но также скрывает патологические случаи и делает ошибки более неясными.