`

用ANTLR分析简单的十六进制格式字符串

 
阅读更多

 

用ANTLR分析简单的十六进制格式字符串

 

一、问题:

假设现在有一个16进制格式的文本字符串,如下:

 

 

0x00, 0x06, 0x6E, 0x61, 0x6e, 0x61, 0x6d, 0x69,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02,
 

目标是解析其中的含义。

其中

0x00, 0x06, 0x6E, 0x61, 0x6e, 0x61, 0x6d, 0x69,

表示一个长度为6的字符串

0x6E, 0x61, 0x6e, 0x61, 0x6d, 0x69即"nanami"

而0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02表示两个32位无符号整数1和2。

 

二、思路:

如果用ANTLR的.g文件描述,大概是:

 

 

packet
: str16 uint32 uint32
;
 

意思是依次读取变长字符串、32位整数、32位整数。

我的想法是用ANTLR的谓词语法处理变长的字符串

完整的.g文件如下:

 

 

/*
Text :
0x00, 0x06, 0x6E, 0x61, 0x6e, 0x61, 0x6d, 0x69,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02,

Start Rule : 
packets

Output	:
username : nanami
x : 1
y : 2
*/

grammar Binary;

@header {
}

@members {
	private int str_num = 0;
	private int str_length = 0;
}

packets
: (packet (',')? NEWLINE* )*
;

packet
: 
  username=str16 {System.out.println("username : " + $username.value);}
  x=uint32 {System.out.println("x : " + x);}
  y=uint32 {System.out.println("y : " + y);}
;

str16 returns [String value]
@init { str_num = 0; StringBuffer sb = new StringBuffer();}
@after { value = sb.toString();}
: s1=ushort16 {str_length = $s1.value;}
  (
	{str_num < str_length}?=>(
	   b1=byte8 {sb.append((char)$b1.value);}  
	   {str_num++;}
	)
  )*
;

byte8 returns [int value]
@init { value = 0; }
@after {}
: b1=BYTE8 
  {
	if ($b1.text.startsWith("0x")) {
	    value |= Integer.parseInt($b1.text.substring(2), 16);
	}
  }
  ',' NEWLINE?
;


ushort16 returns [int value]
@init { value = 0;}
@after {}
: b1=BYTE8 
  {
	if ($b1.text.startsWith("0x")) {
	    value |= Integer.parseInt($b1.text.substring(2), 16) << 8;
	}
  } ',' NEWLINE?
  b2=BYTE8 
  {
	if ($b2.text.startsWith("0x")) {
	    value |= Integer.parseInt($b2.text.substring(2), 16);
	}
  } ',' NEWLINE?
;

uint32 returns [int value]
@init { value = 0; }
@after {}
: b1=BYTE8 
  {
	if ($b1.text.startsWith("0x")) {
	    value |= Integer.parseInt($b1.text.substring(2), 16) << 24;
	}
  } ',' NEWLINE?
  b2=BYTE8 
  {
	if ($b2.text.startsWith("0x")) {
	    value |= Integer.parseInt($b2.text.substring(2), 16) << 16;
	}
  } ',' NEWLINE?
  b3=BYTE8 
  {
	if ($b3.text.startsWith("0x")) {
	    value |= Integer.parseInt($b3.text.substring(2), 16) << 8;
	}
  } ',' NEWLINE?
  b4=BYTE8 
  {
	if ($b4.text.startsWith("0x")) {
	    value |= Integer.parseInt($b4.text.substring(2), 16);
	}
  } ',' NEWLINE?
;

// LEXER

BYTE8: '0x' HexDigit HexDigit;
fragment
HexDigit: ('0'..'9'|'a'..'f'|'A'..'F');
WS: (' '|'\t'|'\u000C') {$channel=HIDDEN;};  
NEWLINE: ('\r')? '\n';
 

 

三、测试结果:

用ANTLRWorks测试,输入数据设置为

 

 

0x00, 0x06, 0x6E, 0x61, 0x6e, 0x61, 0x6d, 0x69,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02,
 

开始规则(Start Rule)设置为 packets

输出为:

 

 

username : nanami
x : 1
y : 2
 

 

四、总结:

相比起其它语言(诸如C的struct和Erlang的binary数据类型匹配),

用ANTLR的BNF语法处理二进制的解码会比较麻烦(需要先转换为文本型的字符串),

而且灵活性很小(虽然可以用谓词分析变长的字符串,但处理更复杂的结构会很困难)。

不过个人觉得这个问题对于了解ANTLR的语法和ANTLRWorks的测试环境很有帮助。

 

分享到:
评论

相关推荐

    用Antlr 分析布尔表达式的例子

    用antlr分析处理布尔表达式的例子,包括:语法定义.g文件;生成的词法分析和语法分析器;带有图形界面的分析器调用代码。 其中带有GUI的分析器ParserFrame,可以用于任何.g文件生成的词法、语法分析器,只要通过改变...

    编译原理课程设计有关antlr的词法分析和语法分析

    《编译原理》课程设计报告主要涉及ANTLR这一强大的分析器生成工具,其在词法分析和语法分析方面具有重要作用。ANTLR能够帮助开发者理解和实现编译器的关键组成部分,包括词法分析器(Lexer)、解析器(Parser)和树...

    Antlr教程文法分析器

    在上述示例中,输入字符串 "Terence\n" 会被Lexer处理成一个 NAME Token(Terence)和一个 NEWLINE Token。Parser 然后处理这个NAME Token,输出 "Hi there, Terence"。 总的来说,Antlr 提供了一种高效且灵活的...

    CalcANTLR:从发明的编程语言到使用ANTLR和自定义堆栈机的二进制文件

    它是如何工作的我正在使用ANTLR生成带有语法文件的Java词法分析器和解析器。 “计算器语言”由数字,运算符,空格,方括号组成...我构建的语法的目的是将计算器语言转换为堆栈机器语言。然后,我们可以使用src / ...

    ANTLR

    ANTLR(ANother Tool for Language Recognition)是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件。它广泛应用于构建语言、工具和框架,包括SQL解析器、XML处理器以及各类编程语言的...

    antlr java语法分析程序

    ANTLR通过提供一个简单的语法描述语言(Grammar)让开发者能方便地定义自己的语言规范,然后自动产生相应的词法分析器(Lexer)和语法分析器(Parser)。 ANTLR的工作流程通常包括以下几个步骤: 1. **定义语法规则...

    antlr 五分钟入门

    Test.java通常包含主程序,调用ANTLR生成的解析器处理输入字符串。Sentence.java可能包含ANTLR生成的解析器类,处理特定的语句结构。 6. **示例解析**:教程会通过一个具体的例子,如解析年龄相关的语句,来演示...

    antlr-2.7.7.jar和antlr-2.7.6.jar

    解析器处理输入的语法结构,而词法分析器则将输入的字符流转换为标记流,供解析器使用。ANTLR支持自定义语法规则,允许开发者定义复杂的语言结构。 在本案例中,我们有两个版本的ANTLR库:antlr-2.7.7.jar和antlr-...

    基于ANTLR4的CMM语言编译器

    总结来说,"基于ANTLR4的CMM语言编译器"项目展示了如何使用ANTLR4工具来设计和实现一个编译器,包括文法定义、词法分析、语法分析、语义分析和代码生成等关键步骤。对于学习编译原理和实践编译器开发的人员来说,这...

    antlr解析sql

    1. **词法分析**:ANTLR的词法分析器(Lexer)将输入的SQL字符串拆分成一系列的标记(Token),每个标记代表一个词汇单元,如关键字、标识符、数字、字符串等。 2. **语法分析**:ANTLR的解析器(Parser)基于词法...

    Antlr4 C++ 计算器

    ANTLR4 是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件。它广泛应用于构建语言、工具和框架,包括SQL、Java、C#、JavaScript、Python等。在本项目中,"Antlr4 C++ 计算器"是一个基于...

    antlr-2.7.7.jar.zip

    ANTLR(ANother Tool for Language Recognition)是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件。ANTLR被广泛应用于各种编程语言的编译器和解释器的构建,它能生成Java、C#、Python...

    antlr4-master 源码

    ANTLR4(ANTLR Version 4)是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件。它广泛应用于构建语言、工具和框架,包括SQL解析器、配置文件解析器、DSL(领域特定语言)以及各种编程...

    antlr-2.7.7.jar

    ANTLR(ANother Tool for Language Recognition)是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件。ANTLR被广泛应用于各种编程语言的编译器和解释器的构建,它能生成Java、C#、Python...

    Antlr3.Runtime_C#_

    ANTLR(ANother Tool for Language Recognition)是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件。它广泛应用于构建语言、工具和框架。ANTLR可以生成Java、C#、Python、JavaScript等...

    The Definitive ANTLR 4 Reference.pdf_antlr_

    ANTLR 4是一款强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件。它广泛应用于构建语言、工具和框架。从标题“Definitive ANTLR 4 Reference”和描述“ANTLR 4的权威参考”可以看出,这本书...

    开源项目-antlr-antlr4.zip

    ANTLR(ANother Tool for Language Recognition)是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件。ANTLR被广泛应用于构建语言、工具和框架,如SQL处理器、Java源码分析器、XML解析器...

Global site tag (gtag.js) - Google Analytics