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

如何提升Antlr4解析器Call分支优先级?解决函数调用解析异常

问题与解答

问题描述

自定义ANTLR4语法规则

grammar Test;

COMMA: ',';
OPEN: '(';
CLOSE: ')';

ATOM: [0-9a-zA-Z_]+;
SPACE: [ \r\n\t]+ -> skip;

start: expr EOF;

expr
    : ATOM                                         # Identifier
    | expr OPEN (expr (COMMA expr)*)? CLOSE        # Call
    | OPEN expr CLOSE                              # Wrap
    | expr COMMA expr                              # Then
    ;

测试表达式

FUNC(1, (2, 3), 4)

实际解析结果

start:
    expr:
        expr "FUNC"
        "("
        expr:
            expr:
                expr "1"
                ","
                expr:
                    "("
                    expr:
                        expr "2"
                        ","
                        expr "3"
                    ")"
            ","
            expr "4"
        ")"
    <EOF>

预期解析结果

start:
    expr:
        expr "FUNC"
        "("
        expr "1"
        ","
        expr:
            "("
            expr:
                expr "2"
                ","
                expr "3"
            ")"
        ","
        expr "4"
        ")"
    <EOF>

疑问

  • 如何让解析器优先选择Call分支而非Then分支?
  • Antlr4中的*是否类似正则表达式中的*??

解答

1. 优先匹配Call分支的解决方案

当前语法存在歧义:Then分支(expr COMMA expr)会先把1, (2, 3)合并成一个表达式,再和4通过Then组合,导致Call的参数被错误嵌套。

解决办法是拆分语法规则,明确区分“可作为调用主体/参数的表达式”和“逗号序列”:

grammar Test;

COMMA: ',';
OPEN: '(';
CLOSE: ')';

ATOM: [0-9a-zA-Z_]+;
SPACE: [ \r\n\t]+ -> skip;

start: expr EOF;

// 专门处理逗号分隔的序列(原Then分支)
expr
    : callable (COMMA callable)* # Then
    ;

// 处理原子、函数调用、括号包裹的表达式(原Identifier、Call、Wrap分支)
callable
    : ATOM                                         # Identifier
    | callable OPEN (expr (COMMA expr)*)? CLOSE    # Call
    | OPEN expr CLOSE                              # Wrap
    ;

调整后,callable负责处理能独立作为调用目标或参数的表达式,expr仅处理逗号连接的序列。解析FUNC(...)时,括号内的1, (2, 3), 4会被expr解析为三个独立的callable,正好符合Call的参数列表预期,得到你想要的结构。

2. Antlr4中*的行为说明

Antlr4里的*是贪婪匹配,和正则表达式中的普通*行为一致,而非非贪婪的*?。它会尽可能多地匹配符合规则的元素,直到后续规则无法匹配时才会回溯。

比如规则(expr (COMMA expr)*)会尽可能匹配所有COMMA expr的组合,不会提前终止匹配,只有当后续需要匹配)等符号时才会停止。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 11:10:36