Antlr4 将分数视为空白。这正常吗?

Antlr4 将分数视为空白。这正常吗?,antlr4,Antlr4,在我的语法中,我有一个空格: WS: (' '|'\r'|'\t'|'\n') -> skip ; 但是,如果我放置一个未加分数而不是一个空格,解析器不会阻塞 My-first-module_DEFINITIONS_::= 被认为是 My-first-module DEFINITIONS ::= 是否有一个选项我必须在lexer中设置一些 谢谢 这是简化的语法,有助于再现我所看到的内容 grammar ASN; /*--------------------- Modul

在我的语法中,我有一个空格:

WS:
    (' '|'\r'|'\t'|'\n') -> skip
;
但是,如果我放置一个未加分数而不是一个空格,解析器不会阻塞

My-first-module_DEFINITIONS_::=
被认为是

My-first-module DEFINITIONS ::=  
是否有一个选项我必须在lexer中设置一些

谢谢

这是简化的语法,有助于再现我所看到的内容

grammar ASN;

/*--------------------- Module definition -------------------------------------------*/

/* ModuleDefinition (see 13 in ITU-T X.680 (08/2015) */
moduleDefinition:  
    moduleIdentifier
    DEFINITIONS_LITERAL
    ASSIGN
    BEGIN_LITERAL
    END_LITERAL
;

moduleIdentifier: 
    UCASE_ID 
;



/*--------------------- LITERAL -----------------------------------------------------*/

DEFINITIONS_LITERAL:
    'DEFINITIONS'
;

BEGIN_LITERAL:
    'BEGIN'
;

END_LITERAL:
    'END'
;

ASSIGN:
    '::='
;

UCASE_ID:
    ('A'..'Z') ('-'('a'..'z'|'A'..'Z'|'0'..'9')|('a'..'z'|'A'..'Z'|'0'..'9'))* 
;


/* white-space (see 12.1.6 in ITU-T X.680 (08/2015) */
WS:
    (' '|'\r'|'\t'|'\n') -> skip
;
以及解析器不应接受的示例:

My-first-module_DEFINITIONS_::= 
BEGIN 

END
编辑:我意识到我的问题是因为我使用JUnit来运行测试,我只是检查解析器发现的语法错误。 下面是代码,包括巴特的答案,如果lexer出现问题,它会导致测试失败

// load test data
InputStream inStream = getClass().getClassLoader().getResourceAsStream(resourceName);

if (inStream == null) {
    throw new RuntimeException("Resource not found: " + resourceName);
}

// create a CharStream that reads from standard input
CharStream input = new ANTLRInputStream(inStream);

// create a lexer that feeds off of input CharStream
ASNLexer lexer = new ASNLexer(input);
lexer.addErrorListener(new BaseErrorListener() {
    public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
        throw new RuntimeException(e);
        }
    }
);
// create a buffer of tokens pulled from the lexer
TokenStream tokens = new CommonTokenStream(lexer);
// create a parser that feeds off the tokens buffer
ASNParser parser = new ASNParser(tokens);
parser.moduleDefinition(); // begin parsing at moduleDefinition rule
assert(0 == parser.getNumberOfSyntaxErrors());
//负载测试数据
InputStream inStream=getClass().getClassLoader().getResourceAsStream(resourceName);
如果(流内==null){
抛出新的RuntimeException(“未找到资源:+resourceName”);
}
//创建从标准输入读取的字符流
CharStream输入=新的AntlInputStream(流内);
//创建一个lexer,该lexer从输入字符流中获取信息
ASNLexer lexer=新ASNLexer(输入);
lexer.addErrorListener(新的BaseErrorListener(){
public void syntaxError(识别器识别器、对象违规符号、int行、int charPositionInLine、字符串消息、识别异常e){
抛出新的运行时异常(e);
}
}
);
//创建从lexer提取的令牌缓冲区
令牌流令牌=新的CommonTokenStream(lexer);
//创建一个以令牌缓冲区为源的解析器
ASNParser parser=新的ASNParser(令牌);
parser.moduleDefinition();//从moduleDefinition规则开始解析
断言(0==parser.getNumberOfSyntaxErrors());

lexer从意外输入中恢复。通过运行此类,可以看到这一点:

public class Main {

  public static void main(String[] args) {

    String source = "My-first-module_DEFINITIONS_::= \n" +
        "BEGIN \n" +
        "\n" +
        "END";

    ASNLexer lexer = new ASNLexer(CharStreams.fromString(source));
    ASNParser parser = new ASNParser(new CommonTokenStream(lexer));
    parser.moduleDefinition();
  }
}
将在标准输出中打印以下内容:

line 1:15 token recognition error at: '_'
line 1:27 token recognition error at: '_'
这里有几个选项:

1.添加一个全面的规则 在语法末尾添加这样一条规则:

Other
 : .
 ;
然后根据需要在解析器中处理
Other

2.添加自定义
ErrorListener
这样做:

lexer.addErrorListener(new BaseErrorListener(){
  @Override
  public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
    throw new RuntimeException(e);
  }
});
UCASE_ID:
    [A-Z] ( '-'? [a-zA-Z0-9] )*
;

WS:
    [ \t\r\n] -> skip
;

可能是lexer或解析器从中恢复,也可能是其他东西。如果看不到一个“最小的、完整的、可验证的例子”(见:),我将把我的东西放到网上。根据你的回答,我想这是不正常的?“我想这是不正常的?”-不,这很可能是ANTLR按预期执行。“我会把我的东西放在网上”-无需发布数百个LOC,只需重现问题即可。请将代码添加到您的问题中,而不是一些非现场位置。这只是一个测试用例: