首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >解析键值IPV6对

解析键值IPV6对
EN

Stack Overflow用户
提问于 2018-03-15 14:22:46
回答 1查看 198关注 0票数 2

我有以下输入格式IP:FE80:CD00::211E:729C进行解析。

解析后,我希望Key为IP:,value为FE80:CD00::211E:729C

我定义了以下语法

代码语言:javascript
复制
grammar IPV6;
keyValue  : KEY ip_v6_address;

ip_v6_address
 : h16 ':' h16 ':' h16 ':' h16 ':' h16 ':' h16 ':' ls32
 | '::' h16 ':' h16 ':' h16 ':' h16 ':' h16 ':' ls32
 | h16? '::' h16 ':' h16 ':' h16 ':' h16 ':' ls32
 | ((h16 ':')? h16)? '::' h16 ':' h16 ':' h16 ':' ls32
 | (((h16 ':')? h16 ':')? h16)? '::' h16 ':' h16 ':' ls32
 | ((((h16 ':')? h16 ':')? h16 ':')? h16)? '::' h16 ':' ls32
 | (((((h16 ':')? h16 ':')? h16 ':')? h16 ':')? h16)? '::' ls32
 | ((((((h16 ':')? h16 ':')? h16 ':')? h16 ':')? h16 ':')? h16)? '::' h16
;

h16
 : hexdig hexdig hexdig hexdig
 | hexdig hexdig hexdig
 | hexdig hexdig
 | hexdig
;

hexdig
 : digit
 | (A | B | C | D | E | F)
;

ls32
 : h16 ':' h16
 | ip_v4_address
;

ip_v4_address
 : dec_octet '.' dec_octet '.' dec_octet '.' dec_octet
;

dec_octet
 : digit
 | non_zero_digit digit
 | D1 digit digit
 | D2 (D0 | D1 | D2 | D3 | D4) digit
 | D2 D5 (D0 | D1 | D2 | D3 | D4 | D5)
;

digit
 : D0
 | non_zero_digit
;

non_zero_digit
 : D1
 | D2
 | D3
 | D4
 | D5
 | D6
 | D7
 | D8
 | D9
;

D0 : '0';
D1 : '1';
D2 : '2';
D3 : '3';
D4 : '4';
D5 : '5';
D6 : '6';
D7 : '7';
D8 : '8';
D9 : '9';

A : 'a'|'A';
B : 'b'|'B';
C : 'c'|'C';
D : 'd'|'D';
E : 'e'|'E';
F : 'f'|'F';

KEY: '['? STRING SPACE* STRING']'?':';

fragment SPACE : ' ';
fragment STRING: [a-zA-Z0-9/._-]+;
WS  : [ \t\r\n] + -> skip;

在运行上面的例子之后,上面的语法给出了以下标记

代码语言:javascript
复制
[TOKENS]
  KEY                  'IP:'
  KEY                  'FE80:'
  KEY                  'CD00:'
  ':'                  ':'
  KEY                  '211E:'
  D7                   '7'
  D2                   '2'
  D9                   '9'
  C                    'C'
  EOF                  '<EOF>'
[PARSE-TREE]
line 1:3 mismatched input 'FE80:' expecting {'::', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', A, B, C, D, E, F}
  (keyValue IP: 
    (ip_v6_address FE80: CD00: : 211E: 7 2 9 C))

我希望将键值对作为输出,但不确定我是否编写了正确的语法。我面临的问题是,分隔符':‘也可以在值中退出。有什么建议如何修正语法吗?

EN

回答 1

Stack Overflow用户

发布于 2018-03-15 16:16:08

它不能工作,因为重叠的词法分析器规则(多个规则匹配相同的输入)。

来自FE80:F字符未标记为十六进制数字( F词法分析器规则)。但是,整个块FE80:被标记为一个KEY令牌。

您必须意识到lexer独立于解析器运行。解析器可能试图匹配某个标记,词法分析器不会“监听”这个标记。词法分析器遵循两个非常简单的规则:

  1. 尝试为单个令牌
  2. 匹配尽可能多的字符当两个或多个令牌匹配相同的字符时,首先定义的规则将"wins"

由于这些规则,输入F被标记化为F令牌,但是像FE这样的输入被标记化为KEY令牌。

解决方案是将KEY的构造从词法分析器移动到key解析器规则,如下所示:

代码语言:javascript
复制
grammar IPV6;

key_value
 : key ':' ip_v6_address
 ;

key
 : '[' string ']'
 | string
 ;

ip_v6_address
 : h16 ':' h16 ':' h16 ':' h16 ':' h16 ':' h16 ':' ls32
 | '::' h16 ':' h16 ':' h16 ':' h16 ':' h16 ':' ls32
 | h16? '::' h16 ':' h16 ':' h16 ':' h16 ':' ls32
 | ((h16 ':')? h16)? '::' h16 ':' h16 ':' h16 ':' ls32
 | (((h16 ':')? h16 ':')? h16)? '::' h16 ':' h16 ':' ls32
 | ((((h16 ':')? h16 ':')? h16 ':')? h16)? '::' h16 ':' ls32
 | (((((h16 ':')? h16 ':')? h16 ':')? h16 ':')? h16)? '::' ls32
 | ((((((h16 ':')? h16 ':')? h16 ':')? h16 ':')? h16 ':')? h16)? '::' h16
 ;

h16
 : hexdig hexdig hexdig hexdig
 | hexdig hexdig hexdig
 | hexdig hexdig
 | hexdig
 ;

hexdig
 : digit
 | (A | B | C | D | E | F)
 ;

ls32
 : h16 ':' h16
 | ip_v4_address
 ;

ip_v4_address
 : dec_octet '.' dec_octet '.' dec_octet '.' dec_octet
 ;

dec_octet
 : digit
 | non_zero_digit digit
 | D1 digit digit
 | D2 (D0 | D1 | D2 | D3 | D4) digit
 | D2 D5 (D0 | D1 | D2 | D3 | D4 | D5)
 ;

digit
 : D0
 | non_zero_digit
 ;

non_zero_digit
 : D1 | D2 | D3 | D4 | D5 | D6 | D7 | D8 | D9
 ;

string
 : (STRING_ATOM | hexdig)+
 ;

D0 : '0';
D1 : '1';
D2 : '2';
D3 : '3';
D4 : '4';
D5 : '5';
D6 : '6';
D7 : '7';
D8 : '8';
D9 : '9';

A : [aA];
B : [bB];
C : [cC];
D : [dD];
E : [eE];
F : [fF];

STRING_ATOM : [g-zG-Z/._-];

WS : [ \t\r\n] + -> skip;

生成以下解析树:

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

https://stackoverflow.com/questions/49292773

复制
相关文章

相似问题

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