免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4027 | 回复: 4

flex bison 的小问题 [复制链接]

论坛徽章:
0
发表于 2010-07-13 10:18 |显示全部楼层
我想把一个包含函数的字符串用flex bison解析生成c代码,能够计算表达式的值,这个flex和bison的语法文件该怎么写?

例如: "abc" + substr("efghijklmn", 0, 3) + "xyz"
substr 是取子字符串的函数,substr("efghijklmn", 0, 3) 表示对字符串"efghijklmn"从第0个位置开始, 取3个字符, 得到子串"efg"
+ 表示连接2个字符串

则上述的表达式计算的结果为: abcefgxyz

要求能支持函数嵌套,如: substr(substr("efghijklmn", 0, 4), 0, 2)
得到结果ef

论坛徽章:
2
摩羯座
日期:2013-10-10 14:29:04天蝎座
日期:2014-01-03 09:14:49
发表于 2010-07-13 10:51 |显示全部楼层
词法分析:字符串,函数标识符,数字,‘+’  ',' '(' ')'

语法分析:计算函数的值,表达式的值

论坛徽章:
0
发表于 2010-07-13 11:32 |显示全部楼层
我刚刚接触, 不知道怎么写, 能否指点一下呀

论坛徽章:
0
发表于 2010-07-14 16:35 |显示全部楼层
我写了一个处理上述问题的flex和bison的语法文件:
cal.l
  1. %{
  2. #include <stdio.h>
  3. #include <stdlib.h>

  4. void yyerror(char*);
  5. #include "cal.tab.h"
  6. char buf[1024];
  7. char* s;

  8. char* removequote(char* s);
  9. void substr(char *s, int pos, int count, char* substr);
  10. %}
  11. %x STRING

  12. %%
  13. "substr"        return SUBSTR;
  14. \"(\\.|[^\\"])*\"   { strcpy(buf, yytext); yylval = removequote(yytext); return STR;}
  15. [0-9]+          {yylval = strdup(yytext); return INT;}
  16. ","             return (',');
  17. "("             return ('(');
  18. ")"             return (')');
  19. "+"             return ('+');  
  20. [\n]            return *yytext;

  21. [\t]            ;
  22. .               yyerror("invalid char\n");

  23. %%
  24. int yywrap(void)
  25. {
  26.   return 1;
  27. }

  28. char* removequote(char* s)
  29. {
  30.   char szValue[1024];
  31.   char szLine[1024];
  32.   int len;
  33.   
  34.   len = strlen(s);
  35.   strcpy(szLine, s);
  36.   strcpy(szValue, &szLine[1]);
  37.   szValue[len - 2] = 0;
  38.   
  39.   s = szValue;
  40.   
  41.   return s;
  42. }

  43. void substr(char *s, int pos, int count, char* substr)
  44. {
  45.   //printf("%s, %d, %d\n", s, pos, count);
  46.   //return s;
  47.   int len, i, j;
  48.   len = strlen(s);
  49.   for ( i = pos, j = 0; i < pos + count; )
  50.     substr[j++] = s[i++];
  51.   
  52.   substr[j] = 0;
  53. }
复制代码
cal.y
  1. %{
  2. int yylex(void);
  3. void yyerror(char*);

  4. char szTmp[1024];
  5. %}
  6. %token STR INT SUBSTR
  7. %left  '+'
  8. %%
  9. program:
  10.        program expr '\n' { printf("%s\n", $2);  exit(0);}
  11.        |
  12.        ;
  13. expr:  
  14.        STR       {$=$1;}
  15.        | SUBSTR '(' STR ',' INT ',' INT ')'
  16.        {
  17.           printf("$3=%s,$5=%s,$7=%s\n", $3, $5, $7);
  18.                       substr($3, atoi($5), atoi($7), szTmp);
  19.           $ = szTmp;
  20.        }
  21.        |  expr '+' expr   
  22.        {
  23.           printf("\n$1=%s, $3=%s\n", $1, $3);
  24.           strcat(szTmp, $1);
  25.           strcat(szTmp, $3);
  26.           $ = szTmp;
  27.        }      
  28.       ;
  29. %%
  30. void yyerror(char *s)
  31. {
  32.   fprintf(stderr, "%s\n", s);
  33.   return;
  34. }

  35. int main(void)
  36. {
  37.   yyparse();
  38.   return 0;
  39. }
复制代码
但问题是,当规约这个表达式expr '+' expr 的时候, 我打印出来的$1和$3的值总是有问题
$1的值被$3的值覆盖了
比如:
当输入: "abcd"+"efgh"的时候,得到的结果是efghefgh, 此时打印的$1和$3的值都是efgh

哪位高人给看看原因呀,谢谢

论坛徽章:
0
发表于 2010-07-14 23:39 |显示全部楼层
回复 4# cnhnyu


    在lex里面分析字符串的时候不能简单的用yylval=yytext来对yylval赋值,这样做只是将yytext的指针传递给了yylval,在第一次读取“abcd”之后,yylval的地址为yytext;(注意yytext是一个缓冲区,它的地址不变),在读取了“efgh”之后,yylval的地址仍然为yytext的地址,即仍然为缓冲区的首地址,这样,楼主的$1和$3都指向了缓冲区的首地址,所以显示的是两个"efgh"

以下给出我的做法。。。

正好这学期有编译原理的课,我就把我的代码拿上来了。

由于yylval要记录字符串或者记录整数,就需要重新定义yylval的结构,见下面的代码:
  1. %union {
  2.     int intValue;                 /* integer value */
  3.     char varName[11];                /* symbol table index */
  4.     nodeType *nPtr;             /* node pointer */
  5. };
复制代码
这样做就能够解决楼主的问题了。。

建议楼主看下草木瓜的关于lex和yacc的博客,还有一本Tom Niemann 的 A compact guide to lex & yacc电子书 , 楼主最好看下
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP