data Expr = Var Char | Tall Int | Sum Expr Expr | Mult Expr Expr | Neg Expr | Let Expr Expr Expr
deriving(Eq, Show)
parseExpr :: String -> (Expr, String)
parseExpr ('*':'(':s) = (Mult x y, s'')
where (x,',':s') = parseExpr s
(y,')':s'') = parseExpr s'
parseExpr ('+':'(':s) = (Sum x y, s'')
where (x,',':s') = parseExpr s
(y,')':s'') = parseExpr s'
parseExpr (x : xs) | isDigit x = (Tall (digitToInt x), xs)
parseExpr (x:s) = (Var x,s)
where x >= 'A' = True
x <= 'Z' = True
我的解析器在完成之前缺少两件事。从上面的数据类型缺少“Neg Expr”和“Expr Expr Expr”。第一部分是这样的:
parseExpr('-'
parseExpr('l':'e':'t':x:'b':'e
与数据类型一样,Let表达式以let开头并接受三个Expr。 我不知道如何写出这些最后的功能。任何帮助都将非常感谢。
我确实在这里提出了另外一个问题,here是该问题的链接。
以下是一个例子:
parseProg "let X be 4 in let Y be *(2 , X) in let Z be +(Y , X) in
+(+(X , Y) , Z)"
Let (Var 'X') (Tall 4) (Let (Var 'Y') (Mult (Tall 2) (Var 'X')) (Let
(Var 'Z') (Sum (Var 'Y') (Var 'X')) (Sum (Sum (Var 'X') (Var 'Y')) (Var
'Z'))))
答案 0 :(得分:1)
表达式的这些部分的基本策略与其他操作的基本策略相同,只是您不必解析两个子表达式,而是解析一个或三个子表达式。对于let
,它看起来像这样:
parseExpr ('l':'e':'t':s) = (Let x y z, s3)
where (x, 'b':'e':s1) = parseExpr s
(y, 'i':'n':s2) = parseExpr s1
(z, s3) = parseExpr s2
如果字符串以字母l
开头,e
,t
取剩余字符串(s
)并尝试从中解析表达式。这会产生表达式(x
)和剩余的字符串。我们希望剩下的字符串以字母b
,e
开头。由于这应该跟随另一个表达式,我们再次将此字符串的其余部分(s2
)提供给parseExpr以解析另一个表达式。等等。
唯一的问题是我们没有考虑可能将这些关键字分开的空格,例如“let”和“be”来自周围的表达式。简单的解决方案是在这些关键字之前/之后只需要一个空格,并在parseExpr中更改模式以明确包含这些空格,例如:
where (x, ' ':'b':'e':' ':s1) = parseExpr s
更灵活的是添加dropSpaces :: String -> String
函数,删除前导空格并在适当的位置调用。