下划线被视为空白。正常吗?

undescores seen as white spaces. Is it normal?

在我的语法中,白色 spaces:

WS:
    (' '|'\r'|'\t'|'\n') -> skip
;

但是,如果我使用下划线而不是 space,解析器不会阻塞。

My-first-module_DEFINITIONS_::=

被识别为

My-first-module DEFINITIONS ::=  

是否有我必须在词法分析器中设置的选项?

谢谢

这是有助于重现我所见内容的精简语法

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 运行 我的测试,我只是检查解析器发现的语法错误。 这是代码,包括 Bart 的回答,如果词法分析器有问题,它会使测试失败 ...

// 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());

词法分析器从意外输入中恢复。你可以通过 运行 这个 class:

查看
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。添加 catch-all 规则

在语法末尾添加这样的规则:

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);
  }
});

这将导致词法分析器中的任何错误抛出 RuntimeException

请注意,ANTLR4 支持更紧凑的定义字符集的表示法,如下所示:

UCASE_ID:
    [A-Z] ( '-'? [a-zA-Z0-9] )*
;

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