子表达式的语法为
name:regex
在处理时,会把name加入进符号表中,方法是hash,最简单的加法
而在regex中如果碰到[name]这种模式,则尝试去找符号表,如果找不到则报错。
代码如下,欢迎大家测试。
#include <stdio.h> #include <malloc.h> #include <string.h> //这个版本允许定义正则子表达式,定义的时候以名字开头,然后是冒号,然后是正则表达式主体。 //在引用子表达式的时候,需要用中括号把子表达式括起来,因此中括号也跟其他操作符一样,作为保留字符 //目前还没有处理转义字符,再过几个版本吧。 int token[100]; int token_pointer; char reg_operator[100]; int reg_operator_pointer=0; int name_number=0; //注意这里name_number是全局的,而其他的几个栈及变量都是每个子表达式都复用的 //其实那些变量及栈可以每次申请一个,为了节省空间,我就懒得管了,直接复用。 int input_pointer=0; char reg_input[40];//由于命名表达式的存在,考虑加长字符,其实随便多大都可以处理。 enum reg_opera_type { parenthesis=1, kleen, cat, or, alias, literal_char };//正则节点类型 typedef struct _reg_pattern { enum reg_opera_type type; union { struct//对应二元操作符 { int left; int right; }; struct//对应假名 { int origin_number; int hash_table_number; }; char value;//对应字符值 int sub;//对应闭包运算符和括号运算符 }; }reg_pattern;//差不多当作抽象语法树吧 reg_pattern reg_pattern_table[100]; //当前的hash只使用加法hash加上一个模97,因为考虑到97是质数 typedef struct _hash_table//hash表类型 { enum _state { empty=0, in_use, deleted }state; char* name_of_alias; int reg_pattern_number; }hash_table; hash_table simple_hash_table[100]; int look_up_hash_table(char* source)//查询一个名字是否在hash表中 { int string_length; int counter; int index; int result; string_length=strlen(source); result=0; for(index=0;index<string_length;index++) { result+=*(source+index); } result=result%97; counter=0; while(counter<97)//顶多查询97次,如果查询达到了97次,则说明当前hash表中不存在这个字符串 { if(simple_hash_table[result].state==empty)//如果当前位置为空,说明不存在这个节点,直接返回-1 { return -1; } else { if(simple_hash_table[result].state==deleted)//如果为删除状态,则继续向下寻找,注意索引溢出的处理 { result=(result+1)%97; counter++; } else { if(strcmp(source,simple_hash_table[result].name_of_alias)==0)//如果出于使用状态,则开始比较 { return result;//名字相同则返回索引 } else//不同则继续向下寻找 { result+=(result+1)%97; counter++; } } } } return -1;//如果找了达到了97次,则返回-1 } int insert_hash_table(char* source,int index_of_reg_pattern) { int string_length; int counter; int index; int result; string_length=strlen(source); result=0; for(index=0;index<string_length;index++) { result+=*(source+index); } result=result%97; counter=0; while(counter<97) { if(simple_hash_table[result].state==in_use)//如果在使用中,则继续下次寻找 { result=(result+1)%97; counter++; } else//如果可用,则使用 { simple_hash_table[result].state=in_use; simple_hash_table[result].name_of_alias=source; simple_hash_table[result].reg_pattern_number=index_of_reg_pattern; return result; } } return -1;//已经满了 ,插入失败 } int is_begin_of_token() //判断输入字符是否可以当作一个token的开始符号,这样是为了处理非显示的连接符 { switch(reg_input[input_pointer]) { case '*': case '|': case '.': case ']': case ')': case '