我完全是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();
}
lexer的输入示例:
take 10 Tablet (25MG) by oral route every week
在本例中,ACTION节点没有被填充,但是take
只被识别为TEXT节点,而不是ACTION节点。然而,10
被识别为INT节点。
我如何修改这个语法,使其正确工作,其中ACTION节点被正确填充(以及FORM,也没有被填充)?
你的语法有几个问题:
- 你的TEXT规则只匹配大写字母。ACTION也一样。
- 你不应该在一个文本规则中混合标点和文本(这里是逗号),否则你不能自由地允许符号之间的空白。
- 您根本不匹配括号,因此
(25MG)
不是有效输入,解析器返回错误状态。 - 您没有检查任何语法错误,以了解在识别过程中出了什么问题。
另外,如果有疑问,请始终从令牌源打印令牌序列,以查看输入是否按预期进行了令牌化。在进入解析器之前,从这里开始修改语法。
关于大小写敏感性:通常(如果你的语言是不区分大小写的)你有这样的规则:
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;