最初步的正则表达式引擎
这里只是当作自己的代码版本管理器使用,并不去详细介绍代码,毕竟我的注释里面已经说明了很多。
欢迎大家测试,如果发现出错了,望在下面回复,多谢。
注意,当前的假定是输入自己不能有错误,而且*、(、)、.、|这几个操作符是保留字,其他的字符则当作其自身意思。当前不考虑转义字符及三元组,以及不考虑子表达式命名,因此只能处理一个长正则表达式。
1 #include <stdio.h> 2 #include <string.h> 3 #include <malloc.h> 4 //这里只处理最简单的正则表达式,即包括括号,星号运算,连接运算和分支运算,这里分支运算在压栈是是一个点号 5 //其中括号优先级最大,其次是星号运算其次是连接运算最后是分支运算 6 //当前版本只是把一个简单的正则表达式的优先级理清 7 #define STRICT 8 //strict 的意思就是不要求显示的写出.运算符 ,因为在缺少这个运算符的情况下,我们还是可以推断出来这个 9 //运算符是存在的 ,例如 在)及 *及非运算符之后如果存在字母则是缺少连接符,我们可以自己加上去 10 int is_operator(char for_in) 11 { 12 switch(for_in) 13 { 14 case'(': 15 case')': 16 case'.': 17 case'*': 18 case'|': 19 return 1; 20 default: return 0; 21 } 22 } 23 int main(void) 24 { 25 int token[100]; 26 int token_pointer; 27 char reg_operator[100]; 28 int reg_operator_pointer; 29 int name_number; 30 int input_pointer; 31 char reg_input[20]; 32 reg_operator_pointer=name_number=token_pointer=0; 33 for(input_pointer=0;input_pointer<100;input_pointer++)//初始化堆栈 34 { 35 reg_operator[input_pointer]='\0'; 36 token[input_pointer]=0; 37 } 38 input_pointer=0; 39 printf("please type in you regex short phrase\n"); 40 scanf("%s",reg_input); 41 while(*(reg_input+input_pointer)!='\0') 42 { 43 if(!is_operator(*(reg_input+input_pointer))) 44 { 45 name_number++; 46 token[token_pointer++]=name_number; 47 printf("name%d is %c\n",name_number,*(reg_input+input_pointer)); 48 input_pointer++; 49 #ifndef STRICT 50 if(!is_operator(*(reg_input+input_pointer))) 51 { 52 reg_operator[reg_operator_pointer++]='.'; 53 } 54 else 55 { 56 if(*(reg_input+input_pointer)=='(') 57 { 58 reg_operator[reg_operator_pointer++]='.'; 59 } 60 } 61 #endif 62 63 } 64 else//如果是操作符 65 { 66 if(reg_operator_pointer!=0)//如果当前栈中有操作符,则需要考虑不同操作符的优先级了 67 { 68 switch(*(reg_input+input_pointer)) 69 { 70 case '('://括号直接入栈,不需要其他操作 71 reg_operator[reg_operator_pointer++]='('; 72 input_pointer++; 73 break; 74 case ')': 75 if(reg_operator[reg_operator_pointer-1]=='(') 76 //如果两个括号匹配,则从操作符和运算数栈中分别弹出一个,然后再生成另外一个运算数入栈 77 { 78 name_number++; 79 printf("name%d is (name%d)\n",name_number,token[token_pointer-1]); 80 token[token_pointer-1]=name_number; 81 reg_operator_pointer--;//弹出匹配的括号 82 input_pointer++; 83 #ifndef STRICT 84 if(!is_operator(*(reg_input+input_pointer))) 85 { 86 reg_operator[reg_operator_pointer++]='.'; 87 } 88 else 89 { 90 if(*(reg_input+input_pointer)=='(') 91 { 92 reg_operator[reg_operator_pointer++]='.'; 93 } 94 } 95 #endif 96 break; 97 } 98 else//如果前面还有运算符,只有可能是连接和选择运算符 99 { 100 //对于这两种运算符,处理都是差不多的,不过还要考虑括号内有多个运算符的情况 101 //这时根据优先级只有可能是| .,不过第二个运算符我们留到第二次迭代的时候去处理 102 if(reg_operator[reg_operator_pointer-1]=='.') 103 { 104 name_number++; 105 printf("name%d is concat of name%d and name%d\n",name_number,token[token_pointer-1],token[token_pointer-2]); 106 token[token_pointer-2]=name_number; 107 token[token_pointer-1]=0; 108 token_pointer--; 109 reg_operator_pointer--; 110 reg_operator[reg_operator_pointer]='\0'; 111 break; 112 } 113 else 114 { 115 name_number++; 116 printf("name%d is name%d or name%d\n",name_number,token[token_pointer-1],token[token_pointer-2]); 117 token[token_pointer-2]=name_number; 118 token[token_pointer-1]=0; 119 token_pointer--; 120 reg_operator_pointer--; 121 reg_operator[reg_operator_pointer]='\0'; 122 break; 123 } 124 125 } 126 case '*': 127 //这个运算符优先级基本上是最高的,因此不需要入栈了,直接处理 128 name_number++; 129 printf("name%d is multiple of name%d\n",name_number,token[token_pointer-1]); 130 token[token_pointer-1]=name_number; 131 input_pointer++; 132 #ifndef STRICT 133 if(!is_operator(*(reg_input+input_pointer))) 134 { 135 reg_operator[reg_operator_pointer++]='.'; 136 } 137 else 138 { 139 if(*(reg_input+input_pointer)=='(') 140 { 141 reg_operator[reg_operator_pointer++]='.'; 142 } 143 } 144 #endif 145 146 break; 147 case '.': 148 //由于*运算符已经被直接处理了,所以只需要考虑其他的三个运算符 149 if(reg_operator[reg_operator_pointer-1]=='.') 150 //如果前面的那个运算符跟当前优先级相同,则处理前面的那个运算符 151 //这时字符栈要减一 152 { 153 name_number++; 154 printf("name%d is concat of name%d and name%d\n",name_number,token[token_pointer-2],token[token_pointer-1]); 155 token[token_pointer-2]=name_number; 156 token_pointer--; 157 reg_operator[reg_operator_pointer-1]='.'; 158 input_pointer++; 159 break; 160 } 161 else 162 //其他情况则直接入栈就行,留到下次来判断优先级处理 163 { 164 reg_operator[reg_operator_pointer++]='.'; 165 input_pointer++; 166 break; 167 } 168 case '|': 169 if(reg_operator[reg_operator_pointer-1]!='(')//括号另外说 170 { 171 name_number++; 172 if(reg_operator[reg_operator_pointer-1]=='.') 173 //如果前面的优先级比当前的高,则处理前面的优先级 174 { 175 printf("name%d is concat of name%d and name%d\n",name_number,token[token_pointer-2],token[token_pointer-1]); 176 } 177 else 178 //这里处理的是相同优先级的情况,其实这里可以与前面的合并的,只不过打印信息不同 179 { 180 printf("name%d is name%d or name%d\n",name_number,token[token_pointer-2],token[token_pointer-1]); 181 } 182 token[token_pointer-2]=name_number; 183 token_pointer--; 184 reg_operator[reg_operator_pointer-1]='|'; 185 input_pointer++; 186 break; 187 } 188 else 189 { 190 reg_operator[reg_operator_pointer++]='|'; 191 input_pointer++; 192 break; 193 } 194 default: 195 printf("error\n"); 196 break; 197 } 198 } 199 else//在当前操作符栈中没有符号的时候 200 { 201 if(reg_input[input_pointer]!='*') 202 //由于*优先级最高,而且是左结合的,所以不需要入栈了 203 //对于其他的操作符则需要入栈 204 { 205 reg_operator[reg_operator_pointer++]=reg_input[input_pointer++]; 206 #ifndef STRICT 207 if(!is_operator(*(reg_input+input_pointer))) 208 { 209 reg_operator[reg_operator_pointer++]='.'; 210 } 211 else 212 { 213 if(*(reg_input+input_pointer)=='(') 214 { 215 reg_operator[reg_operator_pointer++]='.'; 216 } 217 } 218 #endif 219 220 } 221 else 222 { 223 name_number++; 224 printf("name%d is the multiple of name%d\n",name_number,token[token_pointer-1]); 225 token[token_pointer-1]=name_number; 226 input_pointer++; 227 } 228 } 229 } 230 } 231 if(reg_operator_pointer==1)//如果全部的输入都弄完了,可是 操作符栈中还有数据,则输出 232 { 233 if(reg_operator[reg_operator_pointer]=='.') 234 { 235 name_number++; 236 printf("name%d is cancat of name%d and name%d\n",reg_operator[0],token[0],token[1]); 237 } 238 else 239 { 240 name_number++; 241 printf("name%d is name%d or name%d\n",reg_operator[0],token[0],token[1]); 242 } 243 } 244 }