在Haskell中实现优先爬升
我试图在Haskell中实现优先级提升,遵循以下特定算法:在Haskell中实现优先爬升,haskell,compiler-construction,abstract-syntax-tree,operator-precedence,recursive-descent,Haskell,Compiler Construction,Abstract Syntax Tree,Operator Precedence,Recursive Descent,我试图在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_mi
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\u 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)
returnprecxpr
在这种情况下代表了compute\u atom
,我相信它可以达到它的目的。然而,主要功能不是,因为我的主要问题是我不能满足算法中while给出的所有标准。从技术上讲,这意味着我应该能够通过适当的优先级(在这种情况下,自定义数据类型首选项
只是一个Int
)并像现在一样以正确的方式调用优先项
,当算法应该退出当前运算符时,我无法继续,因为它的优先级不等于或大于前一个运算符。这就是我的代码停止的地方。有什么改进的建议吗?
编辑
通过一个具体的例子,让我们有一个表达式,它是2*3+5。这里,因为2*3的优先级高于3+5,所以算法应该返回,返回2*3作为结果(但在我的上下文中,不是6的结果,而是以这种形式,2*3),但在这个阶段,我的算法停止并返回2*3,因为我没有正确地实现算法中的while/递归。这是我希望得到任何帮助的特定部分。我建议您在开始解析之前处理错误消息。我假设
getToken
只从列表中获取第一个令牌,而shrinkTokenList
只从列表中删除第一个令牌。然后,您可以使用更短的名称和模式匹配使函数更为惯用,如下所示:
preferencegranning::[Token]->preference->(Expr,[Token])
先例
|checkBinopTok tok1&&curPrec>=prec
=let(op,toks2)=parseBinop tok1 toks1
(r,toks3)=超前爬升toks2(curPrec+1)
in(ExprBinOp op l r,toks3)
|否则=结果
哪里
结果@(l,tok1:toks1)=返回EXPR toks
curPrec=车把前座(ConvertTokentobino tok1)
returnPrecExpr::[Token]->(Expr[Token])
RETURNPROCEXPR(tok:toks)
|checkLParTok tok=如果checkRParTok tok'then(e,toks')else未定义——错误处理
|否则=(returnTokValueData(ConvertTokenToValueTok),toks)
其中(e,tok':toks')=toks 1
您甚至可以使用
State[Token]
monad使其更加完善,如果您想生成错误消息,那么您可以轻松地将其更改为StateT[Token](MyException之一)
我建议您在开始解析之前处理错误消息。我假设getToken
只从列表中获取第一个令牌,而shrinkTokenList
只从列表中删除第一个令牌。然后,您可以使用更短的名称和模式匹配使函数更为惯用,如下所示:
preferencegranning::[Token]->preference->(Expr,[Token])
先例
|checkBinopTok tok1&&curPrec>=prec
=let(op,toks2)=parseBinop tok1 toks1
(r,toks3)=超前爬升toks2(curPrec+1)
in(ExprBinOp op l r,toks3)
|否则=结果
哪里
结果@(l,tok1:toks1)=返回EXPR toks
curPrec=车把前座(ConvertTokentobino tok1)
returnPrecExpr::[Token]->(Expr[Token])
RETURNPROCEXPR(tok:toks)
|checkLParTok tok=如果checkRParTok tok'then(e,toks')else未定义——错误处理
|否则=(returnTokValueData(ConvertTokenToValueTok),toks)
其中(e,tok':toks')=toks 1
您甚至可以使用
State[Token]
monad使这一点变得更好,如果您想生成错误消息,那么您可以轻松地将其更改为StateT[Token](MyException之一)
如果代码没有缩进到函数参数的右侧,那么您的代码将更易于阅读。对不起,更正了,谢谢你的反馈!我已经对代码风格提出了一些建议,但我真的无法给出改进实际算法实现的建议。你能详细说明一下问题是什么吗。我特别不理解这部分:“当算法应该从当前运算符退出时,我无法继续”。是的,我将编辑我的帖子。如果代码没有缩进到函数参数的右侧,您的代码将更容易阅读。抱歉,更正了,感谢您的反馈!我已经对代码风格提出了一些建议,但我真的无法给出改进实际算法实现的建议。你能详细说明一下问题是什么吗。我特别不理解这一部分:“当算法应该从当前操作符中退出时,我无法继续”。是的,我将编辑我的帖子。谢谢!我对Haskell编程相当业余,从命令式的角度来看,我离实现更好的函数心态还有很长的路要走。谢谢!我对Haskell编程相当业余,从命令式的角度来看,我离实现更好的函数心态还有很长的路要走。