Haskell递归问题,小解析器。一些东西 [英] Haskell recursive problem, tiny parser. A few things
问题描述
data Expr = Var Char |高层Int | Sum Expr Expr | Mult Expr Expr | Neg Expr |让Expr Expr Expr
导出(Eq,Show)
这是<$的数据类型c $ c> Expr ,我有几个问题。我假设分析像 *(Expr,Expr)
这样的表达式,如数据类型定义中所示。然而,我确实遇到了一些问题,创建一个有效的 Expr
。我使用模式匹配来识别Expr可以做的不同事情。还有一些代码:
parseExpr :: String - > (Expr,String)
parseExpr('*':'(':x:',':y:')':s)=(Mult(parseExpr [x] parseExpr [y]),s)
显然,这不起作用。 另一个问题是我不知道如何对 parseExpr
的返回类型是将要解析的表达式的其余部分作为 Expr $的一部分解析的代码返回。 C $ C>。此代码的右侧是问题。我无法生成一个有效的
。我如何检查 Expr
。该函数假设以递归方式自我调用,直到问题解决。
Var
和<$ c $进行模式匹配C>高大 Var
是AZ与 Tall
之间的大写字符是0-9,并将其作为有效 Expr
?
通常,我只需看一下字符串的几个部分即可了解 Expr
的哪一部分用。
输入如下:parseProglet X be 9 in *(X,2)会吐出:Let(Var'X ')(Tall 9)(Mult(Var'X')(Tall 2))
你的 parseExpr
函数返回一对,所以当然你不能直接使用它的结果来构造 Expr
。我写这个的方式就像
parseExpr('*':'(':s)=(Mult xy ,s'')
$ b $ p $基本思想是,因为
其中(x,',':s')= parseExpr s
(y,')':s'')= parseExpr s'
parseExpr
返回剩下的字符串作为第二个参数你需要在每一次递归调用中保存该字符串,当你处理了所有的子表达式时,你需要返回剩下的内容。显然,这里的错误处理很糟糕,所以如果这是一个强大的解析器,你可能会想更多地考虑这一点。
处理
Var
和Tall
我会按照原样提取第一个字符,并且如果 c>构造适当类型的Expr
。
如果你想在Haskell中编写更复杂的解析器,你会想看看Parsec库,它可以让你编写一个解析器,就像你解析语言的语法一样。
data Expr = Var Char | Tall Int | Sum Expr Expr | Mult Expr Expr | Neg Expr | Let Expr Expr Expr deriving(Eq, Show)
That is the datatype for
Expr
, I have a few questions. I'm suppose to parse expressions like*(Expr,Expr)
as shown in the datatype definition. However I do have some problems with "creating" a validExpr
. I use pattern matching for recognizing the different things Expr can be. Some more code:parseExpr :: String -> (Expr, String) parseExpr ('*':'(':x:',':y:')':s) = (Mult (parseExpr [x] parseExpr [y]),s)
This is not working, obviously. The return type of
parseExpr
is to return the rest of the expression that is to be parsed an a portion of the parsed code as anExpr
. The right side of this code is the problem. I can't make a validExpr
. The function is suppose to call it self recursively until the problem is solved.ANOTHER problem is that I don't know how to do the pattern matching against
Var
andTall
. How can I check thatVar
is an uppercase character between A-Z and thatTall
is 0-9 and return it as a validExpr
?Generally I can just look at a few parts of the string to understand what part of
Expr
I'm dealing with.Input like: parseProg "let X be 9 in *(X , 2)" Would spit out: Let (Var 'X') (Tall 9) (Mult (Var 'X') (Tall 2))
解决方案Your
parseExpr
function returns a pair, so of course you cannot use its result directly to construct anExpr
. The way I would write this would be something likeparseExpr ('*':'(':s) = (Mult x y, s'') where (x,',':s') = parseExpr s (y,')':s'') = parseExpr s'
The basic idea is that, since
parseExpr
returns the leftover string as the second argument of the pair, you need to save that string in each recursive call you make, and when you've handled all the subexpressions, you need to return whatever is left over. And obviously the error handling here sucks, so you may want to think about that a bit more if this is intended to be a robust parser.Handling
Var
andTall
I would do by just extracting the first character as is and have anif
to construct anExpr
of the appropriate type.And if you want to write more complex parsers in Haskell, you'll want to look at the Parsec library, which lets you write a parser as pretty much the grammar of the language you're parsing.
这篇关于Haskell递归问题,小解析器。一些东西的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!