java - ANTLR 将部分字符串视为关键字

标签 java antlr

我目前正在自学 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'|'_')+
  ;

我觉得我在某处犯了一个错误,ANTLR 证明抛出了 MismatchedTokenException。它将 something.pid 视为 指令 并抛出异常。

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

谢谢。

最佳答案

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

pid = something.pid

标记为:

PID EQ WORD POINT WORD

但是作为:

PID EQ WORD POINT PID

这就是为什么你的规则:

pid
  : PID EQ (WORD|POINT)+
  ;

匹配 "pid = something." 并将第二个 "pid" 留在 token 流中,期望 EQ 赋予它(因此异常(exception))。

一个可能的解决办法是做这样的事情:

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)*
  ;

// ...

关于java - ANTLR 将部分字符串视为关键字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4305473/

相关文章:

java - testNG 测试类可以从另一个类扩展吗?

java - ANTLR/java/SDK 生成-编译-执行序列在 Windows10 命令窗口中失败

java - Spring 单例范围

java - Socket OutputStream(BufferedWriter) 不刷新消息

java - 如何简化 token 预测 DFA?

java - Antlr 4 中的匹配输入替代方案

antlr - "!"、 "^"和 "$"在 Antlr3 中是否有特殊含义?

java - 在JAVA中使用ANTLR从字符串中获取表达式

java - 在 java 中包含框架 - IntelliJ

java - 以编程方式配置 p2 更新存储库