简易正则表达式引擎
背景
正则表达式引擎一般通过构建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();
}
完整代码下载
已上传资源,不需要积分
分类:
数据结构&算法
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构