0

这是我的工作 EBNF 语法的简化:

%token NEWLINE BLOCK_MARK A
%start file

file: block+ NEWLINE*;
block: BLOCK_MARK line;
line: A+;

\n 和 EOF 都将 NEWLINE 作为令牌吐出(因此在 EOF 之前不需要单个结尾的 NEWLINE)。它适用于这样的流:

BLOCK_MARK A A BLOCK_MARK A NEWLINE[actually EOF]

现在我想有几个lineblock至少一个是强制性的,其余的用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;

但是 Jison 在前瞻时抱怨 S/R 冲突NEWLINE。我猜状态机在决定它NEWLINE是新块的一部分line还是最终NEWLINE*输入时感到困惑file(这是必需的,因为文件可以以 NEWLINE/EOF 结尾)。

我怎样才能解决这个问题?

4

2 回答 2

1

您想要的是使换行符成为前一行的一部分,将除一行之外的任何内容的减少推迟到您看到换行符之后。所以你最终得到:

file: block+ ;
block: BLOCK_MARK line_nl+ line_nonl? | BLOCK_MARK line_nonl ;
line_nl: line NEWLINE ;
line_nonl: line ;
line: A+ ;

现在上面唯一的问题是它不允许任何空行(空行将是语法错误)。但这与您的原始语法相同。

于 2013-12-22T01:42:58.890 回答
0

基于 Chris Dodd 的想法,但在我第一次尝试时就逆转了。基本的想法只是删除NEWLINE*at ,毕竟file它已经被覆盖了。line

file: block+;
block: BLOCK_MARK line_nonl line_nl* NEWLINE?;
line_nl: NEWLINE line_nonl;
line_nonl: A+;

我认为这个解决了所有情况。

于 2013-12-22T17:52:49.287 回答