Определение примитивов в xtext Grammar

Я хотел бы создать невероятно простой DSL с использованием xtext со следующими функциями:

  • Он будет иметь два примитивных типа: Number и String.
  • Пользователи могут определять свои собственные классы, состоящие из объявлений полей.
  • Объявление поля связывает имя с типом, где тип может быть классом или примитивом.

Ниже приведена моя попытка DSL, определение класса и ссылки работают нормально, но я не могу понять, как иметь примитивные типы. Литералы «String» и «Number» не работают:

Model:
    (classes+=Class)*
    (fields+=Field)*;

FieldType: Class | 'String' | 'Number';

Field:
    type=[FieldType] name=ID ";";

Class:
    "class" name=ID
    "{"
        (fields+=Field)*
    "}";

Вот пример, который, как я ожидаю, будет действителен для вышеуказанного DSL:

Class SomeClass {

}

// This works!
SomeClass reference;

// This does not, doesn't recognise the "String" literal
String string;

Обратите внимание, что в дальнейшем я буду поддерживать назначение. Таким образом, мой DSL должен будет включать концепцию числовых / строковых литералов, чтобы он поддерживал Number someNumber = 123;


person jwa    schedule 18.10.2013    source источник
comment
Другие ваши литералы заключены в двойные кавычки, имеет ли это значение? Я не знаю грамматики.   -  person Dave Newton    schedule 19.10.2013


Ответы (1)


Выспавшись на нем, я думаю, что правильный ответ — изменить свой подход. В приведенном выше определении имеем

Field:
    type=[FieldType] name=ID ";";

Это определяет правило под названием «Поле», которое состоит из двух частей; «тип» и «имя». Это часть типа, которая представляет проблему. Квадратные скобки означают, что мы ожидаем экземпляр FieldType, а именно:

FieldType: Class | 'String' | 'Number';

Теперь ясно, что у вас может быть экземпляр класса, но семантически нет возможности иметь экземпляр литералов «String» или «Number».

Я считаю, что именно поэтому мой DSL выше не позволяет мне объявлять примитивы. "Типы" String/Number просто не являются элементами, экземпляры которых у вас могут быть.


Если подумать дальше, есть несколько очень важных различий между определениями полей, которые являются примитивными, и теми, которые являются экземплярами класса. Например, вы можете вызывать методы только для экземпляров класса (в моем случае я рассматриваю String как настоящий примитив, поэтому никаких методов).

Таким образом, вероятно, важно иметь два разных типа объявлений, одно для PrimitiveField и одно для ObjectField. Поле может быть одним из следующих:

Model:
    (classes+=Class)*
    (fields+=Field)*;

PrimitiveType: 'String' | 'Number' | 'Boolean';

Field:
    PrimitiveField | ObjectField
;

PrimitiveField:
    type=PrimitiveType name=ID ";"
;
ObjectField:
    type=[Class] name=ID ";";

Class:
    "class" name=ID
    "{"
    (fields+=Field)*
    (methods+=Method)*
    "}";
person jwa    schedule 19.10.2013
comment
Я не совсем уверен, что полностью понял проблему! Пожалуйста, прокомментируйте / дайте новый ответ, если заметите что-то, что я видел! - person jwa; 19.10.2013
comment
У меня была такая же проблема. Ваше решение работает почти на 100% правильно, но в сгенерированном редакторе для примитивных типов (например: Number или String) нет автодополнения кода. У вас есть идеи, почему? - person Balázs Édes; 17.05.2014