出于好奇心的缘故,我正在学习ANTLR,尤其是4,我正在尝试创建一个简单的语法 . 我选择NES(Nintentdo娱乐系统)Game Genie文件是第一次尝试 . 让我们说,这里有一个侏罗纪公园的Game Genie文件示例,该文件位于Internet的某个地方:
GZUXXKVS Infinite ammo on pick-up
PAVPAGZE More bullets picked up from small dinosaurs
PAVPAGZA Fewer bullets picked up from small dinosaurs
GZEULOVK Infinite lives--1st 2 Levels only
ATVGZOSA Immune to most attacks
VEXASASA + VEUAXASA 3-ball bolas picked up
NEXASASA + NEUAXASA Explosive multi-shots
这是我正在研究的语法 .
grammar NesGameGenie;
all: lines EOF;
lines: (anyLine? EOL+)* anyLine?;
anyLine: codeLine;
codeLine: code;
code: CODE (PLUS? CODE)*;
CODE: SHORT_CODE | LONG_CODE;
fragment SHORT_CODE: FF FF FF FF FF FF;
fragment LONG_CODE: FF FF FF FF FF FF FF FF;
fragment FF: [APZLGITYEOXUKSVN];
COMMENT: COMMENT_START NOEOL -> skip;
COMMENT_START: [#;];
EOL: '\r'? '\n';
PLUS: '+';
WS: [ \t]+ -> skip;
fragment NOEOL: ~[\r\n]*;
好吧,这简直荒谬,但它仍然有两个我能看到的问题:
-
作弊描述导致识别错误,如
line 1:16 token recognition error at: 'In'
,因为没有为语法提供描述规则 . -
将
#
符号添加到描述中可能会导致忽略其余部分到行尾 . 至少,AAAAAA Player #1 ammo
仅报告Player
和#1 ammo
遗憾地被解析为评论,但我认为一旦引入描述规则就可以修复它 .
我之前尝试添加描述规则导致了很多错误,我发现了一个非错误但仍不是一个好的解决方案:
...
codeLine: code description?;
...
description: PRINTABLE+;
...
PRINTABLE: [\u0020-\uFFFE];
...
不幸的是,每个字符都被解析为单个 PRINTABLE
,而我正在寻找的是一个 description
规则来匹配arbirtrary文本,直到包含空格的行(或文件)结尾,但是左右修剪 . 如果我将 +
添加到 PRINTABLE
的末尾,则整个文档被视为无效 . 我猜_1174212_可能会以某种方式安全地内联到 description
规则,但 description: ('\u0020' .. '\uFFFE')+;
捕获的方式更多 .
如何声明 description
规则,让它在代码之后将所有字符捕获到行尾,但仅在左右两侧修剪空格( [ \t]
)?简单来说,我会有一个语法解析成类似的东西(包括 #
字符不解析它作为注释):
code=..., description="Infinite ammo on pick-up"
code=..., description="More bullets picked up from small dinosaurs"
code=..., description="Fewer bullets picked up from small dinosaurs"
code=..., description="Infinite lives--1st 2 Levels only"
code=..., description="Immune to most attacks"
code=..., description="3-ball bolas picked up"
code=..., description="Explosive multi-shots"
还有一点,我正在使用:
-
IntelliJ IDEA 2016.1.1 CE
-
IJ插件:ANTLR v4语法插件1.8.1
-
IJ插件:ANTLRWorks 1.3.1
2 回答
实际上很简单,只需使用词法模式 . 一旦击中某些令牌,请更改模式 .
这是词法分析器语法,解析器很容易基于它(文件名为
NesGameGenieLexer.g4
):我假设
+
不能在评论中 . 如果您使用ANTLRWorks lexer调试器,您可以很好地突出显示所有令牌类型和令牌模式 .这是解析器语法(文件名为
NesGameGenieParser.g4
):在这里我假设
CODE
只是PLUS
之前的字符集,但很明显这很容易改变:)我花了整个不眠之夜,没有多少时间睡觉,我似乎设法写了词法分析器和解析器语法 . 无需多解释,请参阅源代码中的注释,简而言之:
词法分析员:
解析器:
它看起来比我想象的要复杂得多,但它似乎完全按照我想要的方式工作 . 另外,我不确定上面的语法是否真的写得好而且惯用 . 感谢@cantSleepNow给出了模式的想法 .