我在Eclipse环境中使用ANTLR。
我想将属性 (n.text
) 传递给另一个规则 (description
),并在后一个规则中使用语义谓词来验证与 相关的输入>n.text
。这是我的代码:
useCaseSpecification
: n=useCase '='
description[$n.text]
;
useCase
: ucID=('UC' INTEGER)? ucName
;
ucName
: caren io
;
caren
: 'create' | 'creates' | alter | read | 'erase' | 'erases' | notify
;
/* ..more code */
description[String str]
: 'Description' ':' primaryActor (useCase {str==$useCase.text}?) /* more grammar */
;
我尝试了语义谓词表达式的许多替代方案,例如 {str.equals($useCase.text)}
,但没有任何结果。解析器似乎没有进行验证。
当我用示例运行解释器时,它允许 useCase 类型的每个输入。例如,如果输入是:
create a Prescription = Description: a doctor create a Prescription /* ... */
这应该是正确的。
如果输入是:
create a Prescription = Description: a doctor create a Rrrrescription /* ... */
这应该是错误的。
最佳答案
不要依赖解释器(ANTLRWorks 的解释器或 Eclipse 的插件之一)。解释器不考虑任何谓词。
此外,不确定您使用的目标是什么,但要意识到 {str==$useCase.text}?
如果您使用 Java (==
比较对象的身份,请使用 equals(...)
代替)。
例如,解析两个相同的字母可以如下完成:
grammar T;
parse
: Letter same[$Letter.text] EOF
;
same [String s]
: Letter {$Letter.text.equals(s)}?
;
Letter : 'a'..'z' | 'A'..'Z';
解析“AB”
将导致异常:
解析“AA”
时不会:
上面的树是使用 ANTLRWorks 的调试器生成的,它的工作方式就像一个魅力。请注意,调试器会忽略 language=XYZ
选项:它将以 Java 作为目标语言来调试语法。因此,除 Java 之外的任何嵌入式代码都会导致问题!
请注意,在语法中塞入过多的语义检查将导致难以维护混合语法规则和代码的困惑。此类检查通常在解析器创建(抽象)解析树之后执行:这意味着自由匹配 useCase,然后在迭代解析器创建的树时验证它们。
关于parameters - antlr 传递参数和语义谓词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11599943/