我有一个Yacc符号的语法片段:
stylesheet
: [ CHARSET_SYM STRING ';' ]?
[S|CDO|CDC]* [ import [ CDO S* | CDC S* ]* ]*
[ [ ruleset | media | page ] [ CDO S* | CDC S* ]* ]*
;
如何在Irony中实现此片段?我找不到?
的任何等价物,这意味着在Yacc中出现0或1。
答案 0 :(得分:2)
您可以使用BnfTerm.Q
方法来表示'?'(0或1次出现)。
这是一个合理的设计决策,因为C#不允许您编写?
运算符的自定义实现,与+
和*
不同。
来自讽刺Wikibook上的Non Terminals page:
在传统的BNF表示法中,使用“?”,“+”和“*”字符 表示“0或1次”,“1次或更多次”和“0次或更多次”, 分别。在反讽中,它的表现略有不同。你用的是 MakePlusRule和MakeStarRule方法来自基础语法类 “+”和“*”或者您可以使用Q(),Plus()和Star()方法 直接在规则中的术语。
答案 1 :(得分:1)
作者说现在需要一个额外的AST节点用于此目的。 例如,您可以将以下内容替换为规则中的可选术语:
new NonTerminal("OptionalTermName", Empty | TermThatShouldBeOptional)
http://irony.codeplex.com/discussions/550979
我想知道它是否可以简化为:
(Empty | TermThatShouldBeOptional)
重载会创建一个BNF Term,而不是NonTerminal节点,当与其他BNF术语直接连接时,可能会丢失一些分层信息,具体取决于实现。我没有进一步调查。