如何最好地编写这个xtext语法

时间:2016-09-07 22:50:28

标签: grammar xtext bnf context-sensitive-grammar

我正在使用Xtext,需要就以下两个问题提出建议。

问题#1

假设我有三条规则a,b和c。并且我想允许这些规则的任何序列,除了b和c应该只出现一次。如何最好地编写这样的语法?

以下是我提出的建议:

root:
  a+=a*
  b=b
  a+=a*
  c=c
  a+=a*
;
a: 'a';
b: 'b';
c: 'c';

有没有更好的方法来编写根语法? b和c仍然必须严格按顺序排列,这并不理想。

问题#2

看看这个语法:

root:
    any+=any*
    x=x
    any+=any*
;

any:
    name=ID
    '{'
        any+=any*
    '}'
;

x:
    name='x' '{' y=y '}'
;

y:
    name='y' '{' z=z '}'
;

z:
    name='z' '{' any+=any* '}'
;

使用这种语法我希望能够编写如下语言:

a {
    b {

    }

    c {
        y {

        }
    }
}

x {
    y {
        z {
            the_end {}
        }
    }
}

但是,由于节点“y”出现在“c”下,我收到错误。这是为什么?是因为现在“y”已被用作其中一个规则中的终端,它在语法中的任何其他地方都不会出现?

如何解决这个语法?

2 个答案:

答案 0 :(得分:1)

对于问题#1:

root: a+=a* (b=b a+=a* & c=c a+=a*);

对于问题#2,您需要datatype rule,如下所示:

IdOrABC: ID | 'a' | 'b' | 'c' ;

,您必须在any规则name=IdOrABC中使用它,而不是name=ID

答案 1 :(得分:0)

对于问题#1,我们可以调整语法如下:

root:
  a+=a*
  (
    b=b a+=a* c=c
    |
    c=c a+=a* b=b
  )
  a+=a*
;
a: 'a';
b: 'b';
c: 'c';

另一方面,问题#2无法通过语法真正解决,因为解析器永远无法区分ID和特殊关键字" x"," y"或" z"。也许更好的策略是保持语法简单如下:     根:       任何+ =任何+     ;

any:
  name=ID
  '{'
    any+=any+
  '}'
;

并通过验证器强制执行特殊的x / y / z层次结构。