2

我目前正在使用 megaparsec 库在 Haskell 中编写我的简单编程语言解析器。

我找到了这个megaparsec 教程,并编写了以下解析器代码:

import Data.Void

import Text.Megaparsec
import Text.Megaparsec.Char

import qualified Text.Megaparsec.Char.Lexer as L

type Parser = Parsec Void String

lexeme :: Parser a -> Parser a
lexeme = L.lexeme space

rws :: [String] -- list of reserved words
rws = ["if", "then"]

identifier :: Parser String
identifier = (lexeme . try) (p >>= check)
  where
    p = (:) <$> letterChar <*> many alphaNumChar
    check x =
        if x `elem` rws
            then fail $ "keyword " ++ show x ++ " cannot be an identifier"
            else return x

具有保留名称错误处理的简单标识符解析器。它成功解析有效标识符,例如foo, bar123

但是当无效输入(又名保留名称)进入解析器时,它会输出错误:

>> parseTest identifier "if"
1:3:
keyword "if" cannot be an identifier

其中,错误消息还可以,但是错误位置(1:3:)与我的预期有点不同。我预计错误位置是1:1:.

在定义的以下部分中identifier

identifier = (lexeme . try) (p >>= check)

如果失败并返回源位置,我预计try会表现得像没有消耗输入。(p >>= check)1:1:

我的期望错了吗?我怎样才能让这段代码按我的预期工作?

4

0 回答 0