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

Parsec:一行上有多个可能的选项

  •  2
  • ddccffvv  · 技术社区  · 11 年前

    全部的

    我正在尝试使用parsec编写一个解析器。目标是最终能够解析一种玩具语言。

    现在,我正在努力让parsec识别两种不同的可能选项,例如赋值和函数调用。

    如何编写一个“parseCode”函数来解析以下内容:

    x = 3
    y = 4
    plus(x,y)
    

    进入:

    (Assignment "x" "3")
    (Assignment "y" "4")
    (Invocation "plus" ["x","y"])
    

    谢谢

    编辑:

    **为简洁起见省略**

    编辑2:

    我根据你的建议做了一点准备,现在有以下问题 跑步 parse parseTester "bla" "{plus(3,4)\nmin(2,3)\nx=3\n" 给出了预期的解决方案: Right (Body [Invocation "plus",Invocation "min",Assignment "x" "3"]) .

    但运行功能上(几乎)等效的 parse parseBody "bla" "{plus(3,4)\nmin(2,3)\nx=3\n}" 导致错误:

    Left "bla" (line 4, column 2):
    unexpected end of input
    expecting white space or "="
    

    我看不出有什么问题。解析器是否突然在应该寻找调用的地方寻找赋值?有什么建议吗?

    代码:

    data Body = Body [Statement]
        deriving (Show)
    
    data Arguments = Arguments [String]
        deriving (Show)
    
    data Statement = Assignment String String
                   | Invocation String
        deriving (Show)
    
    
    parseBody :: Parser Body
    parseBody = do
        char '{'
        statements <- many1 parseStatement
        char '}'
        return $ Body statements
    
    parseTester :: Parser Body
    parseTester = do 
        char '{'
        x <- many1 parseStatement
        return $ Body x
    
    parseStatement :: Parser Statement
    parseStatement = do
            x <- try parseInvocation <|> parseAssignment <?> "statement"
            return x
    
    parseInvocation :: Parser Statement
    parseInvocation = do
        spaces
        name <- many1 (noneOf " (")
        spaces
        char '('
        spaces
        bla <- many1 (noneOf " )")
        spaces
        char ')'
        char '\n'
        return $ Invocation name
    
    parseAssignment :: Parser Statement
    parseAssignment = do
        spaces
        var <- many1 (noneOf " =")
        spaces
        char '=' <?> "equal in assignment"
        spaces
        value <- many1 (noneOf "\n")
        char '\n'
        spaces
        return $ Assignment var value
    
    1 回复  |  直到 11 年前
        1
  •  2
  •   wit    11 年前

    如果我们需要解析一些选择,您可以使用 choice 从…起 Text.ParserCombinators.Parsec.Combinator

    choice [parseInvocation, parseAssignmen]
    

    或者更简单: try parseInvocation <|> try parseAssignmen

    附笔。

    你可以使用表单 Text.ParserCombinators.Parsec.Char :

    many (oneOf " ") == spaces
    
    oneOf " " == space