为什么这个语法错误208?

时间:2011-10-24 08:38:51

标签: antlr antlr3

我不明白为什么以下语法导致错误208抱怨IF永远不会匹配:

error(208): test.g:11:1: The following token definitions can never be matched because prior tokens match the same input: IF

ANTLRWorks 1.4.3

ANTLT 3.4

grammar test;

@lexer::members {
  private boolean rawAhead() {
  }
}

parse    :    IF*;

RAW    :    ({rawAhead()}?=> . )+;
IF      :    'if';
ID    :    ('A'..'Z'|'a'..'z')+;

删除RAW规则或ID规则解决错误... 从我的观点来看,当rawAhead()返回false时,IF确实可以匹配。

1 个答案:

答案 0 :(得分:0)

  

Bood写道:

     

我认为这实际上很重要,比如我们是否只有一个'如果'在mmode之外,例如<#/>如果<#/>,则if这里将与IF匹配,而不是RAW它应该是(相同长度,匹配第一个),对吗?

是的,你是对的,好的一点。更多地认为预期的行为AFAIK。但是,似乎情况有所不同:RAW规则优先于IDIF规则,即使放在词法分析器语法的末尾,如您所见: / p>

freemarker_simple.g

grammar freemarker_simple;

@lexer::members {

  private boolean mmode = false;

  private boolean rawAhead() {
    if(mmode) return false;
    int ch1 = input.LA(1), ch2 = input.LA(2), ch3 = input.LA(3);
    return !(
        (ch1 == '<' && ch2 == '#') ||
        (ch1 == '<' && ch2 == '/' && ch3 == '#') ||
        (ch1 == '$' && ch2 == '{')
    );
  }
}

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

OUTPUT_START  : '${'  {mmode=true;};
TAG_START     : '<#'  {mmode=true;};
TAG_END_START : '</' ('#' {mmode=true;} | ~'#' {$type=RAW;});

OUTPUT_END    : '}' {mmode=false;};
TAG_END       : '>' {mmode=false;};

EQUALS        : '==';
IF            : 'if';
STRING        : '"' ~'"'* '"';
ID            : ('a'..'z' | 'A'..'Z')+;
SPACE         : (' ' | '\t' | '\r' | '\n')+ {skip();};

RAW           : ({rawAhead()}?=> . )+;

Main.java

import org.antlr.runtime.*;

public class Main {
  public static void main(String[] args) throws Exception {
    freemarker_simpleLexer lexer = new freemarker_simpleLexer(new ANTLRStringStream("<#/if>if<#if>foo<#if>"));
    freemarker_simpleParser parser = new freemarker_simpleParser(new CommonTokenStream(lexer));
    parser.parse();
  }
}

将以下内容打印到控制台:

TAG_START       '<#'
IF              'if'
TAG_END         '>'
RAW             'if'
TAG_START       '<#'
IF              'if'
TAG_END         '>'
RAW             'foo'
TAG_START       '<#'
IF              'if'
TAG_END         '>'

如您所见,'if''foo' 在输入中被标记为RAW

<#/if>if<#if>foo<#if>
      ^^     ^^^