ANTLR4实现基于参数类型的Excel函数重载解析问题
Excel函数解析器重载匹配问题
问题描述
我开发了一款Excel函数解析器,需基于参数类型处理函数重载。核心问题在于数字与字符串列的类型依赖外部上下文,解析器需要根据列上下文选择匹配的函数:
- 输入表达式
IFNA(123, 234)→ 正确解析为number_function - 输入表达式
IFNA("foo", "bar")→ 正确解析为string_function
但使用列时出现异常:
columnsContext = { column1: Type.String column2: Type.String }
输入表达式:IFNA(column1, column2)
该表达式应根据列类型解析为string_function,但因语法中number_function声明在前,被错误识别为number_function。
我尝试通过语义谓词结合自定义解析器处理,但执行isNumber()时抛出noViableAlt异常——解析器已将IFNA识别为number_function,但列类型为字符串,谓词返回false。
相关代码
初始语法
grammar ExcelLikeFunctionsGrammar; expression : number | string; number_function: IFNA LEFT_PAREN number COMMA number RIGHT_PAREN | ... other functions; string_function: IFNA LEFT_PAREN string COMMA string RIGHT_PAREN | ... other functions; number : NUMBER_CONSTANT | number_function | number_column ; string : STRING_CONSTANT | string_function | string_column ; number_column: ALPHANUMERIC; string_column: ALPHANUMERIC;
修改后带语义谓词的语法
grammar ExcelLikeFunctionsGrammar; // 该方法会在自定义解析器中被覆盖 @members { protected boolean isNumber() { return true; } protected boolean isString() { return true; } } expression : number | string; number_function: IFNA LEFT_PAREN number COMMA number RIGHT_PAREN | ... other functions; string_function: IFNA LEFT_PAREN string COMMA string RIGHT_PAREN | ... other functions; number : NUMBER_CONSTANT | number_function | {isNumber()}? number_column ; string : STRING_CONSTANT | string_function | {isString()}? string_column ; number_column: ALPHANUMERIC; string_column: ALPHANUMERIC;
自定义解析器代码
public class ExcelLikeFunctionsGrammarCustomParser extends ExcelLikeFunctionsGrammarParser { private final ReferenceContext referenceContext; public ExcelLikeFunctionsGrammarCustomParser(TokenStream input, ReferenceContext referenceContext) { super(input); this.referenceContext = referenceContext; } @Override protected final boolean isNumber() { return checkColumnTokenType(TableColumnType.DECIMAL); } @Override protected final boolean isString() { return checkColumnTokenType(TableColumnType.STRING); } private boolean checkColumnTokenType(TableColumnType columnType) { return checkTypeLogic(...); }
内容的提问来源于stack exchange,提问作者Daniel Strausz
相关产品推荐
相关产品推荐

