Проблема с sablecc по производственному правилу вида prod = (expr | expr ') * - PullRequest
1 голос
/ 28 марта 2011
Productions
    program = cls*;
    cls = clsdef name openbrace clsdata closingbrace;
    clsdata = (clsfield|clsmethod)*;
    clsfield = [variabletype]:name [variablename]:name semi;
    clsmethod = [returntype]:name [methodname]:name openmethodbrace closingmethodbrace openbrace closingbrace;

Проблема заключается в

clsdata = (clsfield|clsmethod)*;

Если я установлю clsdata на

clsdata = clsfield*;

или на

clsdata = clsmethod*;

, она будет работать нормально,хотя, как вы можете себе представить, это не означает то же, что и я.Я хочу, чтобы класс допускал как методы, так и поля (в произвольном порядке!).

Так что мой вопрос в том, как мне определить clsdata, чтобы я не получал ошибок.Я могу думать о рекурсивных альтернативах, но я бы хотел сохранить это как можно более чистым!

Спасибо

Ответы [ 2 ]

1 голос
/ 28 марта 2011

clsdata = (clsfield | clsmethod) *;

SableCC имеет синтаксис EBNF подобно , но не поддерживает правило грамматики этого типа.Как вы уже сделали, нетерминальные альтернативы clsfield и clsmethod необходимо рефракционировать в собственное производство.

но я не уверен, что это лучший способ сделать это

Если вы посмотрите на любую из SableeCC пример грамматик , вы увидите, что это стандартный способ определения «членов класса».Хотя вы могли бы упростить грамматику, удалив clsmembers:

Productions
    program = cls*;
    cls = clsdef name openbrace clsmember* closingbrace;
    clsmember = {clsfield} clsfield | {clsmethod} clsmethod;
    clsfield = [variabletype]:name [variablename]:name semi;
    clsmethod = [returntype]:name [methodname]:name openmethodbrace closingmethodbrace openbrace closingbrace
0 голосов
/ 28 марта 2011

Это работает:

Productions
    program = cls*;
    cls = clsdef name openbrace clsmembers closingbrace;
    clsmembers = clsmember*;
    clsmember = {clsfield} clsfield | {clsmethod} clsmethod;
    clsfield = [variabletype]:name [variablename]:name semi;
    clsmethod = [returntype]:name [methodname]:name openmethodbrace closingmethodbrace openbrace closingbrace;

но я не уверен, что это лучший способ сделать это.Я приветствую другие подходы!

...