用不同的单词类型解析句子

时间:2011-07-29 08:56:33

标签: antlr whitespace grammar words sentence

我正在寻找分析两种句子的语法 表示由空格分隔的单词:

  1. ID1:包含不以数字开头的单词的句子
  2. ID2:包含不以数字和数字开头的单词的句子
  3. 基本上,语法的结构应该看起来像

    ID1 separator ID2  
    
    ID1: Word can contain number like Var1234 but not start with a number  
    
    ID2: Same as above but 1234 is allowed  
    
    separator: e. g. '='
    

    @Bart
    我只是尝试添加两个令牌'_''"'作为词法规则Special,以便稍后在词法规则Word中使用。 即使我没有在下面的语法中使用Special,我在ANTLRWorks 1.4.2中也会出现以下错误:
    以下令牌定义永远不能匹配,因为先前的令牌匹配相同的输入:特殊
    但是当我在fragment之前添加 Special 时,我没有收到该错误。为什么?

    grammar Sentence1b1;
    
    tokens
    {
      TCUnderscore  = '_' ;
      TCQuote       = '"' ;
    }
    
    assignment
      :  id1 '=' id2
      ;
    
    id1
      :  Word+
      ;
    
    id2
      :  ( Word | Int )+
      ;
    
    Int
      :  Digit+
      ;
    
    // A word must start with a letter
    Word
      :  ( 'a'..'z' | 'A'..'Z') ('a'..'z' | 'A'..'Z' | Digit )*
      ;
    
    Special
      : ( TCUnderscore | TCQuote )
      ;
    
    Space
      :  ( ' ' | '\t' | '\r' | '\n' ) { $channel = HIDDEN; }
      ;
    
    fragment Digit
      :  '0'..'9'
      ;
    

    Lexer-rule Special将在词法分析器Word中使用:

    Word
      :  ( 'a'..'z' | 'A'..'Z' | Special ) ('a'..'z' | 'A'..'Z' | Special | Digit )*
      ;
    

2 个答案:

答案 0 :(得分:1)

我会选择这样的事情:

grammar Sentence;

assignment
  :  id1 '=' id2
  ;

id1
  :  Word+
  ;

id2
  :  (Word | Int)+
  ;

Int
  :  Digit+
  ;

// A word must start with a letter
Word
  :  ('a'..'z' | 'A'..'Z') ('a'..'z' | 'A'..'Z' | Digit)*
  ;

Space
  :  (' ' | '\t' | '\r' | '\n') {skip();}
  ;

fragment Digit
  :  '0'..'9'
  ;

将解析输入:

  

Word可以包含类似Var1234的数字,但不能以数字开头=与上述相同但允许1234

如下:

enter image description here

修改

为了将lexer规则很好地打包在一起,我将它们全部放在语法的底部,而不是部分地放在tokens { ... }块中,我只用它来定义“虚构标记”(用于创建AST) ):

// wrong!
Special      : (TCUnderscore | TCQuote);
TCUnderscore : '_';
TCQuote      : '"';

现在,根据上述规则,TCUnderscoreTCQuote永远不会成为令牌,因为当词法分析器偶然发现_"时,{{1}令牌已创建。或者在这种情况下:

Special

永远不会创建// wrong! TCUnderscore : '_'; TCQuote : '"'; Special : (TCUnderscore | TCQuote); 令牌,因为词法分析器会首先创建SpecialTCUnderscore令牌。因此错误:

TCQuote

如果您使The following token definitions can never be matched because prior tokens match the same input: ... TCUnderscore成为TCQuote规则,则不会出现此问题,因为fragment规则仅“提供”其他词法规则。所以这有效:

fragment

此外,// good! Special : (TCUnderscore | TCQuote); fragment TCUnderscore : '_'; fragment TCQuote : '"'; 规则可能永远不会在任何解析器规则中“可见”(词法分析器永远不会创建fragmentTCUnderscore令牌!)。

TCQuote

答案 1 :(得分:0)

我不确定这是否符合您的需求,但在我的帖子中有Bart的帮助 ANTLR - identifier with whitespace 我来到这个语法:

grammar PropertyAssignment;

assignment
    : id_nodigitstart '=' id_digitstart EOF
    ;

id_nodigitstart
    :   ID_NODIGITSTART+
    ;

id_digitstart
    :   (ID_DIGITSTART|ID_NODIGITSTART)+
    ;

ID_NODIGITSTART
    :   ('a'..'z'|'A'..'Z') ('a'..'z'|'A'..'Z'|'0'..'9')*
    ;           

ID_DIGITSTART
    :   ('0'..'9'|'a'..'z'|'A'..'Z')+
    ;

WS  :   (' ')+ {skip();}
    ;

“a name = my 4value”有效,而“4a name = my 4value”会导致异常。