You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ANTLR4逻辑表达式解析未拦截非法语法的问题排查求助

问题根因

你的语法、词法设计存在4个核心疏漏,直接导致非法查询漏判:

  • 空白处理逻辑混乱:你在AND、OR、括号、比较符等几乎所有token的匹配规则前后硬编码了' '*来匹配空格,同时又重复定义了SPACE、WS两个功能完全一致的、将空白送入隐藏通道的规则。这种写法完全破坏了ANTLR统一的空白处理逻辑,还会干扰词法的最长匹配规则,导致单字符&、|的识别异常。
  • 入口规则未强制全串匹配:你的入口规则query: (expression)+;没有加EOF终止符,ANTLR默认只要输入串的任意前缀能匹配规则就算解析成功,不需要处理完所有输入字符。这就导致解析器碰到第一个合法表达式后,不管后面跟的是单个&、单个|还是其他非法内容,都会直接返回前面的匹配结果,剩余的非法输入被完全忽略,不会触发错误。
  • 语法规则允许无运算符连接表达式:你在query规则和expressionGroup规则里都用了(expression)+的写法,允许多个表达式连续出现、中间不需要任何逻辑运算符,这直接导致两个表达式直接靠空格拼接、甚至完全挨在一起的非法写法,会被解析成多个顺序排列的合法expression,不会触发语法错误。
  • 语法规则存在冗余二义性:你单独写了expressionGroup logicalOperator expressionGroup分支,但expressionGroup本身已经是expression的可选分支,重复定义会产生解析二义性,干扰正常的逻辑表达式匹配。
修改方案

按下面的步骤调整,即可正确拦截所有非法查询:

  1. 统一空白处理逻辑
    删掉所有token规则前后硬编码的' '*,只保留一个送入隐藏通道的空白规则,所有关键字、运算符仅匹配符号本身。注意你贴的代码里出现的&、"是HTML转义结果,实际编写g4文件时要替换为原生的&、"字符。改完的词法规则部分如下:
    // 唯一的空白处理规则,统一送入隐藏通道
    WS: [ \t\r\n]+ -> channel(HIDDEN);
    
    // 关键字、运算符仅匹配核心符号,不带前后空格
    AND: '&&' | 'AND' | 'and';
    OR: '||' | 'OR' | 'or';
    NOT: '!' | 'not' | 'NOT';
    HAS: 'HAS' | 'has';
    IN: 'IN' | 'in';
    EQ: '=';
    NEQ: '!=';
    L_SQ_BRACKET: '[';
    R_SQ_BRACKET: ']';
    L_RND_BRACKET: '(';
    R_RND_BRACKET: ')';
    COMMA: ',';
    KEY_PREFIX: 'tags(';
    IDENTIFIER: [A-Za-z0-9_]+ ;
    ESCAPED_IDENTIFIER: '"' ( '""' | [^"] )* '"';
    STRING_LITERAL: '\'' [A-Za-z0-9_ ]* '\'';
    
    // 放在所有词法规则最后,兜底匹配所有非法字符,触发词法错误
    INVALID_CHAR: . ;
    
  2. 修正语法规则,强制全串匹配、禁止无运算符连写表达式
    删掉冗余的表达式组逻辑运算分支,在入口规则末尾加EOF强制匹配完所有输入,移除所有允许多个表达式连续出现的+量词,明确多表达式之间必须存在逻辑运算符。改完的语法规则部分如下:
    query
        : expression EOF // 强制匹配完整输入,避免提前截断忽略非法内容
        ;
    
    expression
        : keyValue                                                #comparisonExpression
        | inExpression                                            #singleInExpression
        | hasExpression                                           #singleHasExpression
        | expressionGroup                                         #singleExpressionGroup
        | NOT expression                                          #notExpression
        | expression logicalOperator expression                   #logicalExpression
        ;
    
    inExpression
        : key IN literalList
        ;
    
    hasExpression
        : HAS key
        ;
    
    expressionGroup
        : L_RND_BRACKET expression R_RND_BRACKET
        ;
    
    keyValue
        : key comparisonOperator literal
        ;
    
    key
        :  KEY_PREFIX keyName R_RND_BRACKET
        ;
    
    keyName
        : IDENTIFIER
        ;
    
    comparisonOperator
        : EQ | NEQ
        ;
    
    logicalOperator
        : AND | OR
        ;
    
    literalList
        : L_SQ_BRACKET literal (COMMA literal)* R_SQ_BRACKET
        ;
    
    literal
        : STRING_LITERAL
        ;
    
验证效果

调整后所有非法输入都会被正确拦截:

  • 含单个&、单个|的输入会被INVALID_CHAR规则捕获,触发词法错误
  • 两个表达式中间仅靠空格拼接、或完全无间隔连写的输入,会因为缺少逻辑运算符触发语法错误
  • 合法的带&&/||连接符的查询可正常解析,不受影响。

内容的提问来源于stack exchange,提问作者Aditya Jagtiani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 10:27:40