代码之家  ›  专栏  ›  技术社区  ›  Artyom Sokolov

ANTLR将字符串的一部分视为关键字

  •  2
  • Artyom Sokolov  · 技术社区  · 14 年前

    我现在正在为自己学习ANTLR。首先我决定写最简单的语法。有带有指令的纯文本文件:

    pid = something.pid
    log = something.log
    

    我写的语法是:

    grammar TestGrammar;
    
    options {
      language = Java;
    }
    
    @header {
      package test.antlr;
    }
    
    @lexer::header {
      package test.antlr;
    }
    
    program
      : directive+
      ;
    
    directive
      : pid
      | log
      ;
    
    pid
      : PID EQ (WORD|POINT)+
      ;
    
    log
      : LOG EQ (WORD|POINT)+
      ;
    
    WS: ( ' '
        | '\t'
        | '\r'
        | '\n'
        ) {$channel=HIDDEN;}
        ;
    
    PID
      : 'pid'
      ;
    
    LOG
      : 'log'
      ;
    
    EQ
      : '='
      ;
    
    POINT
      : '.'
      ;
    
    WORD
      : ('a'..'z'|'A'..'Z'|'_')+
      ;
    

    我觉得我在某个地方犯了个错误,安特尔证明了 MismatchedTokenException . 它能治疗某些东西。 pid控制 作为一个 directive 并抛出一个例外。

    但是我不明白我做错了什么。任何帮助都将不胜感激。

    谢谢。

    1 回复  |  直到 14 年前
        1
  •  2
  •   Bart Kiers    14 年前

    lexer是一个非常简单的对象:在不受解析器干扰的情况下,它标记输入源。所以,输入:

    pid = something.pid
    

    标记为:

    PID EQ WORD POINT WORD
    

    但作为:

    PID EQ WORD POINT PID
    

    这就是为什么你的规则:

    pid
      : PID EQ (WORD|POINT)+
      ;
    

    比赛 "pid = something." 离开第二个 "pid" 在令牌流中,应为 EQ atfer it(因此是例外)。

    一个可能的解决方法是这样做:

    pid
      : PID EQ (word|POINT)+
      ;
    
    log
      : LOG EQ (word|POINT)+
      ;
    
    word
      : WORD
      | PID
      | LOG 
      ;
    

    或者做一些类似的事情:

    pid
      : PID EQ FULL_WORD
      ;
    
    log
      : LOG EQ FULL_WORD
      ;
    
    // ...
    
    FULL_WORD
      : WORD (POINT WORD)*
      ;
    
    // ...