antlr - 在 Xtext/ANTLR 中终止多行文本块
问题描述
我开始掌握 Xtext,但我仍然在用多个换行符分隔语义部分时遇到了一些麻烦。
grammar org.example.dsl.MyDsl hidden(WS)
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
generate words "http://www.example.org/dsl
Document:
sections+=Paragraph+
;
Paragraph:
lines+=Text+
( -> NL)
;
Text:
value=WordGroup
NL
;
WordGroup: SIMPLE_WORD+;
terminal SIMPLE_WORD:
('0'..'9' | 'a'..'z' | 'A'..'Z')
('0'..'9' | 'a'..'z' | 'A'..'Z' | '-' | '_' | '.')*
;
terminal NL: ('\r'? '\n');
terminal WS: (' ' | '\t');
还行吧...
@Test
def void happyPath() {
val model = parseHelper.parse('''
The quick brown fox
Jumps over the lazy dog
''')
assertThat(model, notNullValue())
assertThat(model.eResource.errors, equalTo(#[]))
assertThat(model.sections.size(), equalTo(1))
assertThat(model.sections.get(0).lines.size(), equalTo(2))
// It works!
}
但这不是...
@Test
def void noTrailingNewlines() {
val model = parseHelper.parse('''
The quick brown fox
Jumps over the lazy dog
''')
assertThat(model, notNullValue())
assertThat(model.eResource.errors, equalTo(#[]))
// Fail ^^^ XtextSyntaxDiagnostic: null:2 mismatched input '<EOF>' expecting RULE_NL
assertThat(model.sections.size(), equalTo(1))
assertThat(model.sections.get(0).lines.size(), equalTo(2))
}
两者都应该是有效的可解析文本,但我不能让它接受单个 NL,如果那是找到的最后一个字符。
我尝试了明显的( -> NL?)
...
Paragraph:
lines+=Text+
( -> NL?)
;
...而且这实际上确实导致测试通过,只是现在我有 ANTLR 警告。
正如我所怀疑的那样,这只是解决了问题......
@Test
def void multipleParagraphs() {
val model = parseHelper.parse('''
The quick brown fox
Jumps over the lazy dog
But only on days that end in Y
''')
assertThat(model, notNullValue())
assertThat(model.eResource.errors, equalTo(#[]))
assertThat(model.sections.size(), equalTo(2)) //Expected: <2> but: was <1>
}
解决方案
我们有一个赢家!
非常感谢@christian-dietrich 和@redknite,他们非常耐心地帮助我解决了这个问题。
Document:
sections+=Paragraph
(NL sections+=Paragraph)*
;
Paragraph:
lines+=Text+
;
Text:
value=WordGroup
NL
;
@Test
def void singleParagraph() {
val model = parseHelper.parse('''
The quick brown fox
Jumps over the lazy dog
''')
assertThat(model, notNullValue())
assertThat(model.eResource.errors, equalTo(#[]))
val doc = model.document
assertThat(doc, notNullValue())
assertThat(doc.sections.size(), equalTo(1))
assertThat(doc.sections.get(0).lines.size(), equalTo(2))
}
@Test
def void multiParagraph() {
val model = parseHelper.parse('''
The quick brown fox
Jumps over the lazy dog
But only on days that end in Y
''')
assertThat(model, notNullValue())
assertThat(model.eResource.errors, equalTo(#[]))
val doc = model.document
assertThat(doc, notNullValue())
assertThat(doc.sections.size(), equalTo(2))
assertThat(doc.sections.get(0).lines.size(), equalTo(2))
}
两个都过!
推荐阅读
- angular - 如何将消息推送给每个用户的 UserAdmin
- c# - 由于 JSON 原因,如何将元素附加到 C# 数组?
- visual-studio - 当我们在 Visual Studio SSIS 项目中点击调试按钮时——它是在 32 位还是 64 位模式下运行——并且 32 位提供程序是否与 64 位运行模式兼容?
- c++ - c++中的this指针
- flutter - Flutter Null 检查运算符用于空值
- webpack - 由于缺少依赖关系,带有 babel 的 Yarn 2 monorepo 无法构建,但它正在查看错误的 package.json
- python - Django UserCreationForm 自定义
- datastage - 使用 RTP 时遍历作业中的字段
- python-3.x - AioHttp 获取请求上的 400 - 标头中的字符无效
- xcode - 未找到可执行文件。xxx.app 不是可执行文件的有效路径