我目前正在为我的语法开发解析器。我的目标是不做任何提前准备,而这正是我真正奋斗的目标。
这是我认为足以证明我所遇到的问题的一个精简示例。
void main() : {}
{
(A())* (B())*
}
void A() : {}
{
C() <ID>
}
void B() : {}
{
<ID> Z()
}
void C() : {}
{
<bah>
| <bha>
| <ID>
}
这是输出警告(我要删除它)
Warning: Choice conflict in (...)* construct at line 200, column 23.
Expansion nested within construct and expansion following construct
have common prefixes, one of which is: <ID>
Consider using a lookahead of 2 or more for nested expansion.
最佳答案
确实,我们需要更多地了解Z
。我假设L(Z
)(即Z
生成的语言)不包含空序列,也不包含以ID
,bha
或bah
开头的序列。我还要假设main
之后的第一个标记不能是ID
,bha
或bah
。
在这种情况下,我几乎肯定会先行使用
void main() : {}
{
AsBs()
}
void AsBs() : {}
{
LOOKAHEAD( A() )
A() AsBs() ;
|
(B()*)
|
{/*nothing*/}
}
与
A
,B
和C
相同,如原始帖子中所述。但是,张贴者需要不提前使用的解决方案。这是一个。我做出了与上述相同的假设。
void main() : {}
{
AsBs()
}
void AsBs() : {}
{
C1() <ID> AsBs()
|
<ID> // This ID might be the start of either A or B
( <ID> AsBs() // That ID started an A
| Z() (B())* ) // That ID started a B.
|
{/*nothing*/}
}
void B() : {}
{
<ID> Z()
}
void C1() : {}
{
<bah>
| <bha>
}
这里不需要
A
或C
。