当前位置: 首页 > 知识库问答 >
问题:

在antlr4 lexer中,如何有一个规则来捕获所有剩余的“单词”作为未知的令牌?

郑富
2023-03-14
Whitespace : [ \t\n\r]+ -> skip;
Punctuation : [.,:;?!];
// Other rules here
Unknown : .+? ; 

现在生成的匹配器捕获“~”为未知,但为输入“~”创建3个“~”未知令牌,而不是单个“~”令牌。我应该做什么来告诉lexer为未知的连续字符生成单词令牌。我还试过“未知:.;”和“未知:.+;”没有结果。

编辑:在当前的antlr版本中。+?现在捕获剩余的单词,所以这个问题似乎已经解决了。

共有1个答案

诸葛康胜
2023-03-14

lexer规则末尾的.+?将始终与单个字符匹配。但是.+将尽可能多地消耗,这在ANTLR v3(可能也是v4)中的规则末尾是非法的。

您所能做的只是匹配一个字符,并在解析器中将这些字符“粘合”在一起:

unknowns : Unknown+ ; 

...

Unknown  : . ; 

...但我只有一个lexer,没有解析器...

lexer grammar Lex;

@members {

  public static void main(String[] args) {
    Lex lex = new Lex(new ANTLRInputStream("foo, bar...\n"));
    for(Token t : lex.getAllTokens()) {
      System.out.printf("%-15s '%s'\n", tokenNames[t.getType()], t.getText());
    }
  }

  private java.util.Queue<Token> queue = new java.util.LinkedList<Token>();

  @Override
  public Token nextToken() {    

    if(!queue.isEmpty()) {
      return queue.poll();
    }

    Token next = super.nextToken();

    if(next.getType() != Unknown) {
      return next;
    }

    StringBuilder builder = new StringBuilder();

    while(next.getType() == Unknown) {
      builder.append(next.getText());
      next = super.nextToken();
    }

    // The `next` will _not_ be an Unknown-token, store it in 
    // the queue to return the next time!
    queue.offer(next);

    return new CommonToken(Unknown, builder.toString());
  }
}

Whitespace  : [ \t\n\r]+ -> skip ;
Punctuation : [.,:;?!] ;
Unknown     : . ; 
java -cp antlr-4.0-complete.jar org.antlr.v4.Tool Lex.g4 
javac -cp antlr-4.0-complete.jar *.java
java -cp .:antlr-4.0-complete.jar Lex
Unknown         'foo'
Punctuation     ','
Unknown         'bar'
Punctuation     '.'
Punctuation     '.'
Punctuation     '.'
 类似资料:
  • 现在生成的匹配器将'~'捕获为未知,但为输入'~~~'创建3'~'未知标记,而不是单个'~~~'标记。我应该做些什么来告诉lexer为未知的连续字符生成单词标记。我还尝试了“未知:.;”和“未知:.+;”没有结果。 编辑:在当前的antlr版本中。+?现在捕获剩余的单词,所以这个问题似乎得到了解决。

  • 我目前在我的路由中使用dotry/doCatch块,因此我无法使用全局onException块。 然而,如果驼峰路由中断(由于错误代码或意外/未测试的场景),我希望执行一些业务逻辑。希望这永远不会发生,但我仍然想处理更糟糕的情况。 我不能在全局OneException块中有java.lang.Exception,而且,我不想在每个路由上都添加一个额外的捕获。 在抛出未捕获的异常和中断路由之前,是否

  • 我有一个具有GUI和套接字通信的不小的多线程应用程序。在开发过程中,我发现有时有些异常没有被捕获和记录。如果有,我必须盯着控制台看。 有没有办法在一个地方捕获来自不同线程(包括EDT)的未捕获异常,比如在main()中,并记录它们?我确实在main()中放置了一个try catch来捕捉可丢弃的对象,但它不起作用。 编辑: 更具体地说,我有遗嘱执行人。newCachedThreadPool(),具

  • 问题内容: 在下面的HTML片段中,如何使包含“ LAST”的列的宽度占据行的其余部分,并且包含“ COLUMN ONE”和“ COLUMN TWO”的列的宽度足够宽以包含其内容,而不是更大。 谢谢 问题答案: 您将需要告诉前两列不要换行,并为最后一列提供99%的宽度: 编辑: 您应该将所有样式/演示文稿放在(外部…)css中。 对列使用类(如果您仅针对现代浏览器,则可以使用css3选择器,例如)

  • 我知道有可能向JBPM/BPMS发出外部信号以启动工作流。你使用信号启动事件,我可以很好地工作。 我想知道的是,没有相应的信号参考的信号会发生什么。 我正在捕获某些事件并将它们发送到JBPM,我希望有一个catch all工作流或规则,如果没有相应的工作流启动,以便这些事件仍然可以被处理。 任何想法都将不胜感激。

  • 我对荡秋千很陌生。我有一个基于外部输入动态生成UI的应用程序。在面板的顶部,有一个带有一些标题文本的JLabel,然后是一个按钮(告诉应用程序重新加载动态生成的内容),然后在下面是一个JScrollPane,其中包含所有动态生成的内容。我希望标签和按钮只占用所需的垂直空间,然后滚动窗格来填充所有剩余的可用空间。 我正在使用GridBagLayout,并在添加滚动窗格之前设置gbc.fill=BOT