1

I am using Xtext, and need suggestions on the following two problems.

Problem #1

Lets say I have three rules a, b and c. And I want to allow any sequence of these rules, except that b and c should appear only once. How best to write such a grammar?

Here is what I came up with:

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

Is there a better way to write root grammar? b and c still have to be in a strict order, which is not ideal.

Problem #2

Have a look at this grammar:

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* '}'
;

Using this grammar I expected to be able to write a language like below:

a {
    b {

    }

    c {
        y {

        }
    }
}

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

However, I get an error due to the node "y" appearing under "c". Why is that? Is it because now that "y" has been used as a terminal in one of the rules, it cannot appear anywhere else in the grammar?

How to fix this grammar?

Waqas Ilyas
  • 3,116
  • 1
  • 17
  • 27

2 Answers2

1

For problem #1:

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

For problem #2 you need a datatype rule like this:

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

and you have to use it in your any rule like name=IdOrABC instead of name=ID.

Bernhard Stadler
  • 1,725
  • 14
  • 24
  • Yes I thought of that too after posting my answer, but didn't pursue it further and instead opted to use vaildators. It seemed like a better choice. I will, however, accept your answer because it does seem right, even though I would not be able to try it out. – Waqas Ilyas Oct 20 '16 at 00:50
0

For problem #1, we can adjust the grammar like below:

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

On the other hand, the problem #2 cannot really be solved via the grammar as parser can never differentiate between an ID and the special keyword "x", "y" or "z". Perhaps a better strategy would be to keep the grammar simple like below: root: any+=any+ ;

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

And enforce the special x/y/z hierarchy via validators.

Waqas Ilyas
  • 3,116
  • 1
  • 17
  • 27
  • 1
    For problem 1, your solution is feasible because you have only 2 unordered "special cases" ``b`` and ``c``, which result in 2 possible orderings ``... b ... c ...`` and ``... c ... b ...``. But if you have ``n`` special cases, you have ``n!`` possible orderings, which makes the grammar huge. So even for 3 or 4 special cases, you will need a different solution, based on unordered groups. – Bernhard Stadler Oct 19 '16 at 10:19
  • Do you have any suggestions on how this can be done through unordered groups? – Waqas Ilyas Oct 20 '16 at 00:55