Flex开发解析器示例(1)

  

通用单据处理支持主表修改,对于复杂数据类型,当仅主表数据的部分数据项改变时只同步这些已变化的字段,减少不必要的开销。
接口表记录变更的方式是记录每个变更字段的当前值。
每个字段的变更描述格式为:字段名=[值长度,属性,值]。
多个字段之间用逗号(",")分隔。

此格式可以避免转义问题(如值内容中出现"],"的情况).
属性目前用于区分是否是base64编码,这可用于binary类型字段的支持,可扩展。

字段类型在同步到目标库时根据数据库的结构信息决定,不需要在此指定。

 

以下为用Flex开发的解析变更字段表达式的解析器代码。

 

/* name: fld_list.y */


%option noyywrap
%x S_FIELDNAME
%x S_EQUEL
%x S_DATA_LEN
%x S_DATA_LEN2
%x S_DATA_PROP
%x S_DATA_PROP2
%x S_FIELDVAL
%x S_END

%{
#include <string.h>
#include <stdlib.h>
char *fld_name; /*字段名称
*/
unsigned int data_len = 0; /* 字段值长度
*/
int data_prop = 0; /*字段属性
*/
char *data_buffer; /* 字段值 */

#define MAX_FIELD_NAME_LEN  64

struct stFieldInfo {
 char *name;
 unsigned int len;
 int prop;
 char *buffer;
 
 struct stFieldInfo *next;
};

struct stFieldInfo  *field_list = 0;
struct stFieldInfo  *last_field = 0;
int add_field(struct stFieldInfo *fld);
%}


%%
[A-Za-z\_]+([A-Za-z\_]|[0-9])* {
 fld_name = strdup(yytext);
 BEGIN S_FIELDNAME;
}

<S_FIELDNAME>([" "\t])*"="([" "\t])*\[([" "\t])* {
 BEGIN S_EQUEL;
}

<S_EQUEL>[0-9]* {
 data_len = atoi(yytext);
 BEGIN S_DATA_LEN;
}
<S_DATA_LEN>([" "\t])*","([" "\t])* {
 BEGIN S_DATA_LEN2; 
}

<S_DATA_LEN2>[0-9]* {
 data_prop = atoi(yytext);
 BEGIN S_DATA_PROP;
}

<S_DATA_PROP>([" "\t])*","([" "\t])* {
 BEGIN S_DATA_PROP2; 
}

<S_DATA_PROP2>. {
 int c;
 int len = 0;
 char *p;
 data_buffer = malloc(data_len+1);
 data_buffer[0] = yytext[0];
 p = data_buffer;
 p++;
 len++;
 while(len<data_len&&(c=input())&&c!=EOF) {
  *p = c;
  p++;
  len++;
 }
 if (c==EOF||len<data_len)
  yyterminate();
 data_buffer[len] = '\0';

 BEGIN S_FIELDVAL;
}

<S_FIELDVAL>([" "\t])*\]([" "\t])*[,]? {
 struct stFieldInfo *fld = malloc(sizeof(struct stFieldInfo));
 fld->name = fld_name;
 fld->len = data_len;
 fld->prop = data_prop;
 fld->buffer = data_buffer;
 fld->next = 0;
 add_field(fld);
 
 BEGIN INITIAL;
}
. { ECHO; }

%%

int add_field(struct stFieldInfo *fld) {
  if (field_list==0) {
   field_list = fld;
   last_field = fld;
   return 0;
  }
  last_field->next = fld;
  last_field = fld;

  return 0;  
}

int print_fld_list() {
 int fld_num = 0;
 struct stFieldInfo *fld = field_list;
 while(fld!=0) {
  printf("name:%s, len=%d,prop=%d,data=%s.\n",fld->name,fld->len,fld->prop,fld->buffer);
  fld_num++;

  fld = fld->next;
 }
 printf("field_num:%d.\n",fld_num);

 return 0;
}

int main()
{
 char *str_input = "f123=[3,3,abc],f23=[5,1,xxxxx]";

 field_list = 0;
 last_field = 0;
 yy_scan_string(str_input);

 yylex();

 print_fld_list();

 getch();

 return 0;
}

 

 

 

此示例的输出为:

name:f123, len=3,prop=3,data=abc.
name:f23, len=5,prop=1,data=xxxxx.
field_num:2.

 

上述代码是不可重入的。

 

修改代码以支持多线程环境使用。修改后的代码如下(FLEX 2.5.35版本):

/* name: fld_list.y */

 

%option reentrant

%option noyywrap

%option extra-type="struct stWorkData*"

 

%x S_FIELDNAME

%x S_EQUEL

%x S_DATA_LEN

%x S_DATA_LEN2

%x S_DATA_PROP

%x S_DATA_PROP2

%x S_FIELDVAL

%x S_END

 

%{

 

#define YY_NO_UNISTD_H

#include <string.h>

#include <stdlib.h>

 

 

#define MAX_FIELD_NAME_LEN  64

 

struct stFieldInfo {

       char *name;

       unsigned int len;

       int prop;

       char *buffer;

      

       struct stFieldInfo *next;

};

 

struct stWorkData {

       char *fld_name; /*字段名称 */

       unsigned int data_len; /* 字段值长度*/

       int data_prop; /*字段属性*/

       char *data_buffer; /* 字段值 */

       struct stFieldInfo  *field_list;

       struct stFieldInfo  *last_field;

};

 

int add_field(struct stWorkData *wkdata,struct stFieldInfo *fld);

%}

 

FLDNAME [A-Za-z\_]+([A-Za-z\_]|[0-9])*

DELIM ([" "\t])*

NUMBERS [0-9]*

%%

{FLDNAME} {

       yyextra->fld_name = strdup(yyget_text(yyscanner));

       BEGIN S_FIELDNAME;

}

 

<S_FIELDNAME>{DELIM}"="{DELIM}\[{DELIM} {

       BEGIN S_EQUEL;

}

 

<S_EQUEL>{NUMBERS} {

       yyextra->data_len = atoi(yyget_text(yyscanner));

       BEGIN S_DATA_LEN;

}

<S_DATA_LEN>{DELIM}","{DELIM} {

       BEGIN S_DATA_LEN2;      

}

 

<S_DATA_LEN2>{NUMBERS}  {

       yyextra->data_prop = atoi(yyget_text(yyscanner));

       BEGIN S_DATA_PROP;

}

 

<S_DATA_PROP>{DELIM}","{DELIM} {

       BEGIN S_DATA_PROP2;    

}

 

<S_DATA_PROP2>. {

       int c;

       unsigned int len = 0;

       char *p;

       yyextra->data_buffer = malloc(yyextra->data_len+1);

       yyextra->data_buffer[0] = yyget_text(yyscanner)[0];

       p = yyextra->data_buffer;

       p++;

       len++;

       while(len<yyextra->data_len&&(c=input(yyscanner))&&c!=EOF) {

              *p = c;

              p++;

              len++;

       }

       if (c==EOF||len<yyextra->data_len)

              yyterminate();

       yyextra->data_buffer[len] = '\0';

 

       BEGIN S_FIELDVAL;

}

 

<S_FIELDVAL>{DELIM}\]{DELIM}[,]? {

       struct stFieldInfo *fld = malloc(sizeof(struct stFieldInfo));

       fld->name = yyextra->fld_name;

       fld->len = yyextra->data_len;

       fld->prop = yyextra->data_prop;

       fld->buffer = yyextra->data_buffer;

       fld->next = 0;

       add_field(yyextra,fld);

      

       BEGIN INITIAL;

}

. { ECHO; }

 

%%

 

int add_field(struct stWorkData *wkdata,struct stFieldInfo *fld) {

              if (wkdata->field_list==0) {

                     wkdata->field_list = fld;

                     wkdata->last_field = fld;

                     return 0;

              }

              wkdata->last_field->next = fld;

              wkdata->last_field = fld;

 

              return 0;             

}

 

int print_fld_list(struct stWorkData *wkdata) {

       int fld_num = 0;

       struct stFieldInfo *fld = wkdata->field_list;

       while(fld!=0) {

              printf("name:%s, len=%d,prop=%d,data=%s.\n",fld->name,fld->len,fld->prop,fld->buffer);

              fld_num++;

 

              fld = fld->next;

       }

       printf("field_num:%d.\n",fld_num);

 

       return 0;

}

 

int main()

{

    yyscan_t scanner;

       struct stWorkData wkdata;

 

       char *str_input = "f123=[3,3,abc],f23=[5,1,xxxxx]";

 

       wkdata.data_len = 0;

       wkdata.data_prop = 0;

       wkdata.field_list = 0;

       wkdata.last_field = 0;

 

    yylex_init ( &scanner );

       yylex_init_extra( &wkdata, &scanner );

       yy_scan_string(str_input,scanner);

 

    yylex ( scanner );

    yylex_destroy ( scanner );

 

       print_fld_list(&wkdata);

 

       getch();

 

       return 0;

}

 

   

  •   FLEX&Bison参考资料:

Lexical Analysis With Flex

http://flex.sourceforge.net/manual/

 

Bison Quick Tutorial

http://gps.nju.edu.cn:88/mediawiki/index.php/Bison_Quick_Tutorial

 

 

Flex 2.5.35 and Win32 / Visual C++

http://www.thebinaryidiot.com/archives/2011/01/29/flex-2-5-35-and-win32-visual-studio-cpp/

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值