这是我工作的EBNF语法的简化:
%token NEWLINE BLOCK_MARK A
%start file
file: block+ NEWLINE*;
block: BLOCK_MARK line;
line: A+;
和 EOF 都吐出 NEWLINE 作为标记(因此在 EOF 之前不需要单个结尾 NEWLINE)。它适用于这样的流:
BLOCK_MARK A A BLOCK_MARK A NEWLINE[actually EOF]
现在我想在block
中有几个line
,至少一个是强制性的,其余的用NEWLINE
分开。 例如:
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
时,S/R冲突。我想状态机在决定NEWLINE
是新块line
的一部分还是file
中的最终NEWLINE*
(这是必需的,因为文件可以以 NEWLINE/EOF 结尾)感到困惑。
我该如何解决这个问题?
你想要的是使换行符成为前一行的一部分,将除一行以外的任何内容的减少推迟到你看到换行符之后。 所以你最终会得到:
file: block+ ;
block: BLOCK_MARK line_nl+ line_nonl? | BLOCK_MARK line_nonl ;
line_nl: line NEWLINE ;
line_nonl: line ;
line: A+ ;
现在上面唯一的问题是它不允许任何空行(空行将是语法错误)。 但这与您的原始语法相同。
基于克里斯·多德的想法,但在我的第一次尝试中发生了逆转。基本的想法只是在file
处移除NEWLINE*
,毕竟这已经被line
覆盖了。
file: block+;
block: BLOCK_MARK line_nonl line_nl* NEWLINE?;
line_nl: NEWLINE line_nonl;
line_nonl: A+;
我认为这个可以解决所有情况。