ANTLR解析没有找到正确的词法分析器部分

时间:2016-10-12 18:16:19

标签: java parsing antlr antlr4 lexer

我是ANTLR的全新人。

我有以下ANTLR语法:

grammar DrugEntityRecognition;

// Parser Rules 

derSentence : ACTION (INT | FRACTION | RANGE) FORM TEXT;

// Lexer Rules

ACTION : 'TAKE' | 'INFUSE' | 'INJECT' | 'INHALE' | 'APPLY' | 'SPRAY' ;

INT : [0-9]+ ;

FRACTION : [1] '/' [1-9] ;

RANGE : INT '-' INT ;

FORM : ('TABLET' | 'TABLETS' | 'CAPSULE' | 'CAPSULES' | 'SYRINGE') ;

TEXT : ('A'..'Z' | WHITESPACE | ',')+ ;

WHITESPACE : ('\t' | ' ' | '\r' | '\n' | '\u000C')+ -> skip ;

当我尝试按如下方式解析句子时:

String upperLine = line.toUpperCase();
org.antlr.v4.runtime.CharStream stream = new ANTLRInputStream(upperLine);
DrugEntityRecognitionLexer lexer = new DrugEntityRecognitionLexer(stream);
lexer.removeErrorListeners();
lexer.addErrorListener(ThrowingErrorListener.INSTANCE);

CommonTokenStream tokenStream = new CommonTokenStream(lexer);
DrugEntityRecognitionParser parser = new DrugEntityRecognitionParser(tokenStream);

try {
        DrugEntityRecognitionParser.DerSentenceContext ctx = parser.derSentence();

        StringBuilder sb = new StringBuilder();

        sb.append("ACTION: ").append(ctx.ACTION());
        sb.append(", ");
        sb.append("FORM: ").append(ctx.FORM());
        sb.append(", ");
        sb.append("INT: ").append(ctx.INT());
        sb.append(", ");
        sb.append("FRACTION: ").append(ctx.FRACTION());
        sb.append(", ");
        sb.append("RANGE: ").append(ctx.RANGE());

        System.out.println(upperLine);
        System.out.println(sb.toString());

  } catch (ParseCancellationException e) {
       //e.printStackTrace();
  }

词法分析器的输入示例:

take 10 Tablet (25MG)  by oral route  every week

在这种情况下,ACTION节点未填充,但take仅被识别为TEXT节点,而不是ACTION节点。但是,10被识别为INT节点。

如何正确填充ACTION节点(以及未填充的FORM),如何修改此语法才能正常工作?

1 个答案:

答案 0 :(得分:1)

你的语法有几个问题:

  1. 您的TEXT规则仅匹配大写字母。同样适用于行动。
  2. 你不应该在单个文本规则(这里是逗号)中混合标点符号和文本,否则你不能在标记之间自由地允许空格。
  3. 根本不匹配括号,因此(25MG)无效输入且解析器返回错误状态。
  4. 您没有检查任何语法错误,以了解识别过程中出现的问题。
  5. 此外,如果有疑问,请始终从令牌源打印令牌序列,以查看输入是否实际上已按预期进行了标记。在你去解析器之前,先从那里修复你的语法。

    关于区分大小写:通常(如果您的语言不区分大小写),您有以下规则:

    fragment A: [aA];
    fragment B: [bB];
    fragment C: [cC];
    fragment D: [dD];
    ...
    

    匹配任何一种情况下的字母,然后定义您的关键字:

    ACTION : T A K E | I N F U S E | I N J E C T |  I N H A L E | A P P L Y  | S P R A Y;