Haskell递归问题,微小的解析器。一些东西

时间:2009-10-05 18:38:11

标签: haskell parsing

data Expr =  Var Char | Tall Int | Sum Expr Expr | Mult Expr Expr | Neg Expr | Let Expr Expr Expr
    deriving(Eq, Show) 

这是Expr的数据类型,我有几个问题。我想要解析像*(Expr,Expr)这样的表达式,如数据类型定义中所示。但是我在“创建”有效Expr时遇到了一些问题。我使用模式匹配来识别Expr可以做的不同事情。还有一些代码:

parseExpr :: String -> (Expr, String)
parseExpr ('*':'(':x:',':y:')':s)   = (Mult (parseExpr [x] parseExpr [y]),s) 

显然这不起作用。 parseExpr的返回类型是将要解析的表达式的其余部分作为Expr返回到已解析代码的一部分。这段代码的右侧是问题所在。我无法建立有效的Expr。该函数假设以递归方式调用它,直到问题解决。

另一个问题是我不知道如何对VarTall进行模式匹配。如何检查Var是A-Z之间的大写字符,而Tall是0-9并将其作为有效Expr返回?

通常我可以查看字符串的一些部分来理解我正在处理的Expr的哪个部分。

Input like: parseProg "let X be 9 in *(X , 2)" Would spit out: Let (Var 'X') (Tall 9) (Mult (Var 'X') (Tall 2)) 

1 个答案:

答案 0 :(得分:2)

您的parseExpr函数返回一对,因此您无法直接使用其结果来构造Expr。我写这个的方式就像

parseExpr ('*':'(':s) = (Mult x y, s'')
    where (x,',':s') = parseExpr s
          (y,')':s'') = parseExpr s'

基本思想是,由于parseExpr返回剩余字符串作为该对的第二个参数,您需要在每个递归调用中保存该字符串,并且当您处理完所有子表达式时,你需要归还剩下的东西。显然,这里的错误处理很糟糕,所以如果想要成为一个强大的解析器,你可能想要考虑更多。

处理VarTall我只需按原样提取第一个字符并使用if来构建相应类型的Expr

如果你想在Haskell中编写更复杂的解析器,你需要查看Parsec库,它允许你编写一个解析器,就像你正在解析的语言的语法一样。