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

使用ANTLR4实现简易解析器:匹配内容至结束标记与函数解析

问题与解决方案

核心问题

需要实现支持文本块(PLAIN_TEXT_BLOB)、脚本块(SCRIPT_BLOB)、函数声明(FUNCTION)的解析器,保持三者出现顺序。当前瓶颈是SCRIPT模式下无法正确匹配函数体到end function标记——贪心规则导致end被识别为普通标识符,无法触发FunctionEnd token;同时无法捕获任意类型的通用脚本语句。

解决方案

1. 调整Lexer规则(解决end function识别问题)

Antlr Lexer遵循先定义优先+最长匹配原则,当前Ident规则会优先捕获end和function作为单独标识符,导致FunctionEnd无法被识别。需调整SCRIPT模式下的token顺序,并补充通用脚本内容的捕获:

lexer grammar ExprLexer;

channels { Comments, SkipChannel }

SeaWhitespace:  [ \t\r\n\f]+ -> channel(HIDDEN);
HtmlDtd:        '<!' .*? '>';
ScriptStart:    '<%' -> channel(SkipChannel), pushMode(SCRIPT);
GenericText:    . ; // 捕获所有未匹配的文本

mode SCRIPT;
ScriptEnd:          '%>' -> channel(SkipChannel), popMode;
ScriptWhitespace:   [ \t\r\n\f]+ -> channel(SkipChannel);
ScriptSingleLineComment:  '\'' -> channel(SkipChannel), pushMode(SingleLineCommentMode);

// 优先识别关键字,避免被Ident捕获
FunctionStart:      'function';
FunctionEnd:        'end function';

// 脚本符号
COMMA:     ',';
SEMICOLON: ';';
L_PAREN:   '(';
R_PAREN:   ')';
ASSIGNTO:  '=';

// 最后定义Ident,确保关键字优先匹配
Ident:     [a-zA-Z0-9_\u0080-\ufffe]+;

// 捕获任意未匹配的脚本内容(用于通用语句)
ScriptContent:      ~[ \t\r\n\f%();,=]+;

mode SingleLineCommentMode;
Comment:            ~[\r\n]+ -> channel(Comments);
CommentEnd:         [\r\n] -> channel(SkipChannel), popMode;

2. 重构Parser规则(实现三类结构的正确捕获)

重新设计规则,明确区分文本块、脚本块(含函数和通用语句),并确保函数体正确匹配到end function:

parser grammar ExprParser;
options { tokenVocab=ExprLexer; }

file
    : contentNode* EOF
    ;

// 统一节点类型,严格保留原顺序
contentNode
    : plainTextBlob
    | scriptBlob
    | functionDeclaration
    ;

// 文本块:连续的非脚本文本内容
plainTextBlob
    : (HtmlDtd | GenericText)+
    ;

// 脚本块:除函数声明外的任意脚本内容
scriptBlob
    : scriptStatement+
    ;

// 通用脚本语句:匹配任意脚本元素,无需区分类型
scriptStatement
    : (Ident | ScriptContent | COMMA | SEMICOLON | L_PAREN | R_PAREN | ASSIGNTO)+
    ;

// 函数声明:匹配完整函数定义到end function,支持可选参数和嵌套函数
functionDeclaration
    : FunctionStart Ident L_PAREN (Ident (COMMA Ident)*)? R_PAREN 
      (scriptStatement | functionDeclaration)* 
      FunctionEnd
    ;

关键说明

  • Lexer优先级调整:将FunctionStart、FunctionEnd等关键字放在Ident之前,确保这些完整标记被优先识别,避免被拆分为普通标识符。
  • 通用脚本内容捕获:新增ScriptContent和scriptStatement规则,直接捕获所有未被关键字/符号匹配的脚本内容,无需区分语句类型。
  • 结构顺序保留:通过contentNode统一管理三类结构,解析结果严格遵循原文件中的出现顺序。
  • 嵌套支持(可选):函数体规则允许嵌套函数,若不需要可移除functionDeclaration选项。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 14:52:19