Haskell递归问题,小解析器。否定Expr并让表达式 [英] Haskell recursive problem, tiny parser. Negation of Expr and let expressions
问题描述
data Expr = Var Char |高层Int | Sum Expr Expr | Mult Expr Expr | Neg Expr |让Expr Expr Expr
派生(Eq,Show)
parseExpr :: String - > (Expr,String)
parseExpr('*':'(':s)=(Mult xy,s'')
其中(x,',':s')= parseExpr s
(y,')':s'')= parseExpr s'
parseExpr('+':'(':s)=(Sum xy,s'')
其中(x,',':s')= parseExpr s
(y,')':s'')= parseExpr s'
parseExpr(x:xs)| isDigit x =(Tall(digitToInt x),xs)
parseExpr(x:s)=(Var x,s)
其中x> ='A'= True
x< = 'Z'= True
解析器在完成之前缺少两件事。从其缺乏Neg Expr和LetExpr Expr Expr之上的数据类型。第一部分是这样的:
parseExpr(' - '
parseExpr('l':'e ':'t':x:'b':'e
在数据类型中,Let表达式以let开头,并带入三个Expr。
我不知道如何写出这些最后的函数。任何帮助都将非常感激。
<我没有问过关于这个问题的另一个问题,并且这里是该问题的链接。
以下是一个例子:
parseProg设X = 4令Y为*(2,X)令Z为+(Y,X)in
+(+( (Var'X')(Tall'4')(Let'Var'Y')(Mult(Tall 2)(Var'X'))(Let'b $ b' (Var'Z')(Sum(Var'Y')(Var'X'))(Sum(Sum(Var'X')(Var'Y'))(Var
'Z'))) )
其中(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中更改模式以明确包含这些模式,例如:
其中(x,'':'b':'e':'':s1)= parseExpr s
更灵活的是添加一个 dropSpaces :: String - > String
函数删除前导空格并在适当的位置被调用。
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
My parser is lacking two things before it is complete. As from the datatype above its lacking "Neg Expr" and Let "Expr Expr Expr". The first part would be something like this:
parseExpr('-'
parseExpr('l':'e':'t':x:'b':'e
As in the datatype, the Let expressions starts with let and takes in three Expr. I don't know how to write out these last functions. Any help at all will be very much appreciated.
I did ask another question here on SO about this, and here is the link for that question.
Here is an example:
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'))))
The basic strategy for these parts of the expression would be the same as for the other operations, just that you don't have to parse two subexpressions, but one or three. For let
it would look like this:
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
If a string starts with the letters l
, e
, t
take the remaining string (s
) and try to parse an expression from it. This results in an expression (x
) and a remaining string. We expect that this remaining string starts with the letters b
, e
. Since this should be followed by another expression we give the rest of this string (s2
) again to parseExpr to parse another expression. And so on.
The only problem with this is that we don't account for spaces that might separate these keywords like "let" and "be" from the surrounding expressions. The easy solution would be to require exactly one space before/after these keywords and change the patterns in parseExpr to explicitly include these, for example:
where (x, ' ':'b':'e':' ':s1) = parseExpr s
More flexible would be to add a dropSpaces :: String -> String
function that removes leading spaces and gets called in the appropriate places.
这篇关于Haskell递归问题,小解析器。否定Expr并让表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!