首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >数和十六进制的Antlr规则

数和十六进制的Antlr规则
EN

Stack Overflow用户
提问于 2021-11-02 23:42:33
回答 2查看 40关注 0票数 1

我正在为libretro数据文件编写一个解析器。这是我第一次使用antlr语法和解析器,所以请原谅我缺乏最佳实践。

但是,antlr是多么的酷,真不敢相信让我走到这一步是那么简单:)

代码语言:javascript
复制
game (
    name "10-Yard Fight (World, set 1)"
    year "1983"
    developer "Irem"
    rom ( name 10yard.zip size 62708 crc 8f401426 md5 040dc0827e184b8da9b91499f96c1fce sha1 8b15a2e54e9fdded3d61205bac6535ccc7b41271 )
)

我的语法是:

代码语言:javascript
复制
grammar Datafile;

game: GAME LP
        gameBody+
        RP;

gameBody: gameName
          | year
          | developer
          | rom+
          ;

rom: ROM LP
          size
        | crc
        | md5
        | serial
        | sha1
        RP;
size: SIZE NUMBER;
crc: CRC HEX;
md5: MD5 HEX;
sha1: SHA1 HEX;
serial: SERIAL STRING;

gameName: NAME STRING;
year: YEAR STRING;
developer: DEVELOPER STRING;

//keywords
GAME: 'game';
ROM: 'rom';
NAME: 'name';
YEAR: 'year';
DEVELOPER: 'developer';
SIZE: 'size';
CRC: 'crc';
MD5: 'md5';
SHA1: 'sha1';
SERIAL: 'serial';
LP: '(';
RP: ')';

STRING : '"' ( '\\"' | . )*? '"';
WS  :   [ \t\r\n\u000C]+ -> skip;

NUMBER: DIGIT+ ([.,] DIGIT+)?;

HEX: [a-fA-F0-9]+;

fragment LETTER: [A-Za-z];
fragment DIGIT: [0-9];

因此,我并不是非常严格地通过使用通用字符串规则来捕获年份/开发人员之类的内容,因为有时日期是数据集中的字符串,我会在解析器逻辑上处理它们。

但我遇到了十六进制值的问题。因为它们不像在某些语言中那样通过0x前缀进行转义。发生的情况是,如果我有一个crc 0001100,那么解析器会将其捕获为NUMBER而不是HEX

有没有办法解决这个问题,或者我只是把sizecrc sha1 md5都映射成十六进制,然后在解析器上处理解析逻辑?

我遇到的另一个问题是试图找出如何捕获文件名(rom -> name),它可以是任何有效的文件名,但我无法编写捕获它的规则。

希望任何人都能加入进来:)

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-11-03 02:08:11

如果没有一些十六进制数字的特殊语法,Lexer将无法识别它们。你只知道一些东西应该被上下文解释为十六进制数字。解析器规则为您提供上下文。

所以:

代码语言:javascript
复制
hexNumber: HEX | NUMBER;
crc: CRC hexNumber;
md5: MD5 hexNumber;
sha1: SHA1 hexNumber;

现在,您的解析树中将有一个HexNumberContext,并且您将知道如何解释它。

你也可以这样做:

代码语言:javascript
复制
crc: CRC ( HEX | NUMBER)

您可以同时尝试这两种方法,并查看生成的解析树和上下文类,看看您更喜欢哪一种。

票数 2
EN

Stack Overflow用户

发布于 2021-11-17 19:02:53

我认为您可以使用LEXER模式强制将数字解析为十六进制数字。我对词法分析器模式不太满意,因为我还是一个ANTLR4新手,但我想到了这样的东西:

代码语言:javascript
复制
CRC : 'crc' ->pushMode(HexOnly);
MD5 : 'md5' ->pushMode(HexOnly);
SHA1: 'sha1' ->pushMode(HexOnly); 
...
mode HexOnly;
HEX1: [a-fA-F0-9]+ ->popMode;
... any other HexOnly mode thing

在示例中,我使用了HEX1,因为我发现当我拥有不可改变的模式时,我有一个令牌类型,它也在其他地方使用,并且由于我仍然在学习"ANTLR4“,所以我将以自己的方式来实现一个解决方案,直到我学到一个优雅的解决方案。

我发现到目前为止,Lexer模式还不够优雅。很酷,但带着行李来。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69818123

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档