【问题标题】:In ANTLR3, I need to discriminate between a 'comment' and a 'directive' (which looks like a comment)在 ANTLR3 中,我需要区分“评论”和“指令”(看起来像评论)
【发布时间】:2014-03-08 10:45:08
【问题描述】:

我对 ANTLR 还很陌生,但遇到了问题。

我正在尝试为一种语言编写一个语法,该语法包括单行 cmets 和以相同注释标识符开头的语言指令。例如:

--This is a comment.  What follows is a directive with a parameter
--directive:param

指令将始终采用该格式 - 两个破折号后跟一个命令、一个冒号和一个参数。

我想让词法分析器忽略实际注释(将其发送到隐藏通道),但对指令进行标记。我有以下词法分析器规则:

DCOMMAND    : DATABASE;
fragment DATABASE   : D A T A B A S E;
fragment COMMENTSTART   : '--';
LINE_COMMENT    : COMMENTSTART ~(DCOMMAND|('\n'|'\r')*) {$channel=HIDDEN;};
fragment A  : ('a'|'A');
fragment B  : ('b'|'B');
fragment C  : ('c'|'C');
fragment D  : ('d'|'D');
....

目前只有一个指令:“数据库”。 DCOMMAND 令牌最终可能代表几个关键字。问题是我的词法分析器总是将任何以“--”开头的东西推入隐藏通道。如何使 LINE_COMMENT 令牌与指令不匹配?还是我必须将评论处理移到解析器中?

【问题讨论】:

  • 评论可以--This:开头吗?换句话说,-- 后跟一个标识符后跟 : 是否总是为指令保留?
  • 后者是真的。 -- This:--This also: 不应该是指令,但是...注意空格。

标签: antlr antlr3 lexer


【解决方案1】:

AFAIK,如果没有一些手动代码(恕我直言,这比将 cmets 推广到解析器更好!),就无法在您的词法分析器语法中处理这个问题。

你可以这样做:

  • 匹配'--'
  • 在自定义方法中,手动向前看直到行尾 (EOL)。当'--' 是指令的一部分时,让此方法返回true
    • 如果在 EOL 之前匹配的内容看起来是指令,则不匹配字符并返回 true
    • 如果在 EOL 之前匹配的不是指令,则匹配字符并返回 false
  • 如果您的自定义方法返回false,则必须是注释,您可以skip()

快速演示:

grammar T;

@lexer::members {

  private boolean directiveAhead() throws MismatchedTokenException {

    StringBuilder b = new StringBuilder();

    for(int ahead = 1; ; ahead++) {

      // Grab the next character from the input.
      int next = input.LA(ahead);

      // Check if we're at the EOL.
      if(next == -1 || next == '\r' || next == '\n') {
        break;
      }

      b.append((char)next);
    }

    if(b.toString().trim().matches("\\w+:\\w+")) {
      // Do NOT let the lexer consume all the characters, just return true!
      return true;
    }
    else {
      // Let the lexer consume all the characters!
      this.match(b.toString());
      return false;
    }
  }
}

parse
 : directive EOF
 ;

directive
 : DIRECTIVE_START IDENTIFIER COL IDENTIFIER 
 ;

IDENTIFIER
 : ('a'..'z' | 'A'..'Z')+
 ;

DIRECTIVE_START
 : '--' { if(!directiveAhead()) skip(); }
 ;

COL
 : ':'
 ;

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

【讨论】:

  • 谢谢,这正是我想要的,在这个过程中你教会了我一些关于 ANTLR 的新知识。我真的不想把我的解析器和评论处理搞混。
猜你喜欢
  • 1970-01-01
  • 2014-08-12
  • 1970-01-01
  • 1970-01-01
  • 2013-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多