Parsing 持续移位-减少Goldparser中的冲突
我真的被Goldparser中的Shift-Reduce冲突所困扰 我编写了一个类似PHP的语法,理论上应该能够解析以下脚本:Parsing 持续移位-减少Goldparser中的冲突,parsing,shift-reduce-conflict,gold-parser,Parsing,Shift Reduce Conflict,Gold Parser,我真的被Goldparser中的Shift-Reduce冲突所困扰 我编写了一个类似PHP的语法,理论上应该能够解析以下脚本: public $Test = null; protected $bDemo = true; function Main() { } private function Run() { } 在顶部,我想分配全局变量,然后是函数定义 为了缩小问题的范围,我把我的大语法简化为以下几行,它们可以重现错误。显然,这是不完整的。函数没有参数,没有返回值,也没有语句 "Start
public $Test = null;
protected $bDemo = true;
function Main()
{
}
private function Run()
{
}
在顶部,我想分配全局变量,然后是函数定义
为了缩小问题的范围,我把我的大语法简化为以下几行,它们可以重现错误。显然,这是不完整的。函数没有参数,没有返回值,也没有语句
"Start Symbol" = <Script>
! ------------------------------------------------- Sets
{Name} = {Letter} + {Alphanumeric} + [_]
! ------------------------------------------------- Terminals
VarName = '$' {Name}*
FuncName = {Name}*
! ------------------------------------------------- Rules
<Variable> ::= VarName
<Value> ::= 'null'
| 'true'
| 'false'
<Modifier> ::= 'private'
| 'protected'
| 'public'
<ModifierOpt> ::= <Modifier>
|
! ---------------
<GlbAssignVar> ::= <ModifierOpt> <Variable> '=' <Value> ';'
<GlobalList> ::= <GlobalList> <GlbAssignVar>
| <GlbAssignVar>
<GlobalListOpt> ::= <GlobalList>
|
! ---------------
<FuncDef> ::= <ModifierOpt> 'function' FuncName '(' ')' '{' '}'
<FuncList> ::= <FuncList> <FuncDef>
| <FuncDef>
<FuncListOpt> ::= <FuncList>
|
! ---------------
<Script> ::= <GlobalListOpt> <FuncListOpt>
“开始符号”=
! ------------------------------------------------- 设置
{Name}={Letter}+{Alphanumeric}+[[uUX]
! ------------------------------------------------- 终端
VarName='$'{Name}*
FuncName={Name}*
! ------------------------------------------------- 规则
:=VarName
:='null'
|“真的”
|“假”
:=“私人”
|“受保护”
|“公众”
::=
|
! ---------------
::= '=' ';'
::=
|
::=
|
! ---------------
::='函数'FuncName'('')'{'}'
::=
|
::=
|
! ---------------
::=
构建LALR表时,Goldparser告诉我:
“解决了减少冲突的问题
“private”、“protected”、“public”可以遵循已完成的规则,也可以进行转换。冲突是通过在“reduce”上选择“shift”操作解决的。请小心,某些语法部分可能无法访问。建议您尝试删除所有冲突。”
但是它所应用的修正使得语法不能正确工作。在上面的示例中,我在function Main()
处得到一个语法错误,它需要一个“private
”、“protected
”或“public
”,尽管我声明它们是可选的
当我从
定义或
定义中删除
时,错误消失
我不知道怎么解决这个问题。请帮忙 请记住,解析器生成器正在构建一个
LALR(1)
解析器,这意味着解析器需要能够在从左向右扫描输入(LR
)时决定是减少已经完成的生产还是转移可能构成尚未完成生产一部分的令牌,仅查看下一个(1)
标记(可能会移位的标记)
因此,假设我们只能看到第一个标记,private
。现在,有两种可能性:
GlobalList
,其中的第一个声明是private
GlobalList
为空,但FuncList
中的第一个函数声明为private
private $a = null;
private function a() {}
但是我们只能看到令牌private
我们正在进行的生产是:
<Script> ::= <GlobalListOpt> <FuncListOpt>
这是因为现在解析器总是可以移动私有的
,即使它不知道最终会减少哪个生产。(这就是LR解析的神奇之处:解析器可以同时保持多个产品处于活动状态;在产品实际减少之前,它不需要提交其中一个产品。)
当然,更简单的解决方案是只允许用户将全局定义与函数交错:
<Script> ::=
| <Script> <FuncDef>
| <Script> <GlbAssignVar>
:=
|
|
它摆脱了<代码> FunCalists<代码>,<代码> FielSistopt < /C>,<代码> Guulalists< /C>和
,只是因为这是一个最小的更改。第二个示例允许使用任意数量的函数和变量。试试看:)
FuncListOpt
<Script> ::=
| <Script> <FuncDef>
| <Script> <GlbAssignVar>