grammar - 否定其他有效匹配的 Xtext 规则
问题描述
我对 Xtext 很陌生,所以我可能问错了问题,或者使用了不正确的术语。请在您的回复中牢记这一点。
我正在尝试在 Xtext 中从头开始实施JBehave EBNF Spec作为学习练习。JBehave 是一种非常“冗长”的语法,类似于我需要能够维护的语法,因此我需要了解如何在不同的上下文中处理各种类型的“单词”。
我已经能够让这个测试用例作为起点通过。
@Test
def void loadModel() {
// Multi-line
var story = parseHelper.parse('''
The quick brown fox
Jumps over the lazy dog
''')
assertThat(story, notNullValue())
assertThat(
story.description,
equalTo('''
The quick brown fox
Jumps over the lazy dog
''')
)
// Single-line description
story = parseHelper.parse('''
The quick brown fox
''')
assertThat(
story.description,
equalTo("The quick brown fox\n")
)
}
使用这个语法定义......
grammar org.example.jbehave.JBehave hidden (WS)
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
generate jbehave "http://www.example.org/jbehave"
// The story describes a feature via description, narrative and a set of scenarios
// Story := Description? Meta? Narrative? GivenStories? Lifecycle? Scenario+ ;
Story:
description=Description?
;
// The Description is expressed by any sequence of words that must not contain any keywords at start of lines.
// Description := (Word Space?)* ;
Description:
((WORD) (WORD)* EOL+)+
// ((NON_KEYWORD) (WORD)* EOL+)+
;
// Key Words
////
// TODO: parser fails when uncommented
//terminal NON_KEYWORD:
// !(IN_ORDER_TO
// | AS_A
// | I_WANT_TO
// | SO_THAT
// | SCENARIO
// | GIVEN_STORIES
// | GIVEN
// | THEN
// | WHEN
// | AND
// )
//;
terminal fragment IN_ORDER_TO: "In order to";
terminal fragment AS_A: "As a";
terminal fragment I_WANT_TO: "I want to";
terminal fragment SO_THAT: "So that";
terminal fragment SCENARIO: "Scenario:";
terminal fragment GIVEN_STORIES: "GivenStories:";
terminal fragment GIVEN: "Given";
terminal fragment WHEN: "When";
terminal fragment THEN: "Then";
terminal fragment AND: "And";
// Common Terminals
////
terminal WORD: ('a'..'z'|'A'..'Z'|'_')('a'..'z'|'A'..'Z'|'_'|'0'..'9')*;
terminal WS: (' '|'\t')+;
terminal EOL: NL;
terminal fragment NL: ('\r'? '\n');
评论中概述了我遇到的问题。
- 当我取消注释终端
NON_KEYWORD
时,测试失败预期:“敏捷的棕色狐狸\n跳过懒狗\n”但:是“The”
- 如果我然后替换注释掉的行
Description
,则测试根本无法解析为预期:不为空,但:为空
我有点模糊地理解这里发生的事情。我在 WORD 之前定义的标记也是有效的单词,因此它会抛出解析器。因此,我的问题如下。
我在哪里可以找到 Xtext 文档(或其他来源),这些文档描述了此处受影响的基础原则。到目前为止,我已经多次阅读 Xtext 文档,但我能找到的只是关于终端语句的顺序依赖性的简要说明。
调试解析器如何解释我的语法的好方法是什么?是否有类似于转储
IFormattableDocument
到控制台的东西,但对于词法分析器/解析器/其他?最后,从 Xtext 的角度来看,解决这个问题的最佳方法是什么。我应该研究自定义数据类型,还是可以在纯 Xtext 中表达?
我正在寻求了解基本原则。
更新
这当然很奇怪。我试图暂时跳过这一点并实施规范的下一部分。
; The narrative is identified by keyword "Narrative:" (or equivalent in I18n-ed locale),
; It is followed by the narrative elements
Narrative:= "Narrative:" ( InOrderTo AsA IWantTo | AsA IWantTo SoThat ) ;
我实际上无法独自完成这项工作。但是,当我取消注释原始代码并一起尝试时,它可以工作!
@Test
def void narrativeOnly() {
var story = _th.parse('''
Narrative:
In order check reports
As a Developer
I want to workin with todos using examples
''')
assertThat(story, notNullValue())
}
@Test
def void descriptionOnly() {
// Multi-line
var story = _th.parse('''
The quick brown fox
Jumps over the lazy dog
''')
assertThat(story, notNullValue())
assertThat(
story.description,
equalTo('''
The quick brown fox
Jumps over the lazy dog
''')
)
// Single-line description
story = _th.parse('''
The quick brown fox
''')
assertThat(
story.description,
equalTo("The quick brown fox\n")
)
}
grammar org.agileware.natural.jbehave.JBehave hidden (WS)
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
generate jbehave "http://www.agileware.org/natural/jbehave"
// Story
////
// The story describes a feature via description, narrative and a set of scenarios
// Story := Description? Meta? Narrative? GivenStories? Lifecycle? Scenario+ ;
Story:
description=Description?
narrative=Narrative?
;
// Narrative
////
// The narrative is identified by keyword "Narrative:" (or equivalent in I18n-ed locale),
// It is followed by the narrative elements
// Narrative:= "Narrative:" ( InOrderTo AsA IWantTo | AsA IWantTo SoThat ) ;
// The narrative element content is any sequence of characters that do not match a narrative starting word
// NarrativeElementContent := ? Any sequence of NarrativeCharacter that does not match NarrativeStartingWord ? ;
Narrative:
'Narrative:'
inOrderTo=InOrderTo
asA=AsA
wantTo=IWantTo
;
// InOrderTo:= "In order to" NarrativeElementContent ;
InOrderTo:
IN_ORDER_TO (WORD) (WORD)* EOL+;
// AsA:= "As a" NarrativeElementContent ;
AsA:
AS_A (WORD) (WORD)* EOL+;
// IWantTo:= "I want to" NarrativeElementContent ;
IWantTo:
I_WANT_TO (WORD) (WORD)* EOL+;
// SoThat:= "So that" NarrativeElementContent ;
SoThat:
SO_THAT (WORD) (WORD)* EOL+;
// The Description is expressed by any sequence of words that must not contain any keywords at start of lines.
// Description := (Word Space?)* ;
Description:
((WORD) (WORD)* EOL+)+
;
// Key Words
////
//terminal NON_KEYWORD:
// !(IN_ORDER_TO
// | AS_A
// | I_WANT_TO
// | SO_THAT
// | SCENARIO
// | GIVEN_STORIES
// | GIVEN
// | THEN
// | WHEN
// | AND
// )
//;
terminal IN_ORDER_TO: "In order to";
terminal AS_A: "As a";
terminal I_WANT_TO: "I want to";
terminal SO_THAT: "So that";
//terminal SCENARIO: "Scenario:";
//terminal GIVEN_STORIES: "GivenStories:";
//terminal GIVEN: "Given";
//terminal WHEN: "When";
//terminal THEN: "Then";
//terminal AND: "And";
// Common Terminals
////
terminal WORD: (LETTER)(LETTER|DIGIT)*;
terminal fragment LETTER: ('a'..'z'|'A'..'Z');
terminal fragment DIGIT: ('0'..'9');
terminal WS: (' '|'\t')+;
terminal EOL: NL;
terminal fragment NL: ('\r'? '\n');
我猜这可以解决#3,但是偶然到达那里有点违背了目的。我现在将接受任何可以指出或向我描述导致我所描述的行为的基本原则的答案。
为什么我不能只匹配一组随机的单词?定义narrative
赋值以及description
赋值Story
如何改变解析器解释语法的方式?
解决方案
我已经能够使用ANTLRWorks回答我的所有 3 个问题,这是一个可执行 jar 形式的 gui 工具,其明确目的是调试、可视化和帮助人们理解解析器的行为。
要使用 Xtext 进行此操作,需要添加以下 mwe2 生成器:
language = StandardLanguage {
// ...
parserGenerator = {
debugGrammar = true
}
}
然后在 ANTLRWorks 工具中打开生成的调试文件并点击“Bug”(调试)图标。该文件应位于src-gen/*/parser/antlr/internal/DebugInternal*.g
来源:https ://blogs.itemis.com/en/debugging-xtext-grammars-what-to-do-when-your-language-is-ambiguous
推荐阅读
- linux - 有没有办法在linux中创建一个“.exe”?
- google-chrome - Google Docs API 在不知道 id 的情况下查看 Docs
- python - 如何使用 tkinter 在条目列表上实现滚动条?
- r - glmer中多项混合效应模型的估计
- windows - 如何在 Windows 10 上安装 ZeroMQ?
- python-3.x - 为什么我的 zip 函数输出的比最短的迭代次数多?
- javascript - 使用javascript计算表单
- python - 用以前的安装替换 Anaconda 包
- ios - 在什么情况下 SKPaymentTransaction.transactionIdentifier 与验证收据的 transaction_id 相同?
- sql - MS Access VBA 调用子程序在第一遍有效,但在第二遍无效