??xml version="1.0" encoding="utf-8" standalone="yes"?>狠狠色丁香久久综合婷婷,久久99精品免费一区二区,国内精品人妻无码久久久影院导航http://www.shnenglu.com/Plator/category/7159.html学术讨论博客zh-cnWed, 28 May 2008 07:25:14 GMTWed, 28 May 2008 07:25:14 GMT60W一ơ用flexhttp://www.shnenglu.com/Plator/archive/2008/05/28/51366.html菊馨菊馨Wed, 28 May 2008 02:47:00 GMThttp://www.shnenglu.com/Plator/archive/2008/05/28/51366.htmlhttp://www.shnenglu.com/Plator/comments/51366.htmlhttp://www.shnenglu.com/Plator/archive/2008/05/28/51366.html#Feedback1http://www.shnenglu.com/Plator/comments/commentRss/51366.htmlhttp://www.shnenglu.com/Plator/services/trackbacks/51366.htmll老师介绍Q而且最q进行实验二Q将正则表达式{换ؓDFAQ然后{换ؓ代码Q想做一个类gflex的YӞ觉得flex很奇妙,输入一个正则表辑ּp够输出对应的扫描E序Q这也开始真正体现老师说的自动化。我一直对计算机的一个终极问题(“什么能够被有效地自动化”Q很感兴,因此惛_?/span>flex开始对q方面有Ҏ性的认识Q?/span>

在网上搜?/span>flexQ安?/span>flexQ先下蝲flexQ原本打放上来的,但是考虑到版权的问题Q还是不要了。需要的朋友Q我可以发给你)Q然后按照默认的步骤逐步安装?/span>

安装后,讄环境变量Q将Path指向flex.exe所在的文g夹(本机上ؓQ?/span>C:\Program Files\GnuWin32\binQ一般按默认方式安装?/span>flex.exe都在该文件夹内)Q具体步骤:

→?#8220;我的电脑”图标按右?#8594;选择“属?#8221;→选择“高”→单击“环境变量”→?#8220;pȝ变量”中查?/span>Path,q择?#8594;?#8220;~辑”→?#8220;变量?#8221;的最后一Ҏ?#8220;;C:\Program Files\GnuWin32\bin”Q按定完成?/span>


最q我是先从课?/span>TINY语言开始,TINY语言?/span>lex文g在源代码?/span>LEX文g夹内

1.       ?/span>tiny.l的最后添加:

int yywrap()

{

return 1;

}

用来l束扫描

2.       ?/span>console上输?/span>flex tiny.lQ生?/span>lex.yy.cQ将其替?/span>scan.cQ编译链接生?/span>tiny的编译器?/span>

 

参考文献:

http://course.cugnc.com/bianyi/shiyan/CHAPTER/f1.htm

http://blog.csdn.net/litchh/archive/2004/07/14/40983.aspx

http://www.cnscn.org/read.php?tid-10862.html



菊馨 2008-05-28 10:47 发表评论
]]>
MFC与LEX l合要注意的问题http://www.shnenglu.com/Plator/archive/2008/05/24/50983.html菊馨菊馨Sat, 24 May 2008 15:33:00 GMThttp://www.shnenglu.com/Plator/archive/2008/05/24/50983.htmlhttp://www.shnenglu.com/Plator/comments/50983.htmlhttp://www.shnenglu.com/Plator/archive/2008/05/24/50983.html#Feedback0http://www.shnenglu.com/Plator/comments/commentRss/50983.htmlhttp://www.shnenglu.com/Plator/services/trackbacks/50983.html׃flex往往为我们生成的?/span>C代码Q?/span>lex.yy.cQ,而实际上我们通常要把它们应用?/span>C++中,特别是应用到Windows应用E序中来Q在MFC工程下构造词法分析程序?/span>

我们往往只是生的lex.yy.c直接d?/span>MFC工程完事,但是~译Ӟ׃各种各样的原因,而生大量的语法错误Q难以修攏V本人最q在MFC下构造一个扩?/span>TINY语言的词法分析也是遇C一些问题,查阅了大量资料(已经主要的参考资料放?/span>lex学习栏目上,LQ?a href="http://www.shnenglu.com/Plator/category/7159.html">http://www.shnenglu.com/Plator/category/7159.htmlQ,耗费了我两天的时间解册些问题。因此我惛_本文Q将把一些注意问题叙q如下,希望对一些朋友有所帮助?/span>

 

1.       要将lex.yy.c改ؓCPP文gQ?/span>lex.yy.cpp。因?/span>MFC?/span>C++工程Q若不修改则会出现错误;

2.       ?/span>#include <stdio.h>改ؓ#include <stdafx.h>Q不然会出现如下错误Q?/span>unexpected end of file while looking for precompiled header directiveQ?/span>

3.       ?/span>flex安装目录?/span>include文g夹的unistd.hd?/span>MFC工程内,q修?/span>#include <unistd.h>#include "unistd.h"。因?/span>unistd.h文g中定义了词法分析需要用C些头文g?/span>

4.       如果lex源文仉要用inputd字符Q则应该换用yyinputQ因?/span>input会与C++中的名词重复,会出现编译错误;

5.       注意一?/span>I/O例程的应用,具体误Q?a href="http://www.shnenglu.com/Plator/archive/2008/05/24/50940.html">http://www.shnenglu.com/Plator/archive/2008/05/24/50940.html

 

只是短短几个错误Q但是解决的q程参考了大量资料Q虽然不知道q些资料何h之手Q但是在此感谢这些作者!



菊馨 2008-05-24 23:33 发表评论
]]>
Lex 入门 [转蝲]http://www.shnenglu.com/Plator/archive/2008/05/24/50982.html菊馨菊馨Sat, 24 May 2008 15:28:00 GMThttp://www.shnenglu.com/Plator/archive/2008/05/24/50982.htmlhttp://www.shnenglu.com/Plator/comments/50982.htmlhttp://www.shnenglu.com/Plator/archive/2008/05/24/50982.html#Feedback0http://www.shnenglu.com/Plator/comments/commentRss/50982.htmlhttp://www.shnenglu.com/Plator/services/trackbacks/50982.htmlFirst!
lexE序的结构是q样的!

定义
%%
规则
%%
用户代码

 

一?Lex E序分ؓ三个D:W一D| C ?Lex 的全局声明Q第二段包括模式QC 代码Q,W三D|补充?C 函数?q些D以%%来分界?下面是一个行C字数的统计工兗?/p>


        int num_lines = 0, num_chars = 0;
 %%
\n      ++num_lines; ++num_chars;
.       ++num_chars;

%%
main()
        {
        yylex();
        printf( "# of lines = %d, # of chars = %d\n",
                num_lines, num_chars );
        }

 

Second!
对First内容的回?
C ?Lex 的全局声明
q一D中我们可以增加 C 变量声明。这里我们将为字数统计程序声明一个整型变量,来保存程序统计出来的字数。我们还进?Lex 的标记声明?

字数l计E序的声?/p>

       %{
        int wordCount = 0;
        %}
        chars [A-za-z\_\'\.\"]
        numbers ([0-9])+
        delim [" "\n\t]
        whitespace {delim}+
        words {chars}+
        %%

 

两个癑ֈh记指Z Lex E序中这一D늚l束和三D中W二D늚开始?

Lex 的模式匹配规?
让我们看一?Lex 描述我们所要匹配的标记的规则。(我们?C 来定义标记匹配后的动作。)l箋看我们的字数l计E序Q下面是标记匚w的规则?
字数l计E序中的 Lex 规则

       {words} { wordCount++; /*
        increase the word count by one*/ }
        {whitespace} { /* do
        nothing*/ }
        {numbers} { /* one may
        want to add some processing here*/ }
        %%

 
C 代码
Lex ~程的第三段Q也是最后一D覆盖了 C 的函数声明(有时是主函数Q。注意这一D必d?yywrap() 函数?Lex 有一套可供用的函数和变量?其中之一是 yywrap。一般来_yywrap() 的定义如下例。我们将?高 Lex 中探讨这一问题?
字数l计E序?C 代码D?/p>

       void main()
        {
        yylex(); /* start the
        analysis*/
        printf(" No of words:
        %d\n", wordCount);
        }
        int yywrap()
        {
        return 1;
        }

 

Lex ~程的基本元素就q样搞定了,它将帮助你编写简单的词法分析E序?
Third
高Lex
Lex 有几个函数和变量提供了不同的信息Q可以用来编译实现复杂函数的E序。下表中列出了一些变量和函数Q以及它们的使用?详尽的列表请参?Lex 手册?
Lex 变量
   yyin  FILE* cd?它指?lexer 正在解析的当前文件?br>   yyout FILE* cd?它指向记?lexer 输出的位|?~省情况下,yyin ?yyout 都指向标准输入和输出?br>   yytext 匚w模式的文本存储在q一变量中(char*Q?br>   yyleng l出匚w模式的长度?br>   yylineno 提供当前的行C息。(lexer不一定支持。)

Lex 函数
   yylex() q一函数开始分析?它由 Lex 自动生成?br>   yywrap() q一函数在文Ӟ或输入)的末调用。如果函数的q回值是1Q就停止解析?因此它可以用来解析多个文件。代码可以写在第三段Q这p够解析多个文件?Ҏ是?yyin 文g指针Q见上表Q指向不同的文gQ直到所有的文g都被解析。最后,yywrap() 可以q回 1 来表C析的l束?br>   yyless(int n) q一函数可以用来送回除了?n? 个字W外的所有读出标记?br>   yymore() q一函数告诉 Lexer 下一个标记附加到当前标记后?
到此为止Q可能你看到lexE序q会范晕Q没关系Q下面我们接着来,分析一个类pascal语法的极析器Q?
/* q个是注释?/
  /* scanner for a toy Pascal-like language */
x部分开?br>%{ 内的东西会原不动地出现在输出文件中 }%

  %{
     /* need this for the call to atof() below */
     #include <math.h>
  %}
  DIGIT    [0-9]
  ID       [a-z][a-z0-9]*
  %%
模式部分开?
  {DIGIT}+    {
    printf( "An integer: %s (%d)\n", yytext,
    atoi( yytext ) );
  }
  {DIGIT}+"."{DIGIT}*        {
    printf( "A float: %s (%g)\n", yytext,
    atof( yytext ) );
  }
  if|then|begin|end|procedure|function        {
    printf( "A keyword: %s\n", yytext );
  }
  {ID}        printf( "An identifier: %s\n", yytext );
  "+"|"-"|"*"|"/"   printf( "An operator: %s\n", yytext );
  "{"[^}\n]*"}"     /* eat up one-line comments */
  [ \t\n]+          /* eat up whitespace */
  .           printf( "Unrecognized character: %s\n", yytext );
  %%
补充部分开?
  main( argc, argv )
   int argc;
   char **argv;
  {
    ++argv, --argc;  /* skip over program name */
    if ( argc > 0 )
      yyin = fopen( argv[0], "r" );
    else
      yyin = stdin;
    yylex();
  }
惌真正了解lex, [[正则表达式]] 是关?
Four
yytext 匚w模式的文本存储变? 可以通过在申明阶D?pointer?array来控制是一个字W指针还是一个字W数l。指针模式与数组模式各有特点Q导致在yytexx上也不一P具体请参考lex手册Q?
在模式阶D中

  模式            动作
  [ \t]+        putchar( ' ' );
  [ \t]+$       /* ignore this token */

模式部分是正则表辑ּQ动作部分是处理ҎQ动作部分如果时{开_那么Q动作将会持l到},如果动作中出C括号{},开始采?%{ %}来表C动作去区段。动作部分如果时 |,pCZ下一条规则执行相同的动作?
好的Q我们来看一个更为实用一点的lexE序?br>我们先定义三个动?
ECHO yytext输出
BEGIN 开始一个条件处理块
REJECT 指示析器对当前规则不做处理,而是采用W二匚w规则?
  int word_count = 0;
  %%
  frob        special(); REJECT;
  [^ \t\n]+   ++word_count;
如果frob没有REJECT动作Qfrob不会被计数Q因析器在通常情况下,每个被匹配的对象只会对一个动作生效,多个REJECT也是允许的,会寻找下一个最配的规则来做处理。所以,下面的规则会把输入的"abcd"处理后输?abcdabcaba".
  %%
  a        |
  ab       |
  abc      |
  abcd     ECHO; REJECT;
  .|\n     /* eat up any unmatched character */

`yymore()' 告诉解析器下一ơ匹配的规则Q满的部分会d到当前yytext值得后面而不是替换它?例如Q指定的输入"mega-kludge"l过下面的程序处理后会输出"mega-mega-kludge"?
  %%
  mega-    ECHO; yymore();
  kludge   ECHO;
W一?"mega-" 被满_ƈ且输? 然后 "kludge" 满, 但是q没有替换之前的"mega-"而是"kludge"附加C的后面,然后输出的其实是"mega-kludge".
yymore()需要两件事情需要注意。第一Qyymnore()依赖于表现当前匹配项的长度yyleng的|所以用yymore不允许改变yyleng的倹{第二,yymore()的用会使解析器付出一点点性能的代仗?
有yymore()有yyless()
yyless(n) q回当前匚ww了开始的n个字W内的所有的内容到输入缓存区Q解析器处理下一个匹配时Q它们将会被重新解析。yyless会Dyytext与yyleng的调整。(yyleng会{于=nQ?如输?foobar"被下面的E序处理后,会输出"boobarbar". 因ؓ前n=3个字Wfoo外的字符bar被重新返回到输入~存Z?
  %%
  foobar    ECHO; yyless(3);
  [a-z]+    ECHO;
参数0对于yyless会D整个当前匚w会被重新解析。除非你改变了解析器本来的处理流E?如用begin),q将会导致@环结束。需要注意的是,yyless是一个宏Qƈ且在flex输入文g中用,不能在其他源文g中用?
unput(c) 字Wc攑֛到输入流中,该字W可以重新被解析。下面的动作当前的匚w值附上括号后重新q行匚w?
 {
  int i;
  /* Copy yytext because unput() trashes yytext */
  char *yycopy = strdup( yytext );
  unput( ')' );
  for ( i = yyleng - 1; i >= 0; --i )
    unput( yycopy[i] );
  unput( '(' );
  free( yycopy );
 }
注意: ׃每次unput()指定的字符d到输入源的开_所以将字符串添加到输入源开头必M后道前处理。一个比较重要的潜在问题是用unput()的时候,如果采用?pointer指针模式保存yytext,unput会破坏yytext的内容,从最双的字W开始将会破坏左边的一个字W。如果在unput()后要用到yytext,你首先必d制一份yytext,或者用%array模式来保存yytext. 最后你不能放一个EOF去试图标志输入流的结束?
input 从输入源中读取下一个字W。例如,下面有的例子会吃掉C语言注释

  %%
  "/*"        {
            register int c;
            for ( ; ; )
                {
                while ( (c = input()) != '*' &&
                        c != EOF )
                    ;    /* eat up text of comment */
                if ( c == '*' )
                    {
                    while ( (c = input()) == '*' )
                        ;
                    if ( c == '/' )
                        break;    /* found the end */
                    }
                if ( c == EOF )
                    {
                    error( "EOF in comment" );
                    break;
                    }
                }
            }

注意: 如果析器采用用C++~译Qinput()被yyinput()的替代,因ؓinput()与C++中的名Uinput冲突?
YY_FLUSH_BUFFER h解析器内部缓存以便于下一ơ的匚w工作Q首先它会用YY_INPUT填充~存区。这是通用yy_flush_buffer()的一个特例,会在多输入~存中描q?
yyterminate()可以在动作内部返回描q区域中使用Q它终止解析器q返?l解析器调用者,表示操作完成。缺省情况下Q到达文件结束位|也会被调用Q它是一个宏Qƈ且可能重定义?/p>


Lexq阶
模式
模式在第一阶段或第二个阶段使用Q也是在申明或规则阶段中出玎ͼ模式定义了匹配的目标Q目标被匚w后将会执行动作?br>对于模式不想做太多说明,使用正则表达式定义,可以参看 regex ?pcre.

开始条?br>lex提供了根据条件激z规则的机制。在<sc>前缀的规则将会在解析器在"sc"的开始条件下被匹配?/p>

<STRING>[^"]*        { /* eat up the string body ... */            ...            }
会在启动条?STRING"的情况下被激zR?/p>

<INITIAL,STRING,QUOTE>\.        { /* handle an escape ... */            ...            }
会?"INITIAL", "STRING", "QUOTE"三者之一的条件下被激zR?/p>

开始条件在输入源的定义(W一Q部分被xQ在‘%s' ?’%x'后跟随着名字列表?%sx了包含的开始条Ӟ%xx了排他的开始条件。开始条件被BEGIN动作ȀzR直C一个BEGIN动作Q满_始条件名U的规则会被规则,不满_动条件的规则不会被执行?/p>


如果是包含条Ӟ没有开始条件的规则也会被激zL行,如果时排他条Ӟ只有满开始条件的规则才会被执行?/p>

h相同排他条g的规则的集合可以使解析器独立于其他的规则。因此,排他条g可以Ҏ地创建微型解析器处理输入源中的独立与其他部分的一部分Q如Q注释)。如果对于包含与排他条gq有hQ可以看下面的例子?/p>

%s example%%<example>foo   do_something();bar            something_else();
{同?/p>


%x example%%<example>foo   do_something();<INITIAL,example>bar    something_else();
上面的程序中如果没有<INITIAL,example>Q在example条g下bar规则永q不会被ȀzR如果?lt;example>Q将会导致只能在exmaple开始条件下Ȁz,而INITIAL条g下不会被ȀzR而第一个程序中在Q何条件下bar都被会激zR因为第一个程序用example?sQ时包含条g。页可以通过Ҏ开始条?lt;*>来配|Q何开始条Ӟ上面的程序还可以写ؓQ?/p>

%x example%%<example>foo   do_something();<*>bar    something_else();
~省规则Q显CZQ何未被匹配的字符Q在开始条件下仍然生效。等同于Q?/p>

<*>.|\\n     ECHO;
‘BEGIN(0)’在无开始条件的规则ȀzL件下q回原始状态,q个状态同于开始条件下?INITIAL',所?#8216;BEGIN(INITIAL)'{同?#8217;BEGIN(0)'?br>BEGIN行ؓ在规则部分的开头是默认的代码(BEGIN actions can also be given as indented code at the beginning of the rules section.L译)例如Q下面的代码会仅需SPECIAL开始条Ӟ不管合适yylex()被调用ƈ且全局变量enter_special是true?/p>

        int enter_special;%x SPECIAL%%        if ( enter_special )            BEGIN(SPECIAL);<SPECIAL>blahblahblah...more rules follow...
Z说明开始条Ӟ我们用两U方法处?123.456".~省会被解析ؓ '123','.','456'三个标记Q如果expect-floats后面会被解析ؓ点?123.456

%{#include <math.h>%}%s expect%%expect-floats        BEGIN(expect);<expect>[0-9]+"."[0-9]+      {            printf( "found a float, = %f\n",                    atof( yytext ) );            }<expect>\n           {            /* that's the end of the line, so             * we need another "expect-number"             * before we'll recognize any more             * numbers             */            BEGIN(INITIAL);            }[0-9]+      {            printf( "found an integer, = %d\n",                    atoi( yytext ) );            }"."         printf( "found a dot\n" );
下面的代码能够是被C语言注释q且l计行数?/p>

%x comment%%        int line_num = 1;"/*"         BEGIN(comment);<comment>[^*\n]*        /* eat anything that's not a '*' */<comment>"*"+[^*/\n]*   /* eat up '*'s not followed by '/'s */<comment>\n             ++line_num;<comment>"*"+"/"        BEGIN(INITIAL);
实际上,~写高速解析程序的办法时在每个规则中做可能多的匹配?/p>

This scanner goes to a bit of trouble to match as much text as possible with each rule. In general, when attempting to write a high-speed scanner try to match as much possible in each rule, as it's a big win.

注意: 开始条件的名字实际上时一个整形值ƈ且能够被保存Q所以,上面的代码可以扩展ؓQ?/p>

%x comment foo%%        int line_num = 1;        int comment_caller;"/*"         {             comment_caller = INITIAL;             BEGIN(comment);             }...<foo>"/*"    {             comment_caller = foo;             BEGIN(comment);             }<comment>[^*\n]*        /* eat anything that's not a '*' */<comment>"*"+[^*/\n]*   /* eat up '*'s not followed by '/'s */<comment>\n             ++line_num;<comment>"*"+"/"        BEGIN(comment_caller);
而且Q可能易使用YY_START宏来讉K当前的开始条件。如上面的赋值条件可以改写ؓ

comment_caller = YY_START

YYSTATE是YY_START的别名(因ؓAT&T lex使用了YYSTATEQ?br>注意 开始条件没有他们的名字I间; %s ?%x x?#define形式一栗?/p>

到这里,时一个用排他开始条件如何匹配C风格的引用字W串的处理。包含的扩展的{义,但不包括查,因ؓ代码太长?/p>

%x str%%        char string_buf[MAX_STR_CONST];        char *string_buf_ptr;\"      string_buf_ptr = string_buf; BEGIN(str);<str>\"        { /* saw closing quote - all done */        BEGIN(INITIAL);        *string_buf_ptr = '\0';        /* return string constant token type and         * value to parser         */        }<str>\n        {        /* error - unterminated string constant */        /* generate error message */        }<str>\\[0-7]{1,3} {        /* octal escape sequence */        int result;        (void) sscanf( yytext + 1, "%o", &result );        if ( result > 0xff )                /* error, constant is out-of-bounds */        *string_buf_ptr++ = result;        }<str>\\[0-9]+ {        /* generate error - bad escape sequence; something         * like '\48' or '\0777777'         */        }<str>\\n  *string_buf_ptr++ = '\n';<str>\\t  *string_buf_ptr++ = '\t';<str>\\r  *string_buf_ptr++ = '\r';<str>\\b  *string_buf_ptr++ = '\b';<str>\\f  *string_buf_ptr++ = '\f';<str>\\(.|\n)  *string_buf_ptr++ = yytext[1];<str>[^\\\n\"]+        {        char *yptr = yytext;        while ( *yptr )                *string_buf_ptr++ = *yptr++;        }
通常Q如上面的例子中所看到你,会有许多相同开始条件的处理。开始条件范围可以简化重复操作?/p>


<SCs>{}
SCs 是一个或开始条件的列表。在q个开始条件范围内Q每个规则将会自动具有前~ `<SCs>' 直到 `}' 与开始的 `{' 匚w.  例如

<ESC>{    "\\n"   return '\n';    "\\r"   return '\r';    "\\f"   return '\f';    "\\0"   return '\0';}
{h?

<ESC>"\\n"  return '\n';<ESC>"\\r"  return '\r';<ESC>"\\f"  return '\f';<ESC>"\\0"  return '\0';
开始条仉可以嵌套Q下面时三个理开始条件堆栈的参数?

`void yy_push_state(int new_state)'
当前的开始条件压栈,切换?new_state 与?`BEGIN new_state'cM?
`void yy_pop_state()'
从栈弹出,cM?BEGIN.
`int yy_top_state()'
q回栈顶|不改变栈内容?
开始条件栈动态增长,没有固定限制Q如果内容用,E序竟会l止?

Z使用开始条件栈Q需要?`%option stack' 指o?

 


多输入缓存区

 

一些允许include文g解析器的解析器要求从几个输入中d内容。YY_INPUT只在l束~存时被调用Q碰?include 后需要切换输入源Q而解析一个描qC讔R要很长时间。ؓ了解xc问题,解析器提供了创徏q在多个输入~存中创建的机制。输入缓存可以通过下面的方式创?

YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )


参数Z~存兌的输入文件指针,以及_的可l持size字符Q如果不定Qsize可以使用YY_BUF_SIZE)。返回一个YY_BUFFER_STATE,可以传递到其他的处理过E。YY_BUFFER_STATE是一个不可见l构yy_buffer_state的指针,所以可以安全地使用`((YY_BUFFER_STATE) 0)'来初始化YY_BUFFER_STATEQ如果你愿意Q你可以在解析器之外的源E序中引用这个不透明l构来正的x输入~存。可以通过下面的参数来选择一个缓存区?

void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )


切换解析器的输入~存会D记接下来的匹配项来自于新的缓存中。yy_switch_to_buffer可能出现在yywrap中ؓl箋解析做准备,替换打开一个新的文件ƈ执行yyin. 通过yy_switch_to_buffer ?yywrap切换输入源不改变开始条件?

 

void yy_delete_buffer( YY_BUFFER_STATE buffer )


用于收回与缓存关联的I间。你可以使用下面的函数清I当前内?

void yy_flush_buffer( YY_BUFFER_STATE buffer )


此函数废弃缓存内容,下一个解析器试图匚w一个内Ҏ会使用YY_INPUT来更新缓存区?/p>

`yy_new_buffer()' ?`yy_create_buffer()' 的一个别名,用于提供C++使用new ?delete操作创徏与销毁动态对象的兼容性?/p>

最? YY_CURRENT_BUFFER 宏返?YY_BUFFER_STATE 指针Q表C当前的~存?/p>

q里是一个扩展include使用的一个解析器 (`<<EOF>>' Ҏ将会在以后讨论):


/* "incl" 状态用于获取include的文件名 */
%x incl

%{
#define MAX_INCLUDE_DEPTH 10
YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
int include_stack_ptr = 0;
%}

%%
include             BEGIN(incl);

[a-z]+              ECHO;
[^a-z\n]*\n?        ECHO;

<incl>[ \t]*      /* eat the whitespace */
<incl>[^ \t\n]+   { /* got the include file name */
        if ( include_stack_ptr >= MAX_INCLUDE_DEPTH )
            {
            fprintf( stderr, "Includes nested too deeply" );
            exit( 1 );
            }

        include_stack[include_stack_ptr++] =
            YY_CURRENT_BUFFER;

        yyin = fopen( yytext, "r" );

        if ( ! yyin )
            error( ... );

        yy_switch_to_buffer(
            yy_create_buffer( yyin, YY_BUF_SIZE ) );

        BEGIN(INITIAL);
        }

<<EOF>> {
        if ( --include_stack_ptr < 0 )
            {
            yyterminate();
            }

        else
            {
            yy_delete_buffer( YY_CURRENT_BUFFER );
            yy_switch_to_buffer(
                 include_stack[include_stack_ptr] );
            }
        }


提供三个q程来实现内存字W串而不是文件输入缓存的解析。它们都要创Z个输入缓存来解析字符Ԍq且q回YY_BUFFER_STATE (可以在完成解析后?`yy_delete_buffer()' 删除).Q也可以通过`yy_switch_to_buffer()'来切? 下一ơ调用`yylex()' 会解析字符丌Ӏ?/p>

`yy_scan_string(const char *str)'                             解析0l尾字符丌Ӏ?br>`yy_scan_bytes(const char *bytes, int len)'               解析bytes开始的len个字W?可能包含 0 字符)


注意Q上面的两个函数会创建字W串或字节串的副本?q也许时期望的,因ؓ`yylex()' 会修改被解析~存的内?  可以使用下面的方式来拒绝使用副本:

`yy_scan_buffer(char *base, yy_size_t size)'

会从base开始解析,包含size个字? 最后的两个字节必须?YY_END_OF_BUFFER_CHAR (ASCII NUL)。他们不会被解析, 解析范围?`base[0]'  ?`base[size-2]'Q包含)。如果你没能按照q种规定使用baseQ如Q忘C最后的两个YY_END_OF_BUFFER_CHAR字节), `yy_scan_buffer()' 会q回I指针而不创徏YY_BUFFER_STATE。yy_size_tcd是个整型Q可以{化ؓ整数来反映buffer的长度?/p>

 


文gl束规则


Ҏ规则 "<<EOF>>" 只是规则在文件结束位|发生且yywrap()q回?倹{?如,没有更多的文件要处理). q个动作必须完成下面四g事情之一:

赋值给yyin一个新的文?(早期版本的flex, 此操作后必须调用Ҏ动作 YY_NEW_FILE; q个操作已经不需要了);
执行一个返回申?
执行一个特D的`yyterminate()' 动作;
或者用`yy_switch_to_buffer()' 切换C个新的输入缓存区.


<<EOF>> 不能与其他模式一起用;它也总在开始条件列表申明。如果指定了不合?<<EOF>> 规则, 它将会应用到所有的开始条件而不仅是 <<EOF>> 动作. 指定 <<EOF>> 规则仅在 initial 开始条件下匚wQ就是用:

<INITIAL><<EOF>>


下面的规则可以发现象不关闭的注释cȝ问题?/p>

%x quote
%%

...other rules for dealing with quotes...

<quote><<EOF>>   {
         error( "unterminated quote" );
         yyterminate();
         }
<<EOF>>  {
         if ( *++filelist )
             yyin = fopen( *filelist, "r" );
         else
            yyterminate();
         }


 



菊馨 2008-05-24 23:28 发表评论
]]>
Flex内存泄露问题[转蝲]http://www.shnenglu.com/Plator/archive/2008/05/24/50981.html菊馨菊馨Sat, 24 May 2008 15:25:00 GMThttp://www.shnenglu.com/Plator/archive/2008/05/24/50981.htmlhttp://www.shnenglu.com/Plator/comments/50981.htmlhttp://www.shnenglu.com/Plator/archive/2008/05/24/50981.html#Feedback0http://www.shnenglu.com/Plator/comments/commentRss/50981.htmlhttp://www.shnenglu.com/Plator/services/trackbacks/50981.html我写了一个Flex的例子测试,q个例子能把SQL语句按照分号隔开Q放入一个listQƈ且读出每一句SQL的v始和l束的位|,以及该SQL的类型,例如是一个空SQLq是只含注释的SQLQ还是一个标准SQL。Flexq个工具生成d后缀是l的词法文Ӟ然后输出一个lex.yy.c的文Ӟ我写了个E序试q个lex.yy.c。我的目标是把这个解析器做成MFC DLL或者能输出xml的标准程序,q样以后的元数据目p直接用了Q甚臌通过GUI界面处理SQLQ但是Flex生成?c文gMFCE序无法直接使用Q首先要注释掉c文g中的#include <unistd.h>q一行,q行会报错,再修改b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;q一行,让b->yy_is_interactive = 0,然后在把.c文g的的开头的#include <stdio.h>替换?include <stdafx.h>Q这样就行了么?q不行,VC2003~译q是报错Q我鼓捣半天才发玎ͼ需要把lex.yy.c文g重命名成lex.yy.cpp可以了Q这一pd操作太复杂了Q我写了一个批处理文g生成cppQ然后又写了一个VC的宏来修ҎӞq样Q按两下鼠标一切就都OK了,嘿嘿Q懒人就喜欢自动化?br>然后写了单的界面输入SQLq行解析Q解析效果不错,但是q行后却发现了两处内存泄Ԍ一处是16386字节Q一处是40字节。在q里先给非程序员普及一下内存泄露的知识QQ何一个计机E序Q在q行的时候存放数据是需要内存的Q需要多内存是E序向操作系l申LQ这块内存用完了把它还l操作系l,操作pȝ可以再分配给其他E序。就像我们去饭馆吃饭Q饭菜就是数据,内存是和子Q我们点了菜又点汤,q时候碗不够了,我们׃喊一壎ͼ“老板Q再拿两个碗来盛?#8221;Q这是内存甌Q等我们吃完了抹嘴买单走人,服务员收拄子和,q就是内存回Ӟ如果我们看到q家饭馆的碗太漂亮了Q于是偷hC个(q事我经常干Q,q就是内存泄霌Ӏ如果偷的人太多了Q这安馆的就不够了,你再甌要碗老板׃说碗不够了,L{一下,于是你们几个人只能用一个碗吃饭Q吃的很慢,q就叫内存不뀂C++和C的程序太灉|了,h和送回都是程序员自己来做Q就像一个饭馆没人看,完全靠个觉性来l持Q因此不是水^差也好,疏忽也好QC/C++E序会很Ҏ产生内存泄露Qjava和C#好多了Q他们就相当于饭馆门口有搜n的,你一个碗也带不走?br>q里我发C两处内存泄露Q一?6KB左右Q你可能会说?6KBQ现在内存都好几个GBQ这么点什么,但是如果q是一个服务器上常q不停机q行的程序,有很多h来访问,会很快把内存吃掉的。虽然我q个E序不是服务器上q行的程序,但是我能容忍E序的bugQ却不能容忍内存泄露Q想当年我刚刚写C++E序的时候,E序有内存泄Ԍ我死zL不出来是哪里的问题,最后只能告诉客戯我这个程序要求内存多Q你的电脑需要增加内存,于是客户增加了内存,但即使这样也不行Q还需要半夜重启一下机器才可以。在此我对该客户表示深深的歉意,从此我发誓,再也不让我的E序有一个字节的内存泄露Q于是深plcoding和调试技术,l过多年的浸淫,自己写的代码肯定不会有这L错误了,而且别h的多复杂的问题代码我拿过来就调试Q就跟饭端过来就吃一样easy?br>q回的问题我认ؓ很easyQ调试呗Q一开始以为是list有问题,q是很容易出问题的地方,CList是一个模板类Q用了好多年了,好用量又I我们一直用它,但是CList里面如果攑օ指针的话p注意了,单的Removeall是不行的Q还需要一个一个的delete掉里面的对象指针Q我跟踪了一遍,不是它的问题Q每ơ内存泄露的大小都是那么多,与list的大没关系。难道是我写的CSQLSet和CSQLNodeq两个类有问题?仔细查了一遍也没问题,奇了怪了Q难道是lex.yy.c不能和MFC混在一LQ我有把q个E序拆出来,用纯c做了一遍,果然没报告内存泄Ԍ好像是问题解决了。但是我如果单的在程序里面用MFC CStringc,׃报告泄露QCStringq更是久l考验的共产主义战士,不可能有问题的,太o人困惑了Q后来通过艰苦的内存检查发玎ͼ其实Uc的程序也有内存泄Ԍ只不qVC2003没有报告|了Q这直是VC的一个大bugQ这太让我失望了Q以前用VC6我比较喜Ƣnumega的调试插Ӟ它能发现比较隐秘的bug和泄Ԍ但是VC2003我觉得应该不错了Q就没去找这L插gQ没惛_啊没惛_Q微软还是忽悠了我一下?br>现在问题集中在Flex生成的lex.yy.c上了Q这个程序很长,好几千行Q而且作者肯定是C的高手,很多地方没看懂,太牛了,我从头到֤概浏览一遍,里面好几处申请了内存Q可能就是它们的问题Q但是这E序太复杂了无法下手啊,郁闷之中上网googleQ输入Flex memory leakQ结果发CAdobe有一个品也叫FlexQ而且也有内存泄露问题Q我倒,什么世道啊Q我又加入关键字lex.yy.cQ这回搜出来的对了,原来不止一个h发现了这个问题,很多人都在报告这个问题,但是讨论都没l果Q找到Flex的老家sourceforge.netQ打投诉一下作者,看到上面有讨论,又搜索了一下,作者针对内存泄露的问题说了Q对于制作解析非C的解析器来说Q可能会有泄露问题,解决的方案是在你真的准备l束解析的时候加上这两句代码Q?br>yy_delete_buffer(YY_CURRENT_BUFFER);
yy_init = 1;
我加上了Q好了,困扰我两天的问题解决了,q下世界清静了。但是看到其他的帖子说Bison也会有内存泄Ԍ前面的\q很ѝ?

菊馨 2008-05-24 23:25 发表评论
]]>
Lex中I/O例程的解?/title><link>http://www.shnenglu.com/Plator/archive/2008/05/24/50940.html</link><dc:creator>菊馨</dc:creator><author>菊馨</author><pubDate>Sat, 24 May 2008 04:05:00 GMT</pubDate><guid>http://www.shnenglu.com/Plator/archive/2008/05/24/50940.html</guid><wfw:comment>http://www.shnenglu.com/Plator/comments/50940.html</wfw:comment><comments>http://www.shnenglu.com/Plator/archive/2008/05/24/50940.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/Plator/comments/commentRss/50940.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Plator/services/trackbacks/50940.html</trackback:ping><description><![CDATA[Lex允许直接使用I/O例程。它们是Q? <ol> <li> <div align=justified><strong><em>input()</em></strong>Q返回下一个输入字W; </div> <li> <div align=justified><strong><em>output(c)</em></strong>Q将字符c写入输出 </div> <li> <div align=justified><strong><em>unput(c)</em></strong>Q将字符c压回输入,下次<strong><em>input()</em></strong>时被d?</div> </li> </ol> <p>q些例程都有默认的宏定义Q但是用户可以重写它们以适应不同的需求。这些例E定义了外部文g和内部字W之间的关系Qƈ且只能同时存在或更改。它们可以被重写使得输入或者输定向到特D的位置Q包括其他的E序或者内存;但是字符集的使用必须在整个例E中保持l一Q?strong><em>input</em></strong>必须q回0以表C文件结束;<strong><em>unput</em></strong>?strong><em>input</em></strong>之间的关pdM留,否则Lex不能完成向前搜烦的操作。Lex在不需要的时候不会向前搜索,但是每一个以+*?$l尾的、或者含?的规则需要这个功能。同P当一个表辑ּ是另一个的前缀Ӟ向前搜烦也是必不可少的。参阅下文中有关Lex使用的字W集的讨论。默认的Lex库?00个字W作为备用限制?</p> <br>Q但是这些在C++中似乎存在问题,我也正在调试Q? <img src ="http://www.shnenglu.com/Plator/aggbug/50940.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Plator/" target="_blank">菊馨</a> 2008-05-24 12:05 <a href="http://www.shnenglu.com/Plator/archive/2008/05/24/50940.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.shnenglu.com/" title="精品视频久久久久">精品视频久久久久</a> <div class="friend-links"> </div> </div> </footer> <a href="http://www.hrwp.net.cn" target="_blank">þ͵wcŮ</a>| <a href="http://www.woai858.cn" target="_blank">ٸ޾þþþþ4</a>| <a href="http://www.ppmov.cn" target="_blank">ĻþþƷ1 </a>| <a href="http://www.sccdseo.cn" target="_blank">þþþAVۺ</a>| <a href="http://www.r7831.cn" target="_blank">ŮдþӰԺ</a>| <a href="http://www.cdmt.org.cn" target="_blank">޹þþþþþ</a>| <a href="http://www.cjubbs.cn" target="_blank">ھƷþþþþþþõӰ </a>| <a href="http://www.chenxipeng.cn" target="_blank">þ߿ۿƷ㽶</a>| <a href="http://www.tzcn86.cn" target="_blank">þþþĻɫ</a>| <a href="http://www.97hh.cn" target="_blank">һþþ</a>| <a href="http://www.xy-ly.com.cn" target="_blank">þùƷ99þþþþ</a>| <a href="http://www.xecwf.cn" target="_blank">ƷһþþƷ</a>| <a href="http://www.y0ing.cn" target="_blank">ƷþþþþþþþӰԺ</a>| <a href="http://www.sxweishang.cn" target="_blank">Ʒþþþav</a>| <a href="http://www.46test.cn" target="_blank">Ƭѹۿþ</a>| <a href="http://www.uubux.com.cn" target="_blank">Ʒþþþav</a>| <a href="http://www.symedia.com.cn" target="_blank">þþƷþþþùۿ99ˮ</a>| <a href="http://www.niutuan.com.cn" target="_blank">Ʒþþþþ</a>| <a href="http://www.hbswmm.cn" target="_blank">þþù޾Ʒ</a>| <a href="http://www.xyszgh.cn" target="_blank">ƷŮþþþavˬ</a>| <a href="http://www.logeng.cn" target="_blank">ɫþþ99Ʒ</a>| <a href="http://www.00175.com.cn" target="_blank">þֹۺ޾Ʒ</a>| <a href="http://www.cn-yb.cn" target="_blank">Ʒþþþþ˳</a>| <a href="http://www.tvjay.cn" target="_blank">þþƷëƬѹۿ</a>| <a href="http://www.baizen.cn" target="_blank">þ˾Ʒһ</a>| <a href="http://www.baoshuidaili.com.cn" target="_blank">Ʒþþþþþþþ</a>| <a href="http://www.ylcq185.cn" target="_blank">ƷŮþþm</a>| <a href="http://www.024qixinyu.cn" target="_blank">ĻþþƷAPP</a>| <a href="http://www.carnegietech.com.cn" target="_blank">þþƷ</a>| <a href="http://www.zyhyhz.cn" target="_blank">þþƷһapp</a>| <a href="http://www.ksxhsd.cn" target="_blank">99ȶǾƷþþþþ</a>| <a href="http://www.i-ss.com.cn" target="_blank">ݺɫþþۺϲ</a>| <a href="http://www.west-data.cn" target="_blank">97Ʒ˾þþô߽97</a>| <a href="http://www.zhaozhounews.cn" target="_blank">ھƷþ鶹Ħ</a>| <a href="http://www.3q168.net.cn" target="_blank">þŷձƷ</a>| <a href="http://www.cjubbs.cn" target="_blank">޹þ</a>| <a href="http://www.hbsannong.com.cn" target="_blank">Ʒþһ </a>| <a href="http://www.bbdhtex.cn" target="_blank">þþƷ޾Ʒ</a>| <a href="http://www.r7831.cn" target="_blank">Ʒ˾þ˵Ӱ</a>| <a href="http://www.weryuadfsd.cn" target="_blank">Ʒۺþþþþ</a>| <a href="http://www.ampv.cn" target="_blank">þ99Ʒþþþþ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>