QML文法是LALR(1)吗?

Is QML Grammar LALR(1)?

这是一个QML语法(摘自https://github.com/kropp/intellij-qml/blob/master/grammars/qml.bnf):

/* identifier, value, integer and float are terminals */

qml ::= object  /* Simplified */

object ::= type body
body ::= '{' (property_definition|signal_definition|attribute_assignment|method_attribute)* '}'
type ::= 'double'|'real'|identifier

attribute_assignment ::= (attribute ':')? attribute_value ';'?
item ::= list|object|string|boolean|number|identifier|value
attribute_value ::= method_call|method_body|item|value+

property_definition ::= 'default'? 'readonly'? 'property' ('alias'|'var'|type) property (':' attribute_value)?
signal_definition ::= 'signal' signal ('(' (signal_parameter ',')* signal_parameter? ')')?
signal_parameter ::= ('var'|type) parameter

method_attribute ::= 'function' method '(' (parameter ',')* parameter? ')' method_body

method_call ::= method '(' (argument ',')* argument? ')'

method_body ::= '{' javascript '}'
javascript ::= ('{' javascript '}'|'var'|'['|']'|'('|')'|','|':'|';'|string|identifier|number|value)*

list ::= '[' item? (',' item)* ']'

property ::= identifier
attribute ::= identifier
signal ::= identifier
parameter ::= identifier
method ::= identifier
argument ::= string|boolean|number|identifier|value

number ::= integer|float
boolean ::= 'true'|'false'

是 LALR(1) 吗?我的程序为包含冲突项的闭包 I[n] 引发了 reduce/reduce 冲突:

// other items here...
[item ::= identifier . , {]  // -> ACTION[n, {] = reduce to item  
[type ::= identifier . , {]  // -> ACTION[n, {] = reduce to type  
// other items here...

注:

下面的回答是根据问题提供的信息写的。碰巧的是,QML 的实际实现只接受名称以大写字母开头的类型的用户声明,而属性名称必须以小写字母开头。 (许多内置类型的名称也以小写字母开头。所以它并不像在词法扫描中根据标识符的首字母将标识符分为两类那么简单。内置类型和关键字仍然需要被认可。)

不幸的是,我没能找到明确的 QML 语法,甚至连语法的正式描述都找不到。以上评论基于Qt's QML Reference.

感谢 @mishmashru 提请我注意以上内容。


语法不明确,因此解析器生成器正确识别了 reduce/reduce 冲突。

特别是考虑从语法中提取的以下简化产生式,其中删除了大多数备选方案以关注冲突:

body ::= '{' attribute_assignment* '}'
attribute_assignment ::= attribute_value
attribute_value ::= method_body | item
method_body ::= '{' javascript '}'
item ::= object | identifier
object ::= type body
type ::= identifier

现在,考虑开始于

body
{ x {

我们假设解析器刚刚看到 x,现在正在查看第二个 {,以确定要采取的操作。

如果 x 是一个普通标识符(无论“普通”是什么意思,那么它可以解析为 item,这是 attribute_value 的替代方法。那么第二个 { 可能会启动一个 method_body,这也是 attribute_value.

的替代方法

另一方面,如果 x 是一个 type,那么我们正在寻找一个从 type body 开始的 object。在那种情况下,第二个 { 是内部 body.

的开始

所以解析器需要决定是直接把x变成attribute_value,还是把它变成type。此时无法做出决定,因为 { 前瞻标记没有提供足够的信息。

所以很明显语法不是LR(1)。

在不了解问题领域的更多信息的情况下,很难给出好的建议。如果可以区分 identifiertype,也许通过参考符号 table,那么您可以使用某种词汇反馈来解决这个问题。