如何用Parsec在Haskell中解析Python式链式运算符?
使用Parsec解析链式表达式的可行性问题
我当前项目用Parsec构建表达式解析器,核心的运算符表代码如下:
opTable :: [[Operator Parser Expr]] opTable = [ -- ... [ InfixL $ binary (ArithOp . Exp) TokExp ] , [ InfixL $ binary (ArithOp . Mod) TokMod , InfixL $ binary (ArithOp . Mul) TokMul , InfixL $ binary (ArithOp . Div) TokDiv ] , [ InfixL $ binary (ArithOp . Add) TokAdd , InfixL $ binary (ArithOp . Sub) TokSub ] , [ InfixL $ binary (ArithOp . Max) TokMax , InfixL $ binary (ArithOp . Min) TokMin ] -- = , [ InfixL $ binary (ChainOp . EQ) TokEQ -- ~, <, <=, >, >= , InfixL $ binary (ChainOp . NEQ) TokNEQ , InfixL $ binary (ChainOp . NEQU) TokNEQU , InfixL $ binary (ChainOp . LT) TokLT , InfixL $ binary (ChainOp . LTE) TokLTE , InfixL $ binary (ChainOp . LTEU) TokLTEU , InfixL $ binary (ChainOp . GT) TokGT , InfixL $ binary (ChainOp . GTE) TokGTE , InfixL $ binary (ChainOp . GTEU) TokGTEU ] -- && , [ InfixL $ binary (ArithOp . Conj) TokConj , InfixL $ binary (ArithOp . ConjU) TokConjU -- || , InfixL $ binary (ArithOp . Disj) TokDisj , InfixL $ binary (ArithOp . DisjU) TokDisjU ] -- => , [ InfixR $ binary (ArithOp . Implies) TokImpl , InfixR $ binary (ArithOp . ImpliesU) TokImplU -- <=> , InfixL $ binary (ChainOp . EQProp) TokEQProp , InfixL $ binary (ChainOp . EQPropU) TokEQPropU ] ]
说明:
- 存在
ArithOp和ChainOp两类运算符:ArithOp是常规运算符ChainOp是Python式链式运算符(支持a <= b < c这类写法),包含TokLT(<)、TokEQProp(<=>)等类型
- 问题在于
ArithOp与ChainOp的优先级是相互交错的
我希望将表达式解析为如下结构的语法树:
data Expr = Lit Lit | Var Name | Op Op | App Expr Expr | Chain Chain -- ... -- ... data Chain = Pure Expr | Ch Chain Op Expr
例如表达式1 <= 1 + 1 < 3应解析为:
Ch ( Ch ( Lit 1 ) ( Op "<=") ( App ( App (Op "+" ) (Lit 1) ) (Lit 1) ) ) (Op "<") (Lit 3)
(已省略部分构造器)
我想知道:能否基于现有的Parsec表达式解析器(即上述运算符表的方式)构建出这种带链式结构的语法树?我知道可以手动编写分层解析器,但用现有框架会更简便。之前尝试过chainl组合子,但似乎无法生成目标Chain结构。如果不可行,我就手动实现。
内容的提问来源于stack exchange,提问作者盛安安
相关产品推荐
相关产品推荐

