我在Parsec写一个解析器。左递归产品,如E - > E + E不能在LL解析器中轻松编写,因此Parsec提供buildExpressionParser
,它支持中缀,后缀和前缀运算符。但是下标运算符呢?
E-> E [E]是否已实施?
如果我可以使用结束括号而不使用第二个表达式,那么我可以使用buildExpressionParser
的Infix表条目来模拟它。想法?
编辑:我知道有一种左递归消除算法很可能适用于我的语法。我正在寻找一些简单或抽象的东西(例如buildExpressionParser
)。否则我只会用Happy。
答案 0 :(得分:1)
在我们的项目中,我们手动消除了表达式中的左递归。这可以通过以下方式实现:
我们创建了一个通用的表达式,由术语解析器参数化:
expressionGen :: MParser (Expr LocInfo) -> MParser (Expr LocInfo)
expressionGen term = buildExpressionParser precedenceTable term <?> "expression"
where precedenceTable = -- unary, binary expressions
我们有一个普通的术语解析器,以及一个没有递归规则的术语解析器。有了它,我们可以解析(多个)下标运算符:
term :: MParser (Expr LocInfo)
term = do indBase <- termNoArray
indexes <- many $ (brackets expression >>= return)
return -- semantics
<?> "term"
termNoArray :: MParser (Expr LocInfo)
termNoArray = -- normal terms
最后,我们有一个最顶层的表达式解析器:expression = expressionGen term
答案 1 :(得分:0)
技巧是将后缀下标运算符视为一个整体,包括索引表达式。
以megaparsec/parsec-combinators
项:
pExpr = makeExprParser pTerm operatorTable
...
parseSubscr :: Operator Parser Expr
parseSubscr =
Postfix $ do
symbol space "["
index <- pExpr
symbol space "]"
pure $ \parent ->
Subscript parent index