LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 788|回复: 2

斑竹看看好吗

[复制链接]
发表于 2006-3-31 16:53:41 | 显示全部楼层 |阅读模式
就只运行一下,看看就觉得怪异了 。

如下的struct.l定义:
  1. %{


  2. #include<cctype>

  3. using namespace std;


  4. #include "structy.hpp"

  5. extern YYSTYPE yylval;

  6. %}

  7. char [a-zA-Z\_]

  8. nonzerodigit [1-9]

  9. zero "0"

  10. number {nonzerodigit}({nonzerodigit}|zero)*

  11. blank [\r\n\t\ ]

  12. %%

  13. {char}({char}|{number})* { yylval.charVal = yytext; return NAME; }

  14. {number} { yylval.intVal = atoi(yytext); return ID; }

  15. . /*do nothing*/

  16. %%


  17. int yywrap()
  18. { return 1; }
复制代码


语法分析如下struct.y:
  1. %{
  2. #include<iostream>
  3. #include<cstdlib>
  4. #include<cstdio>
  5. #include<cstring>

  6. using namespace std;

  7. struct valueType
  8. {
  9.         int intVal;
  10.         char* charVal;
  11.         valueType(const int a,const char* c)
  12.         {
  13.                 intVal = a;
  14.                 charVal = new char[strlen(c)+1];
  15.                 for(int i=0;c[i];i++)
  16.                 {
  17.                         cout<<c[i]<<' ';
  18.                 }
  19.                 cout<<endl;
  20.                 strcpy(charVal,c);
  21.         }
  22. };

  23. int yylex();
  24. void yyerror(const char* );

  25. %}

  26. %union{
  27.         int intVal;
  28.         char* charVal;
  29.         valueType* p;
  30. }

  31. %token<intVal> ID
  32. %token<charVal> NAME
  33. %type<p> pair


  34. %start list


  35. %%
  36. list:
  37.     | list pair

  38. pair:NAME ID {
  39.     $$ = new valueType($2,$1);
  40.     cout<<"--------------------------------------------------------"<<endl;
  41.     cout<<"name:"<<$$->charVal<<endl
  42.         <<"ID:"<<$$->intVal<<endl;
  43.     }



  44. %%

  45. extern FILE* yyin;

  46. int main(int args,char*argv[])
  47. {
  48.     if(args<=1 || (NULL==(yyin=fopen(argv[1],"rt"))))
  49.     {
  50.         cout<<"cannot open the input file."<<endl;
  51.         return 1;
  52.     }
  53.     yyparse();
  54.     return 0;
  55. }


  56. void yyerror(const char* err)
  57. {
  58.     cout<<err<<endl;
  59. }
复制代码


相关命令是:

  1. flex -L -ostructl.cpp struct.l
  2. bison -l -d -ostructy.cpp struct.y
  3. g++ -ostruct *.cpp
  4. ./struct input

复制代码


要注意的是需要在structy.hpp中添加声明struct valueType;:ask

当输入文件是input时:

  1. asd_syd98as 6767887
  2. _siufas7CjSas 989080
  3. jasfd 09sua f0
  4. 54356
复制代码


输出是:
  1. a s d _ s y d 9 8 a s   6 7 6 7 8 8 7
  2. --------------------------------------------------------
  3. name:asd_syd98as 6767887
  4. ID:6767887

  5. _ s i u f a s 7 C j S a s   9 8 9
  6. --------------------------------------------------------
  7. name:_siufas7CjSas 989
  8. ID:989
  9. syntax error
复制代码


也就是说yytext中包含了后面扫描到的ID的值,我以为输出只是象a s d _ s y d 9 8 a s
,没有后面的ID部分,能讲讲yytext的缓冲处理是怎样的一个过程吗?
发表于 2006-3-31 19:36:14 | 显示全部楼层
你下面的这条规则:
{char}({char}|{number})* { yylval.charVal = yytext; return NAME; }
应改为:
{char}({char}|{number})* { yylval.charVal = strdup(yytext); return NAME; }
一般是这么用的,可能要加一个 string.h 头文件

原因(猜测):
每次要匹配一个yacc(语法)规则时,申请一块内存,yytext 就指向它,每当一个lex规则匹配时,将匹配字符串放置在申请的内存中,并将 yytext 指针移动到那个地方。在一个语法规则匹配结束后,释放内存
回复 支持 反对

使用道具 举报

发表于 2006-4-2 10:06:32 | 显示全部楼层
《lex 与 yacc》第二版中提到: lex每次匹配一个新标记时就替换yytext的内容。如果yytext的内容在后面还要使用(例如:由调用lex扫描程序的yacc语法分析程序中的一个动作使用),通过使用strdup或者类似例程保存字符串的拷贝,从而使字符串的拷贝位于刚刚分配的存储器中
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表