У меня есть фрагмент грамматики в нотации Yacc:
stylesheet
: [ CHARSET_SYM STRING ';' ]?
[S|CDO|CDC]* [ import [ CDO S* | CDC S* ]* ]*
[ [ ruleset | media | page ] [ CDO S* | CDC S* ]* ]*
;
Как реализовать этот фрагмент в Иронии? Я не могу найти эквивалент ?
, что означает 0 или 1 появление в Yacc.
Вы можете использовать метод BnfTerm.Q
для представления '?' (0 или 1 вхождения). Это было разумное дизайнерское решение, поскольку С# не позволяет вам писать пользовательскую реализацию ?
оператор, в отличие от +
и *
.
На странице Non Terminals на Irony Wikibook:
В традиционной нотации BNF символы "?", "+" И "*" используются для обозначения "0 или 1 раз", "1 или более раз" и "0 или более раз" соответственно. В Иронии это делалось несколько иначе. Вы используете методы MakePlusRule и MakeStarRule из базового класса грамматики для "+" и "*", или вы можете использовать методы Q(), Plus() и Star() непосредственно на члене в правиле.
Автор говорит, что для этой цели теперь требуется дополнительный узел АСТ. Так, например, вы можете подставить следующее правило для необязательного термина в правиле:
new NonTerminal("OptionalTermName", Empty | TermThatShouldBeOptional)
http://irony.codeplex.com/discussions/550979
Интересно, можно ли это уменьшить:
(Empty | TermThatShouldBeOptional)
Перегрузка создает термин BNF, а не узел NonTerminal, который может потерять некоторую иерархическую информацию при соединении напрямую с другими терминами BNF в зависимости от реализации. Я еще не исследовал.