【发布时间】:2021-05-24 09:16:03
【问题描述】:
我正在尝试按照以下特定算法在 Haskell 中实现优先级攀升:
compute_expr(min_prec):
result = compute_atom()
while cur token is a binary operator with precedence >= min_prec:
prec, assoc = precedence and associativity of current token
if assoc is left:
next_min_prec = prec + 1
else:
next_min_prec = prec
rhs = compute_expr(next_min_prec)
result = compute operator(result, rhs)
return result
在此伪代码中,compute_atom 负责传递值并处理自然优先级被括号覆盖的情况。
我的 Haskell 代码如下:
precedenceClimbing :: Tokens -> [Either MyException Tokens] -> Precedence -> (Expr, [Either MyException Tokens])
precedenceClimbing tok listOfTokens prec =
let result = returnPrecExpr tok listOfTokens
nextTBinOp = getToken (snd result)
in if checkBinopTok nextTBinOp -- checkRParTok nextTBinOp
then let listOfTokensBinOp = shrinkTokenList (snd result)
binOp = convertTokenToBinOp nextTBinOp
binOpParsed = parseBinop nextTBinOp listOfTokensBinOp
prec_cur = handleBinopsPrecedence binOp
in if prec_cur >= prec
then let newPrec = prec_cur + 1
nextTokAtom = getToken (snd binOpParsed)
listOfTokensAtom = shrinkTokenList (snd binOpParsed)
newCalc = precedenceClimbing nextTokAtom listOfTokensAtom newPrec
newBinExpr = ExprBinOp (fst binOpParsed) (fst result) (fst newCalc)
in (newBinExpr, snd newCalc)
else result --This is the most unsure section
else result
returnPrecExpr :: Tokens -> [Either MyException Tokens] -> (Expr, [Either MyException Tokens])
returnPrecExpr tok listOfTokens =
if checkLParTok tok
then let nextTokValue = getToken listOfTokens
listOfTokensNValue = shrinkTokenList listOfTokens
result = precedenceClimbing nextTokValue listOfTokensNValue 1
nextRPar = getToken (snd result)
listOfTokensRPar = shrinkTokenList (snd result)
in if checkRParTok nextRPar
then (fst result, listOfTokensRPar)
else undefined --error handling
else let token = convertTokenToValue tok
result = returnTokValueData token
in (result, listOfTokens)
returnPrecExpr 在这种情况下代表compute_atom,我相信它的目的是好的。但是,主要功能不是,因为我的主要问题是我无法满足算法中 while 给出的所有标准。从技术上讲,这意味着我应该能够通过适当的优先级(在这种情况下,自定义数据类型Preference 只是一个Int)并以现在正确的方式调用precedenceClimbing,我当算法应该退出当前运算符时,我无法继续,因为它的优先级不等于或大于前一个运算符。这是我的代码停止的地方。
有什么改进的建议吗?
编辑
因此,通过一个具体的例子,让我们有一个表达式,即 2 * 3 + 5。这里,因为 2 * 3 的优先级高于 3 + 5,所以算法应该返回,返回 2 * 3 作为结果 (但在我的上下文中,不是 6 的结果,而是这种形式的 2 * 3),但在这个阶段,我的算法停止并返回 2 * 3,因为我没有正确实现算法中的 while/recursion。这是我希望得到任何帮助的具体部分。
【问题讨论】:
-
如果你的代码没有缩进到函数参数的右边,会更容易阅读。
-
抱歉,已更正,感谢反馈!
-
我对代码风格给出了一些建议,但我真的无法给出改进实际算法实现的建议。您能否详细说明问题所在。我特别不明白这部分:“当算法应该退出当前操作符时,我无法继续”。
-
是的,我要编辑我的帖子。
标签: haskell compiler-construction abstract-syntax-tree operator-precedence recursive-descent