代码之家  ›  专栏  ›  技术社区  ›  Felix

光年解析器的行为出乎意料

  •  1
  • Felix  · 技术社区  · 7 年前

    我正在尝试用光年为Idris构建格式化程序。

    https://github.com/hejfelix/IdrisFMT/blob/501a4a9e8b1b4154ed0d7836676c24d98de8b76a/IdrisFmt.idr

    目前,目的是标记文件本身,然后漂亮地打印它,即作为输入的文件应该是一个固定点。

    问题出现在每个字符串文字之后,我的解析器似乎会吃掉空白。如果我在字符串文字后立即放置除空格以外的任何内容,它将解析该字符以及以下所有空格。

    此示例程序将显示错误:

    main2 : IO ()
    main2 = putStrLn $ str
        where
          str = case parse tokenParser "\"IdrisFMT.idr\" \n" of
                     (Left l) => "failed" ++ show l
                     (Right r) => show $ map (show @{default}) r
    

    *IdrisFMT> :exec main2
    ["StringLiteral(\"IdrisFMT.idr\")"]
    

    如果我将要解析的字符串更改为 "\"IdrisFMT.idr\"c \n"

    *IdrisFMT> :exec main2
    ["StringLiteral(\"IdrisFMT.idr\")", "Identifier(c)", "' '", "'\\n'"]
    

    这正是我所期望的。

    我相信错误是由我解析字符串文字的方式引起的,但我无法理解我的错误,并且我很难找到调试光年解析器的好方法。 我的字符串文字解析器的实现如下:

    escape : Parser String
    escape = do
      d <- char '\\'
      c <- oneOf "\\\"0nrvtbf"
      pure $ pack $ (the $ List Char) [d,c]
    
    nonEscape : Parser String
    nonEscape = map (\x => pack $ (the $ List _) [x]) $ noneOf "\\\"\0\n\r\v\t\b\f"
    
    character : Parser String
    character = nonEscape <|>| escape
    
    stringLiteralToken : Parser Token
    stringLiteralToken = map (StringLiteral . concat) $ dquote (many character)
    

    如何防止字符串文字解析器吃掉文字后面的空白?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Felix    7 年前

    在#idris频道上聊天后,我了解到大多数内置的高阶解析器(例如。 dquote )跳过末尾的空白。 就我而言,这不是我想要的。相反,我使用了 between 函数包含3个参数,一个用于何时启动,另一个用于何时停止,第三个用于中间的任何参数。

    为了解析字符串文字,我现在要做以下操作:

    escape : Parser String
    escape = do
      d <- char '\\'
      c <- oneOf "\\\"0nrvtbf'"
      pure $ pack $ (the $ List Char) [d,c]
    
    nonEscape : Parser String
    nonEscape = map (\x => pack $ (the $ List _) [x]) $ noneOf "\\\"\0\n\r\v\t\b\f"
    
    character : Parser String
    character = nonEscape <|>| escape
    
    stringLiteralToken : Parser Token
    stringLiteralToken = map (StringLiteral . concat) $ (between (char '"') (char '"')) (many character)
    

    推荐文章