我想解析类似的东西:
变量路径
“path”和“to”是名为“Instance”的对象,变量引用了一个double。
我有以下语法:
expr ::= instancePath:i INSTANCE_SEPARATOR SHORTCUT:s
{:
RESULT = getDouble(s);
:}
;
instancePath ::= instanceSubPath:p
{:
RESULT = p;
:}
;
instanceSubPath ::= instanceSubPath:i1 INSTANCE_SEPARATOR instanceSubPath:i2
{:
RESULT = i2;
:}
| SHORTCUT:s
{:
RESULT = pushInstance(s);
:}
;
在这个语法中:
- INSTANCE_SEPARATOR 是“。” 字符。
- SHORTCUT 是一个仅包含“path”、“to”或“variable”之类的字母的名称。
- expr 必须返回通过调用函数 getDouble 获得的双精度值,该函数采用名称(此处为“变量”)。此函数使用当前选定的实例。一个实例包含一个包含双精度或其他实例的哈希表。
- pushInstance 是一个设置当前实例的函数
例如我们可以有:
- 包含哈希表的实例“路径”:“to”=>链接到实例“to”
- 一个实例“to”,其中包含一个哈希表:“variable”=>10
- 路径“path.to.variable”必须返回 10。
这不会运行,因为语法抱怨空值。这是因为解析器这样做:
expr(
instancePath(
instanceSubPath(SHORTCUT("path"))
INSTANCE_SEPARATOR
instanceSubPath(SHORTCUT("to"))
INSTANCE_SEPARATOR
instanceSubPath(SHORTCUT("variable"))
)
INSTANCE_SEPARATOR
!NULL!
)
而不是做
expr(
instancePath(
instanceSubPath(SHORTCUT("path"))
INSTANCE_SEPARATOR
instanceSubPath(SHORTCUT("to"))
)
INSTANCE_SEPARATOR
SHORTCUT("variable")
)
为什么 ?有优先级问题吗?
最后,如果我删除 instancePath 规则,所有运行:
expr ::= instanceSubPath:i INSTANCE_SEPARATOR SHORTCUT:s
{:
RESULT = getDouble(s);
:}
;
instanceSubPath ::= instanceSubPath:i1 INSTANCE_SEPARATOR instanceSubPath:i2
{:
RESULT = i2;
:}
| SHORTCUT:s
{:
RESULT = pushInstance(s);
:}
;
我无法删除这些额外的规则,因为我已经简化了示例,但实际上它要复杂得多。
我不明白为什么删除这个额外的规则可以解决我的问题......