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

如何让ANTLR4词法分析器多消费字符并在已有规则处停止?

合并ANTLR4 PhpLexer的INLINE_HTML Token解决方案

现有如下PhpLexer词法规则:

lexer grammar PhpLexer;

options {
    superClass = PhpLexerBase;
    caseInsensitive = true;
}

T_OPEN_TAG_WITH_ECHO: '<?='  -> pushMode(PHP);
T_OPEN_TAG: PhpOpenTag -> pushMode(PHP);

T_INLINE_HTML: .+?;      // 问题点

mode PHP;
   T_CLOSE_TAG: '?>';
   T_BAD_CHARACTER: .;

fragment NEWLINE: '\r'? '\n' | '\r';

fragment PhpOpenTag
    : '<?php' ([ \t] | NEWLINE)
    | '<?php' EOF
    ;

输入内容为:

<html><?php echo "Hello, world!"; ?></html>

当前识别结果为每个HTML字符均被识别为独立的T_INLINE_HTML Token,期望将<html>这类连续HTML内容合并为单个T_INLINE_HTML Token,让词法分析器消费更多字符直到遇到已定义的PHP标签规则时终止。

问题原因

原规则中的.+?是非贪婪匹配,它会尽可能少地匹配字符——由于没有明确的终止条件,ANTLR会每次只匹配一个字符就生成Token,最终导致每个HTML字符都被拆分成独立的T_INLINE_HTML。

解决方案

修改T_INLINE_HTML的规则,使用贪婪匹配并通过否定预查明确终止条件:匹配所有字符,直到即将出现PHP开标签(<?=或<?php)为止。

修改后的完整词法规则:

lexer grammar PhpLexer;

options {
    superClass = PhpLexerBase;
    caseInsensitive = true;
}

T_OPEN_TAG_WITH_ECHO: '<?='  -> pushMode(PHP);
T_OPEN_TAG: PhpOpenTag -> pushMode(PHP);

// 合并连续HTML内容为单个Token
T_INLINE_HTML: ( . (?! PhpTagStart ) )+;

mode PHP;
   T_CLOSE_TAG: '?>';
   T_BAD_CHARACTER: .;

fragment NEWLINE: '\r'? '\n' | '\r';

// 统一定义PHP标签的起始序列
fragment PhpTagStart
    : '<?='
    | '<?php'
    ;

fragment PhpOpenTag
    : '<?php' ([ \t] | NEWLINE)
    | '<?php' EOF
    ;

规则说明

  • (?! PhpTagStart) 是否定预查,确保当前位置之后不会出现PHP标签的起始序列;
  • 外层的( . ... )+ 是贪婪匹配,会尽可能多地消费字符,直到遇到PHP标签起始或文件结束,从而将连续的HTML内容合并为单个T_INLINE_HTML Token。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 23:25:54