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

如何在不修改原有正则的前提下让Flex正确识别表达式中的.:

问题描述

现有一个Lex文件,需添加对.:的识别支持,已完成初步修改,代码如下:

%option caseless

ALP     [a-z]+
NUM     [0-9]+
REF     {ALP}{NUM}

_NAME_0     [^\-\^\]`~!@#$%&*()+=|{}[;:'",<>/ .1234567890?\n]
_NAME_1     {_NAME_0}|[0-9.?]
NAME        {_NAME_0}{_NAME_1}*

OP_1        ":"
OP_2        ".:"

T       (" "|\n)*

%s S1 S2

%%
<S1>{
    {T}{OP_1} { printf(": "); }
    {T}{OP_2} { printf(".: "); }
    {T}{NAME} {
        BEGIN(S2);
        yyless(0);
    }
}

<S2>{
    {T}{REF} { printf("tokRef "); BEGIN(S1); }
    {T}{NAME} { printf("tokName "); BEGIN(S1); }
}
%%

int main() {
    BEGIN(S1);
    yylex();
    return 0;
}

int yywrap() { return 1; }

当前规则对部分输入的解析结果如下:

input               output
a1:b1        -->    tokRef : tokRef
a1   : b1    -->    tokRef : tokRef
a1.  : b1    -->    tokName : tokRef
a1  .: b1    -->    tokRef .: tokRef

a1.:b1       -->    tokName : tokRef

其中最后一条输入a1.:b1的输出不符合预期,期望结果为:

a1.:b1       -->    tokRef .: tokRef

因应用限制,原有正则表达式定义(如REF、NAME、OP_1、T)不可修改,需通过修改新增的OP_2或状态机规则实现预期效果。

解决方案

可以通过在<S1>状态下新增一条优先匹配{REF}{OP_2}的规则来解决问题,利用Lex的最长匹配优先级特性,让a1.:这类输入被优先识别为REF+OP_2,而非被NAME规则误匹配为a1.。

修改后的<S1>状态规则如下:

<S1>{
    {T}{OP_1} { printf(": "); }
    {T}{OP_2} { printf(".: "); }
    {T}{REF}{OP_2} { printf("tokRef .: "); BEGIN(S1); }
    {T}{NAME} {
        BEGIN(S2);
        yyless(0);
    }
}

原理说明

  1. 当输入为a1.:b1时,新增的{T}{REF}{OP_2}规则会匹配整个a1.:片段(匹配长度为4),比NAME规则匹配a1.(长度为3)更长,因此会被优先触发,直接输出tokRef .: 。
  2. 剩余的b1会进入<S2>状态,被REF规则识别为tokRef,最终得到预期输出。
  3. 原有其他输入的解析逻辑不受影响:
    • a1. : b1中a1.与: 之间有空格,不会触发新增规则,仍按原逻辑输出tokName : tokRef;
    • a1 .: b1中a1与.:之间有空格,会先在<S2>识别a1为tokRef,再在<S1>识别.:为.: ,输出不变。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 22:35:53