ANTLRv3 不读取选项

标签 antlr grammar

我对 ANTLR 非常陌生,正在尝试了解词法分析器和解析器规则的工作原理。我遇到了我编写的语法问题,该问题似乎与词法分析器标记有关,即使只有前几个字符实际匹配,多个字符也被视为“匹配”。为了演示这一点,我编写了一个简单的 ANTLR 3 语法:

grammar test;
options {
    k=3;
}

@lexer::header { package test;}
@header {package test;}

sentence    :   (CHARACTER)*;

CHARACTER   :   'a'..'z'|' ';
SPECIAL     :   'special';

我正在使用 AntlrWorks 解析以下测试输入:

apple basic say sponsor speeds speckled specific wonder

我得到的输出是:

apple basic say nsor ds led ic wonder

在我看来,词法分析器正在使用 k=1,因此将我的 SPECIAL 标记与包含两个字母“sp”的任何内容相匹配。一旦遇到字母“sp”,它就会匹配特殊文字中的连续字符,直到实际输入无法匹配预期的标记 - 此时它会抛出错误(消耗该字符),然后继续执行句子的其余部分。每个错误的形式如下:

  line 1:18 mismatched chracter 'o' expecting 'e'

但是,这不是我想要创建的行为。我希望创建一个与关键字(“special”)匹配的词法分析器标记 - 用于此测试示例中未包含的其他解析器规则。但是,我不希望恰好包含相同初始字符的其他规则/输入受到影响

总结一下:

  1. 如何实际设置 antlr 3 选项(例如 k=2 或 k=3 等)?至少在我看来,我在这里尝试使用的选项尚未设置。
  2. 是否有更好的方法来创建解析器或词法分析器规则来匹配输入中的特定关键字,而不影响对不包含完全匹配的输入的其他部分的处理?

最佳答案

koptions { ... }部分定义了解析器的前瞻,而不是词法分析器。

注意语法

CHARACTER   :   'a'..'z'|' ';
SPECIAL     :   'special';

不明确:你的'special'也可以被视为 7 'a'..'z'的。通常,它的词法如下:

grammar Test;

sentence : (special | word | space)+ EOF;
special  : SPECIAL;
word     : WORD;
space    : SPACE;

SPECIAL  : 'special';
WORD     : 'a'..'z'+;
SPACE    : ' ';

它将解析输入:

specia special specials

如下:

enter image description here

即它(或多或少)被标记为 LL(1) 和“最长匹配”的组合。抱歉,我知道这有点含糊,但是 Definitive ANTLR Reference并没有准确地澄清这一点(至少,我找不到它......)。但我意识到这可能不是您想要的。

据我所知,生成单个字符标记定义由这些单个字符标记组成的关键字的唯一方法是通过将这两个标记合并到单个规则中并使用谓词来完成并手动预测它们是否符合关键字,如果不符合,则更改“失败”子规则中的标记类型。演示:

grammar test;

tokens {
  LETTER;
}

@lexer::members {
  // manual look ahead
  private boolean ahead(String text) {
    for(int i = 0; i < text.length(); i++) {
      if(input.LA(i+1) != text.charAt(i)) {
        return false;
      }
    }
    return true;
  }
}

sentence
  :  (t=. {System.out.printf("\%-7s :: '\%s'\n", tokenNames[$t.type], $t.text);})+ EOF
  ;

SPECIAL 
  :  {ahead("special")}?=> 'special'
  |  {ahead("keyword")}?=> 'keyword'
  |  'a'..'z' {$type = LETTER;} // Last option and no keyword is found: 
                                // change the type of this token
  ;

SPACE
  :  ' '
  ;

从上述语法生成的解析器可以使用类进行测试:

import org.antlr.runtime.*;

public class Main {
    public static void main(String[] args) throws Exception {
        ANTLRStringStream in = new ANTLRStringStream("apple basic special speckled keyword keywor");
        testLexer lexer = new testLexer(in);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        testParser parser = new testParser(tokens);
        parser.sentence();
    }
}

如您所见,解析输入时:

apple basic special speckled keyword keywor

生成以下输出:

LETTER  :: 'a'
LETTER  :: 'p'
LETTER  :: 'p'
LETTER  :: 'l'
LETTER  :: 'e'
SPACE   :: ' '
LETTER  :: 'b'
LETTER  :: 'a'
LETTER  :: 's'
LETTER  :: 'i'
LETTER  :: 'c'
SPACE   :: ' '
SPECIAL :: 'special'
SPACE   :: ' '
LETTER  :: 's'
LETTER  :: 'p'
LETTER  :: 'e'
LETTER  :: 'c'
LETTER  :: 'k'
LETTER  :: 'l'
LETTER  :: 'e'
LETTER  :: 'd'
SPACE   :: ' '
SPECIAL :: 'keyword'
SPACE   :: ' '
LETTER  :: 'k'
LETTER  :: 'e'
LETTER  :: 'y'
LETTER  :: 'w'
LETTER  :: 'o'
LETTER  :: 'r'

查看问答What is a 'semantic predicate' in ANTLR?了解有关 ANTLR 中谓词的更多信息。

关于ANTLRv3 不读取选项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6013622/

相关文章:

css - Mozilla Developer Network 上语法规范使用的语法是什么?

antlr - 这个语法有什么问题?

Antlr4 函数应用语法

java - ANTLR:空格缩进?

json - JSON 语法是否允许元素使用裸标签?是否允许使用单引号?

regex - 正则语言的定义

c - 对于决策错误,调试 Xtext 甚至无法执行 k=1

javascript - ANTLR 3 中针对 Javascript 的表达式解析器

c++ - Antlr4 C++ 访客 API

visual-studio-2010 - 在VS2010中寻找Antlr Grammar语法高亮