Проблема с sablecc по производственному правилу вида prod = (expr | expr')*

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 ответа

Решение

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

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

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;

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

Другие вопросы по тегам