【发布时间】:2017-11-24 14:40:15
【问题描述】:
我正在尝试从 ML 中的现代编译器实现 为 Tiger 语言编写解析器,但我被困在其中一种递归类型上。
我有以下类型
data LValue =
Id Atom
| RecordAccess LValue Atom
| ArraySubscript LValue Expression
语法如下:
lvalue -> id
-> lvalue.id
-> lvalue[exp]
id -> atom
exp -> (the big, overarching, everything-is-an-expression type)
我正在尝试使用 Parsec 对其进行解析,但我陷入了无限递归循环。这是我当前的基本解析器:
lvalueParser :: Parsec String () LValue
lvalueParser =
try (Id <$> (atomParser <* (notFollowedBy (char '.'))))
<|> try recordAccessParser
where recordAccessParser = (uncurry RecordAccess) <$> do {
record <- lvalueParser;
char '.';
atom <- atomParser;
return (record, atom)
}
(注意:我还没有尝试实现任何东西来处理ArrayAccess 部分)
显然,当recordAccessParser 回调lvalueParser 时,就会发生无限循环。
我可以这样更改recordAccessParser:
recordAccessParser = (uncurry RecordAccess) <$> do {
record <- atomParser;
char '.';
atom <- atomParser;
return (Id record, atom)
}
然后它终止。但是,它解析记录访问的深度不会超过单层:
Parsec.parse lvalueParser "" "record_1.field_1.field_2"
#=> RecordAccess (Id record_1) (Id field_1)
我期待
#=> RecordAccess (RecordAccess (Id record_1) (Id field_1)) (Id field_2)
我查看了chainl1,但是链接解析器的类型是a -> a -> a,这与反映语法的LValue 的类型不匹配。我还看了many;但是我没有每个术语的常量前缀 - 左递归术语是我试图解析为结果类型的一部分。
我想我缺少 Parsec/解析的特定概念,并希望指出正确的方向。我正在为其编写解析器的语言中有更多类型将具有类似的结构。
【问题讨论】:
标签: parsing haskell parsec left-recursion