怎么修? Xtext 语法在输入不正确时停止使用 'no viable alternative at input ...' 进行解析
How to fix? Xtext grammar stops parsing with 'no viable alternative at input ...' on incorrect input
作为 Xtext 和 Antlr 的新手,我正在努力为我要解析的(与 JVM 无关的)语言的一个非常简单的子集获取容错的 Xtext 语法。
这种迷你语言的文档可能如下所示:
$c wff |- $.
$c class $.
$c set $.
因此,由 $c
和 $.
关键字包围的一系列语句,中间有一个或多个可能不包含 $
的词。并且所有内容都由 mandatory 空格分隔。
我能想到的最好的是以下语法:
grammar mm.ecxt.MMLanguage
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
generate mmLanguage "urn:marnix:mm.exct/MMLanguage"
MMDatabase:
WS? (statements+=statement WS)* statements+=statement WS?;
statement:
DOLLAR_C WS (symbols+=MATHSYMBOL WS)+ DOLLAR_DOT;
terminal DOLLAR_C: '$c';
terminal DOLLAR_DOT: '$.';
terminal MATHSYMBOL:
('!'..'#'|'%'..'~')+; /* everything except '$' */
terminal WS : (' '|'\t'|'\r'|'\n')+;
terminal WORD: ('!'..'~')+;
对于有效输入,此语法可以正常工作。但是,对于无效输入,例如
$c class $.
$c $.
$c set $.
$c x$u $.
只有一个错误 (no viable alternative at input '$.'
),之后看起来解析就停止了:没有检测到更多错误,模型只包含错误之前的正确语句(这里只有 class
声明)。
我尝试了各种变体(使用 =>
、with/without terminal
声明、启用回溯等等)但我得到的只是 no viable alternative at input ...
.
所以我的问题是:我应该如何为这种语言编写语法以便 Antlr 进行某种形式的错误恢复?还是我做错了什么?
来自,例如,http://zarnekow.blogspot.de/2012/11/xtext-corner-7-parser-error-recovery.html 我预计这会开箱即用。还是因为我没有使用基于 Xbase 的 Java/C-like 语法?
这里似乎发生的是,在您的示例输入的第 2 行中,根据您的语法缺少两个标记:解析器需要 (symbols+=MATHSYMBOL WS)+
但得到 $.
。 Antlr 会很乐意尝试使用不同的策略进行恢复,一些在本地工作,而另一些则在每个解析器规则的基础上工作。 Antlr 不会插入两个恢复令牌来完成规则 statement
但它会从那里退出。在该声明之后,预计会出现强制性的 WS
,但它会看到 $.
,因此它会再次退出。这就是为什么它似乎根本无法恢复。
好吧,所有这些或多或少都是有根据的猜测。
但有帮助的是一个小的语法重构,你不让语法像现在一样严格。一些可选的标记将帮助解析器恢复:
MMDatabase:
WS? (statements+=statement WS?)*;
statement:
DOLLAR_C WS (symbols+=MATHSYMBOL WS?)* DOLLAR_DOT;
作为 Xtext 和 Antlr 的新手,我正在努力为我要解析的(与 JVM 无关的)语言的一个非常简单的子集获取容错的 Xtext 语法。
这种迷你语言的文档可能如下所示:
$c wff |- $.
$c class $.
$c set $.
因此,由 $c
和 $.
关键字包围的一系列语句,中间有一个或多个可能不包含 $
的词。并且所有内容都由 mandatory 空格分隔。
我能想到的最好的是以下语法:
grammar mm.ecxt.MMLanguage
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
generate mmLanguage "urn:marnix:mm.exct/MMLanguage"
MMDatabase:
WS? (statements+=statement WS)* statements+=statement WS?;
statement:
DOLLAR_C WS (symbols+=MATHSYMBOL WS)+ DOLLAR_DOT;
terminal DOLLAR_C: '$c';
terminal DOLLAR_DOT: '$.';
terminal MATHSYMBOL:
('!'..'#'|'%'..'~')+; /* everything except '$' */
terminal WS : (' '|'\t'|'\r'|'\n')+;
terminal WORD: ('!'..'~')+;
对于有效输入,此语法可以正常工作。但是,对于无效输入,例如
$c class $.
$c $.
$c set $.
$c x$u $.
只有一个错误 (no viable alternative at input '$.'
),之后看起来解析就停止了:没有检测到更多错误,模型只包含错误之前的正确语句(这里只有 class
声明)。
我尝试了各种变体(使用 =>
、with/without terminal
声明、启用回溯等等)但我得到的只是 no viable alternative at input ...
.
所以我的问题是:我应该如何为这种语言编写语法以便 Antlr 进行某种形式的错误恢复?还是我做错了什么?
来自,例如,http://zarnekow.blogspot.de/2012/11/xtext-corner-7-parser-error-recovery.html 我预计这会开箱即用。还是因为我没有使用基于 Xbase 的 Java/C-like 语法?
这里似乎发生的是,在您的示例输入的第 2 行中,根据您的语法缺少两个标记:解析器需要 (symbols+=MATHSYMBOL WS)+
但得到 $.
。 Antlr 会很乐意尝试使用不同的策略进行恢复,一些在本地工作,而另一些则在每个解析器规则的基础上工作。 Antlr 不会插入两个恢复令牌来完成规则 statement
但它会从那里退出。在该声明之后,预计会出现强制性的 WS
,但它会看到 $.
,因此它会再次退出。这就是为什么它似乎根本无法恢复。
好吧,所有这些或多或少都是有根据的猜测。
但有帮助的是一个小的语法重构,你不让语法像现在一样严格。一些可选的标记将帮助解析器恢复:
MMDatabase:
WS? (statements+=statement WS?)*;
statement:
DOLLAR_C WS (symbols+=MATHSYMBOL WS?)* DOLLAR_DOT;