gpt4 book ai didi

parsing - Haskell Parsec - 使用自定义 token 时错误消息的帮助不大

转载 作者:行者123 更新时间:2023-12-04 15:13:58 25 4
gpt4 key购买 nike

我正在分离解析器的词法分析和解析阶段。经过一些测试,我意识到当我使用 Parsec 的 Char token 以外的其他 token 时,错误消息的帮助不大。

以下是 Parsec 在使用 Char token 时的一些错误消息示例:

ghci> P.parseTest (string "asdf" >> spaces >> string "ok") "asdf  wrong"
parse error at (line 1, column 7):
unexpected "w"
expecting space or "ok"


ghci> P.parseTest (choice [string "ok", string "nop"]) "wrong"
parse error at (line 1, column 1):
unexpected "w"
expecting "ok" or "nop"

因此,字符串解析器会在发现意外字符串时显示预期的字符串,而选择解析器会显示备选字符串。

但是当我对我的标记使用相同的组合器时:
ghci> Parser.parseTest ((tok $ Ide "asdf") >> (tok $ Ide "ok")) "asdf  "
parse error at "test" (line 1, column 1):
unexpected end of input

在这种情况下,它不会打印预期的内容。
ghci> Parser.parseTest (choice [tok $ Ide "ok", tok $ Ide "nop"]) "asdf  "
parse error at (line 1, column 1):
unexpected (Ide "asdf","test" (line 1, column 1))

当我使用 choice ,它不打印替代品。

我希望这种行为与组合函数有关,而不是与 token 有关,但似乎我错了。我怎样才能解决这个问题?

这是完整的词法分析器+解析器代码:

词法分析器:
module Lexer
( Token(..)
, TokenPos(..)
, tokenize
) where

import Text.ParserCombinators.Parsec hiding (token, tokens)
import Control.Applicative ((<*), (*>), (<$>), (<*>))

data Token = Ide String
| Number String
| Bool String
| LBrack
| RBrack
| LBrace
| RBrace
| Keyword String
deriving (Show, Eq)

type TokenPos = (Token, SourcePos)

ide :: Parser TokenPos
ide = do
pos <- getPosition
fc <- oneOf firstChar
r <- optionMaybe (many $ oneOf rest)
spaces
return $ flip (,) pos $ case r of
Nothing -> Ide [fc]
Just s -> Ide $ [fc] ++ s
where firstChar = ['A'..'Z'] ++ ['a'..'z'] ++ "_"
rest = firstChar ++ ['0'..'9']

parsePos p = (,) <$> p <*> getPosition

lbrack = parsePos $ char '[' >> return LBrack
rbrack = parsePos $ char ']' >> return RBrack
lbrace = parsePos $ char '{' >> return LBrace
rbrace = parsePos $ char '}' >> return RBrace


token = choice
[ ide
, lbrack
, rbrack
, lbrace
, rbrace
]

tokens = spaces *> many (token <* spaces)

tokenize :: SourceName -> String -> Either ParseError [TokenPos]
tokenize = runParser tokens ()

解析器:
module Parser where

import Text.Parsec as P
import Control.Monad.Identity
import Lexer

parseTest :: Show a => Parsec [TokenPos] () a -> String -> IO ()
parseTest p s =
case tokenize "test" s of
Left e -> putStrLn $ show e
Right ts' -> P.parseTest p ts'

tok :: Token -> ParsecT [TokenPos] () Identity Token
tok t = token show snd test
where test (t', _) = case t == t' of
False -> Nothing
True -> Just t

解决方案:

好的,在 fp4me 的回答和更仔细地阅读 Parsec 的 Char 源之后,我得到了这个:
{-# LANGUAGE FlexibleContexts #-}
module Parser where

import Text.Parsec as P
import Control.Monad.Identity
import Lexer

parseTest :: Show a => Parsec [TokenPos] () a -> String -> IO ()
parseTest p s =
case tokenize "test" s of
Left e -> putStrLn $ show e
Right ts' -> P.parseTest p ts'


type Parser a = Parsec [TokenPos] () a

advance :: SourcePos -> t -> [TokenPos] -> SourcePos
advance _ _ ((_, pos) : _) = pos
advance pos _ [] = pos

satisfy :: (TokenPos -> Bool) -> Parser Token
satisfy f = tokenPrim show
advance
(\c -> if f c then Just (fst c) else Nothing)

tok :: Token -> ParsecT [TokenPos] () Identity Token
tok t = (Parser.satisfy $ (== t) . fst) <?> show t

现在我收到相同的错误消息:

ghci> Parser.parseTest (choice [tok $ Ide "ok", tok $ Ide "nop"]) " asdf"
parse error at (line 1, column 1):
unexpected (Ide "asdf","test" (line 1, column 3))
expecting Ide "ok" or Ide "nop"

最佳答案

解决方案的开始可以是在 Parser 中定义您的选择函数,
使用特定的意外函数来覆盖意外错误,最后
使用 <?>运算符覆盖预期的消息:

mychoice [] = mzero
mychoice (x:[]) = (tok x <|> myUnexpected) <?> show x
mychoice (x:xs) = ((tok x <|> mychoice xs) <|> myUnexpected) <?> show (x:xs)

myUnexpected = do
input <- getInput
unexpected $ (id $ first input )
where
first [] = "eof"
first (x:xs) = show $ fst x

并像这样调用您的解析器:
ghci> Parser.parseTest (mychoice [Ide "ok", Ide "nop"]) "asdf  "
parse error at (line 1, column 1):
unexpected Ide "asdf"
expecting [Ide "ok",Ide "nop"]

关于parsing - Haskell Parsec - 使用自定义 token 时错误消息的帮助不大,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12167329/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com