2017-03-13 2 views
0

Je suis coincé dans l'écriture d'un DSL en utilisant XText. Supposons que je veux analyser quelque chose comme ceci:XText DSL avec lookbehind

A { 
    B, //this comma is needed 
    C, 
    D {E}, //comma is optional after a closing curly brace 
    F {G} 
    H 
} 
I, 
J 

Il devrait être représenté par les types de modèle et classe, où le modèle contient une liste des classes.

Ce que j'ai est actuellement:

Model: (classes += Class)* 
Class: name = ID ('{' (subclasses += Class) (',' subclasses += Class)* '}')? 

Cela fonctionnerait si les classes doivent être séparés par une virgule, indépendamment de les avoir sous-classes ou non. Cependant, comme une classe peut avoir des sous-classes encadrées par des accolades, une virgule n'est pas obligatoire après une accolade de fermeture.

Cela signifie que je besoin d'une grammaire exprimant les éléments suivants:

Class: ID (',' Class | '{' subclasses += Class '}' ','? Class)? 

Depuis que je ne suis pas en mesure de faire référence à la règle contenant, la référence de la règle de classe à l'intérieur de classe ne fonctionnera pas. Je crois qu'il existe une solution simple à ce problème que je ne vois tout simplement pas.

Editer: Je crois qu'un lookbehind serait une solution. Cependant, il me semble que ce n'est pas suppoerted dans XText.

Répondre

2

vous pouvez essayer quelque chose comme ce qui suit (+ une validation pour la dernière virgule)

Model: 
    ((classes+=ClassWithBraces|classes+=ClassWithComma)* classes+=ClassAtEnd?); 

ClassWithComma returns Class: 
    name=ID "," 
; 

ClassWithBraces returns Class: 
    name=ID =>("{" ((classes+=ClassWithBraces|classes+=ClassWithComma)* classes+=ClassAtEnd?) "}") ","? 
; 

ClassAtEnd returns Class: 
    name=ID 
; 
+0

Dans votre cas 'A {B} {} I' est autorisé, mais' A {} 'ne va pas ? –

+0

Je voulais juste mentionner qu'une fois que vous utilisez 'ClassAtEnd' comme facultatif et l'autre fois pas. –

+0

bonne prise, vous avez raison –