这是我工作的EBNF语法的简化:
%token NEWLINE BLOCK_MARK A
%start file
file: block+ NEWLINE*;
block: BLOCK_MARK line;
line: A+;
\ n \ n和\ n \ EOF都将NEWLINE作为代币吐出(因此在EOF之前不需要单个结束NEWLINE)。它适用于这样的流:
BLOCK_MARK A A BLOCK_MARK A NEWLINE[actually EOF]
现在我希望在line
中有多个block
,其中至少有一个是强制性的,其余的则用NEWLINE
分隔。 E.g:
BLOCK_MARK A A NEWLINE A A BLOCK_MARK A A A EOF
我试过这样做:
file: block+ NEWLINE*;
block: BLOCK_MARK line moreline*;
line: A+;
moreline: NEWLINE line;
但是当前瞻是NEWLINE
时,Jison抱怨S / R冲突。我想状态机很困惑,决定NEWLINE
是否是新line
的一部分或NEWLINE*
中的最终file
(这是必需的,因为文件可以以NEWLINE / EOF)。
我该如何解决这个问题?
答案 0 :(得分:1)
你想要的是将换行符作为前一行的一部分,在看到换行符之前推迟减少除行之外的任何内容。所以你最终得到:
file: block+ ;
block: BLOCK_MARK line_nl+ line_nonl? | BLOCK_MARK line_nonl ;
line_nl: line NEWLINE ;
line_nonl: line ;
line: A+ ;
现在唯一的问题是它不允许任何空白行(空行会出现语法错误)。但这与你的原始语法相同。
答案 1 :(得分:0)
根据克里斯多德的想法,但在我的第一次尝试中反转。基本想法就是删除NEWLINE*
处的file
,line
已经涵盖了file: block+;
block: BLOCK_MARK line_nonl line_nl* NEWLINE?;
line_nl: NEWLINE line_nonl;
line_nonl: A+;
。
{{1}}
我认为这个解决了所有情况。