首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >正确解析Haskell uu-parsinglib中的行缩

正确解析Haskell uu-parsinglib中的行缩
EN

Stack Overflow用户
提问于 2013-08-14 16:45:21
回答 1查看 247关注 0票数 6

我想要创建一个解析器组合器,它将收集当前位置以下的所有行,缩进级别将大于或等于某个i。我认为这个想法很简单:

使用一行-如果其缩进是:

  • 好的,->为下一行做它
  • 错误的->失败

让我们考虑以下代码:

代码语言:javascript
复制
import qualified Text.ParserCombinators.UU as UU
import           Text.ParserCombinators.UU hiding(parse)
import           Text.ParserCombinators.UU.BasicInstances hiding (Parser)

-- end of line
pEOL   = pSym '\n'

pSpace = pSym ' '
pTab   = pSym '\t'

indentOf s = case s of
    ' '  -> 1
    '\t' -> 4

-- return the indentation level (number of spaces on the beginning of the line)
pIndent = (+) <$> (indentOf <$> (pSpace <|> pTab)) <*> pIndent `opt` 0

-- returns tuple of (indentation level, result of parsing the second argument)
pIndentLine p = (,) <$> pIndent <*> p <* pEOL

-- SHOULD collect all lines below witch indentations greater or equal i
myParse p i = do
    (lind, expr) <- pIndentLine p
    if lind < i
        then pFail
        else do
            rest <- myParse p i `opt` []
            return $ expr:rest

-- sample inputs
s1 = " a\
   \\n a\
   \\n"

s2 = " a\
   \\na\
   \\n"

-- execution
pProgram = myParse (pSym 'a') 1 

parse p s = UU.parse ( (,) <$> p <*> pEnd) (createStr (LineColPos 0 0 0) s)

main :: IO ()
main = do 
    print $ parse pProgram s1
    print $ parse pProgram s2
    return ()

它提供了以下输出:

代码语言:javascript
复制
("aa",[])
Test.hs: no correcting alternative found

s1的结果是正确的。s2的结果应该首先消费"a“,然后停止消费。这个错误从何而来?

EN

回答 1

Stack Overflow用户

发布于 2013-08-15 08:13:40

您正在构建的解析器将始终尝试继续;如果有必要,输入将被丢弃或添加。然而,pFail是一个死胡同.它充当<|>的一个单元元素。

但是,在您的解析器中,如果输入不符合解析器认可的语言,则没有其他选择。在您的规范中,您说希望解析器在输入s2上失败。现在它失败了,有一条消息说这是失败的,你会感到惊讶。

也许你不希望它失败,但你想停止接受进一步的输入?在这种情况下,将pFail替换为return []

请注意,案文:

代码语言:javascript
复制
do
    rest <- myParse p i `opt` []
    return $ expr:rest

可以用(expr:) <$> (myParse p i `opt` [])代替

解决问题的一种自然方法可能是

代码语言:javascript
复制
pIndented p = do i <- pGetIndent
             (:) <$> p <* pEOL  <*> pMany (pToken (take i (repeat ' ')) *> p <* pEOL)

pIndent = length <$> pMany (pSym ' ')
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18237578

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档