ANTLR 4.8环境下Java生成的解析器无法正常运行问题求助
ANTLR 4.8 解析故障解决方案
核心问题1:ParseTree实例化逻辑错误
ANTLR 中ParseTree是接口,不能直接通过构造方法传入parser实例创建,必须调用parser对应语法的入口规则方法获取解析树,你代码中ParseTree pt = new ParseTree(parser);是完全错误的写法。
核心问题2:语法规则存在疏漏
- 缺失空格忽略规则:你输入的公式包含大量空格,但语法中没有配置空格跳过逻辑,所有空格会被识别为非法字符,导致词法解析直接中断
- 逻辑表达式规则限制过严:现有
logicalStmt规则要求逻辑运算必须整体包裹在括号中,但你的输入(fm.a < fm.b) | (fm.a = fm.b)最外层没有括号,无法匹配规则
核心问题3:4.8版本CharStream访问方式变更
ANTLR 4.8对Lexer的私有属性封装更严格,直接访问lexer._input在部分环境下会失效,且你传入的区间0~100超过输入长度时也会返回空值,应该直接使用你创建的CharStream实例调用getText方法。
修正代码示例
String formula = "(fm.a < fm.b) | (fm.a = fm.b)"; CharStream input = CharStreams.fromString(formula); // 验证输入读取正常 System.out.println(input.getText(Interval.of(0, input.size() - 1))); Antlr.LogicGrammerLexer lexer = new Antlr.LogicGrammerLexer(input); CommonTokenStream tokens = new CommonTokenStream(lexer); // 预加载所有token,验证词法解析结果 tokens.fill(); for (Token token : tokens.getTokens()) { System.out.printf("Token文本:%s,对应类型:%s%n", token.getText(), lexer.getVocabulary().getSymbolicName(token.getType()) ); } Antlr.LogicGrammerParser parser = new Antlr.LogicGrammerParser(tokens); // 调用入口规则获取解析树 ParseTree pt = parser.logicalStmt(); // 打印解析树结构 System.out.println(pt.toStringTree(parser));
修正后语法文件
grammar LogicGrammer; logicalStmt: logicalStmt LOGIC_SYMBOL logicalStmt | '(' logicalStmt ')' | BOOL_EXPR ; BOOL_EXPR: '(' IDENTIFIER ' '* MATH_SYMBOL ' '* IDENTIFIER ')'; IDENTIFIER: CHAR+ ('.' CHAR+)*; CHAR: [a-zA-Z1-9]; LOGIC_SYMBOL: '~' | '|' | '&'; MATH_SYMBOL: '<' | '≤' | '=' | '≥' | '>'; // 跳过所有空格、换行符 WS: [ \t\r\n]+ -> skip;
内容的提问来源于stack exchange,提问作者David Franz
相关产品推荐
相关产品推荐

