6

我写了一个简单的语法来识别一些表达式。在这里,我发布了一个更简单的版本,我写它只是为了简化我的解释。这个更简单的版本可以识别如下表达式:

  1. 这是一个文本
  2. [n]这是另一个文本[/n]
  3. [n][n]这是一个复合表达式[/n][/n]

我的问题是当我总结一个表达式时:[i]这应该只生成一个识别异常[/n]

抛出识别异常,但解析器进入无限递归,因为它匹配'[',但是当它不匹配'i'时它会丢失自己。我认为这是因为我的语法文本组件不能包含方括号。所以,我发布了语法。

grammar ErrorTest;

expression
    :    rawText EOF
    |    command EOF
    ;

rawText
    :    word+
    ;

word
    :    ESPACE* TEXT ESPACE*
    ;

command 
    :    simpleCommand
    |    compoundCommand
    ;

simpleCommand
    :    HELP
    ;

compoundCommand
    :    rawText
    |    BEGIN compoundCommand END
    ;

HELP   : '[help]';

BEGIN  : '[n]';
END    : '[/n]';

ESPACE : ' ';
TEXT   : ~(' '|'['|']')*;

我该如何解决?

4

2 回答 2

6

word 匹配空字符串,因为在

word
    :    ESPACE* TEXT ESPACE*
    ;

TEXT 匹配导致的空字符串

rawText
    :    word+
    ;

无限循环。

改变

TEXT   : ~(' '|'['|']')*;

TEXT   : ~(' '|'['|']')+;

这将使您的语法只有有限的模棱两可。

考虑这个的方法是rawText可以通过多种方式匹配空字符串

  1. 零 TEXT 令牌
  2. 一个长度为 0 的 TEXT 令牌。
  3. 两个长度为 0 的 TEXT 标记。
  4. 三个长度为 0 的 TEXT 标记。
  5. ...

这会在您遇到语法错误 ( [i]) 时表现出来,因为它会尝试这些替代方案中的每一个以查看它们中的任何一个是否解决了错误。


为了摆脱任何二次行为,你真的应该让它完全明确。

rawText : ign (word (ign word)*)? ign;
ign     : ESPACE*;
word    : TEXT;

天真的修复的问题是 rawText 可以"foo"通过多种方式匹配:

  1. TEXT("foo")
  2. TEXT("fo"), ESPACE(""), TEXT("o")
  3. TEXT("f"), ESPACE(""), TEXT("oo")
  4. TEXT("f"), ESPACE(""), TEXT("o"), ESPACE(""), TEXT("o")
于 2012-04-25T23:28:06.637 回答
1

为什么不做这样的事情:

grammar Test;

expression
 : atom+ EOF
 ;

atom
 : TEXT
 | ESPACE
 | command
 ;

command 
 : simpleCommand
 | compoundCommand
 ;

simpleCommand
 : HELP
 ;

compoundCommand
 : BEGIN atom+ END
 ;

HELP   : '[help]';
BEGIN  : '[n]';
END    : '[/n]';
ESPACE : ' ';
TEXT   : ~(' '|'['|']')+;

这会像输入一样

this is [n][n]a [help][n]compound[/n] expression[/n][/n]

进入以下解析树:

在此处输入图像描述

(点击图片放大)

于 2012-04-26T07:09:58.650 回答