c实现极简单的正则表达式解析

来源:互联网 发布:淘宝开网店哪里进货 编辑:程序博客网 时间:2024/05/15 23:50

//c实现极简单的正则表达式解析

///////////////////////////////////////////////////////////////////////define 头文件///////////////////////////////////////////////////////////////////////

#ifndef _DEFINE_H_

#define _DEFINE_H_

#define REGEX_LENGTH 40

//typedef unsigned char uint8;

typedef enum
{
IS_LETTER_OR_NUMBER = 0x11, //字母或数字
IS_NUMBER = 0x22,           //数字
IS_RANGE = 0x33,            //范围
IS_SPECIAL_VALUE = 0x44,    //指定值
IS_ERROR_TYPE = 0XAA,       //错误类型
}valueType;

typedef struct _STRUCT_VALUE_TYPE_INFOR
{
valueType uType;
uint8 uRange[2];
}STRUCT_VALUE_TYPE_INFOR;

#endif

///////////////////////////////////////////////////////////////////////regex_analysis头文件///////////////////////////////////////////////////////////////////////

#ifndef _REGEX_ANALYSIS_H_

#define _REGEX_ANALYSIS_H_

#include "define.h"

enum COMPILE_ERROR
{
REGEX_SUCCESS = 0,
REGEX_ERROR,
REGEX_LENGTH_ERROR
};

uint8 compile_regex(uint8 * regex);
bool match_regex(const uint8 * data, uint8 uSum);

#endif

///////////////////////////////////////////////////////////////////////regex_analysis源文件///////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include "regex_analysis.h"
/*
说明:
这里的正则表达式解析是非常精简的处理,主要规则如下:
1.\w    表示字母(大、小)或数字
2.\d    表示数字
3.{n}   表示重复n次,n大于或等于1
4.[A-Z],[1-9],[a-z]分别表示具体范围
5.LN(B-2)E+D    直接列出字母、数字或包含在[0x20-0x7e]范围内ascii码值的表示列出内容本身
6.{n}{m}的写法是不被允许的
7.目前只支持如上列出的“元字符”
8.具体详细的规则可参照网上正则表达式的说明
*/

static STRUCT_VALUE_TYPE_INFOR g_stValueTypeInfor[REGEX_LENGTH];

void init_value_type_infor(void)
{
uint8 i = 0;

for(; i < REGEX_LENGTH; i++)
{
g_stValueTypeInfor[i].uType = IS_ERROR_TYPE;
g_stValueTypeInfor[i].uRange[0] = 0;
g_stValueTypeInfor[i].uRange[1] = 0;
}
}

//这里会把“编译”后的值信息放到g_stValueTypeInfor数组中
uint8 compile_regex(uint8 * regex)
{
uint8 *pRegex = regex;
uint8 uVINCount = 0;
uint8 uOffset = 0;
uint8 uOffsetSum = 0;

if(pRegex == NULL)
return REGEX_ERROR;

init_value_type_infor();

while(*pRegex != '\0')
{
switch(*pRegex)
{
case '\\':
{
if((pRegex[1] != 'w') && (pRegex[1] != 'd'))
return REGEX_ERROR;

if (pRegex[1] == 'w')
{
g_stValueTypeInfor[uVINCount].uType = IS_LETTER_OR_NUMBER;
}
else if (pRegex[1] == 'd')
{
g_stValueTypeInfor[uVINCount].uType = IS_NUMBER;
}

uVINCount += 1;
uOffset = 2;
}
break;
case '{':
{
uint8 n = 0;
uint8 i = 0;

if((!isdigit(pRegex[1])) || (pRegex[2] != '}'))//若{n}中不是数字则认为是错误的
return REGEX_ERROR;

if(uOffsetSum == 0)//{n}写在表达式的开头是错误的
return REGEX_ERROR;

if(regex[uOffsetSum - 1] == '}')//{n}{m}这样写是错误的
return REGEX_ERROR;

n = pRegex[1] - 0x30;

if(n == 0)
return REGEX_ERROR;

for (; i < n - 1; i++)
{
g_stValueTypeInfor[uVINCount - 1 + i + 1] = g_stValueTypeInfor[uVINCount - 1];//复制前一个
}

uVINCount += n - 1;
uOffset = 3;

}
break;
case '[':
{
if( !isalnum(pRegex[1]) ||(pRegex[2] != '-')
|| !isalnum(pRegex[3]) ||(pRegex[4] != ']'))//[A-Z] OR [0-9] or [a-z] 并不严格判断 [0-z] is ok
return REGEX_ERROR;


g_stValueTypeInfor[uVINCount].uType = IS_RANGE;
g_stValueTypeInfor[uVINCount].uRange[0] = pRegex[1];
g_stValueTypeInfor[uVINCount].uRange[1] = pRegex[3];

uVINCount += 1;
uOffset = 5;
}
break;
default:
{
if( !isprint(pRegex[0]) )//可打印字符[0x20-0x7e]
return REGEX_ERROR;

g_stValueTypeInfor[uVINCount].uType = IS_SPECIAL_VALUE;
g_stValueTypeInfor[uVINCount].uRange[0] = pRegex[0];

uVINCount += 1;
uOffset = 1;
}
break;

}//end switch

uOffsetSum += uOffset;
pRegex += uOffset;
}//end while

if(uVINCount > REGEX_LENGTH)
return REGEX_LENGTH_ERROR;

return REGEX_SUCCESS;
}
//正则表达式比较操作 data:待比较的数据源 uSum:待比较的数据长度
//true:ok false:fail
bool match_regex(const uint8 * data, uint8 uSum)
{
uint8 i = 0;

if(data == NULL)
return false;

while(i < uSum)
{
switch(g_stValueTypeInfor[i].uType)
{
case IS_LETTER_OR_NUMBER:
{
if( !isalnum(data[i]) )
return false;
}
break;
case IS_NUMBER:
{
if(!isdigit(data[i]))
return false;
}
break;
case IS_RANGE:
{
if((data[i] < g_stValueTypeInfor[i].uRange[0]) 
|| (data[i] > g_stValueTypeInfor[i].uRange[1]))
return false;
}
break;
case IS_SPECIAL_VALUE:
{
if(data[i] != g_stValueTypeInfor[i].uRange[0])
return false;
}
break;
default:
return false;

}//end switch

i += 1;

if(i == REGEX_LENGTH - 1)

return true;
}//end while

return true;
}

///////////////////////////////////////////////////////////////////////测试代码///////////////////////////////////////////////////////////////////////

#include "regex_analysis.h"
#include <Windows.h>
#include <stdio.h>
#include <string.h>

int main()
{
uint8 str[] = "(\\w\\w)4A S-E2\\w{6}[0-9]{5}";
uint8  VIN[] = "(LL)4A S-E2A2EJ1085732";//LL4ASE2A2EJ1085732

if(REGEX_SUCCESS == compile_regex(str) )
{
printf("compile success!\n");

if(match_regex(VIN,(uchar)strlen((char*)VIN)))
printf("match!\n");
else
printf("not match!\n");
}
else
printf("compile fail!\n");

system("pause");

return 0;
}

0 0
原创粉丝点击