简易正则表达式引擎

背景

正则表达式引擎一般通过构建NFA/DFA实现, 关于该种实现方式,可以参考如下文章

https://www.codeproject.com/Articles/5412/Writing-own-regular-expression-parser

对于仅需要支持较少运算符等简单场景, 可以考虑一种更为简单的实现思路,这里以只需要支持

任意字符"."和任意次数重复字符"*" 2个符号来说明,并给出完整代码

实现方案介绍

将正则表达式按照结合关系进行一步组合切分, 不包含特定字符,只包含常规字符的自动结合到一起,而包含特定字符的组合到一起, 形成更大范围的状态单元, 处理时基本上可以按照顺序执行匹配即可.

举例: abc*ddd

那么自动组合为 [ab]->[c*]->[ddd]

abc.ufo  组合为  [abc]->[.]->[ufo]

示例代码按照TDD方式编写, 测试用例全部调通

写的过程中有些调整,没有再从头优化结构, 稍微有点冗余,程序还能简化

实现代码

核心入口类: LRegex

实现正则匹配

class LRegex
{
public:
    LRegex();
    ~LRegex();
    
    bool Match(const std::string& pattern, const std::string& s);
};

核心实现


bool LRegex::Match(const std::string& pattern, const std::string& s)
{
    StateMachine stateMachine;
    for(auto c : pattern)
    {
        if(!stateMachine.Input(c))
        {
            return false;
        }
    }
    cout << stateMachine.ToString() << endl;
    return stateMachine.Match(s);
}

状态机类 StateMachine, 用于管理流转状态

class StateMachine
{
public:
    StateMachine();
    ~StateMachine();

    bool Input(char c);

    bool Match(const std::string& s);

    std::string ToString() const;

private:
    std::deque<RegState*> regStateQue;
};

核心实现


bool StateMachine::Input(char c)
{
    if(regStateQue.empty())
    {
        RegState* regState = new RegState();
        regStateQue.push_back(regState);
        regState->pattern.Append(c);
        return true;
    }

    RegState* lastState = regStateQue.back();
    if(c == '.')
    {
        RegState* regState = new RegState();
        regStateQue.push_back(regState);

        regState->pattern.Append(c);
        lastState->nextStateList.push_back(regState);
    }
    else if(c == '*')
    {
        if(lastState->pattern.Length() == 1)
        {
            lastState->pattern.Append(c);
        }
        else
        {
            char baseChar = lastState->pattern.PopBack();
            RegState* regState = new RegState();
            regStateQue.push_back(regState);
            regState->pattern.Append(baseChar);
            regState->pattern.Append(c);
            lastState->nextStateList.push_back(regState);
        }
    }
    else if(!lastState->None() && !lastState->pattern.type.Normal())
    {
        RegState* regState = new RegState();
        regStateQue.push_back(regState);

        regState->pattern.Append(c);
        lastState->nextStateList.push_back(regState);
    }
    else
    {
        lastState->pattern.Append(c);
    }

    return true;
}

bool StateMachine::Match(const std::string& s)
{
    if(regStateQue.empty())
    {
        return true;
    }

    RegState* regState = regStateQue.front();
    size_t pos = 0;
    while(true)
    {
        int ret = regState->Match(s, pos);
        if(!regState->pattern.type.WithStar() && ret < 0)
        {
            return false;
        }

        if(regState->nextStateList.empty())
        {
            return true;
        }

        regState = regState->nextStateList.front();
        pos += ret;
    }
}

std::string StateMachine::ToString() const
{
    if(regStateQue.empty())
    {
        return "";
    }
    return regStateQue.front()->ToString();
}

状态类

每个状态能指向下一组可到达状态

class RegState
{
public:
    RegState();

    bool None() const;

    int Length() const;

    int Match(const std::string s, size_t pos) const;

    std::string ToString() const;
    
    std::vector<RegState*> nextStateList;

    Pattern pattern;a
    StateType stateType;
};

模式类

每个模式对应分开的一个单元子串


class Pattern
{
public:
    void Append(char c);

    char PopBack();

    PatternType type;

    std::string GetContent() const;

    unsigned int Length() const;

private:
    std::string content;
};

核心实现


void Pattern::Append(char c)
{
    if(c == '*')
    {
        if(type.Any())
        {
            type.SetAnyStar();
        }
        else if(type.Normal())
        {
            type.SetNormalStar();
        }
    }
    else if(c == '.')
    {
        type.SetAny();
    }
    else
    {
        type.SetNormal();
    }

    content += c;
}

std::string Pattern::GetContent() const
{
    return content;        
}

char Pattern::PopBack()
{
    char c = content.back();
    content.pop_back();
    return c;
}

unsigned int Pattern::Length() const
{
    return content.size();
}

完整代码下载

已上传资源,不需要积分

简易正则表达式实现源码-C++文档类资源-CSDN下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值