免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1940 | 回复: 5
打印 上一主题 下一主题

一个yacc的问题,求助! [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-10-04 10:01 |只看该作者 |倒序浏览
我想写一个解释简单sql语言的解释器,用lex和yacc做。 我先试着写了很简单的sql.l sql.y如下,想先实现最简单的CREATE TABLE功能。

sql.l

  1. %{
  2.         #include "y.tab.h" //<>
  3.         #include <stdlib.h>
  4.         #include <string.h>
  5.         void yyerror(char *);
  6. %}

  7. %%
  8. CREATE                                { return CREATE;}

  9. TABLE                                { return TABLE;}


  10. [0-9]+                                {
  11.                                                 yylval.intval = atoi(yytext);
  12.                                                 return INTEGER;
  13.                                         }       

  14. [a-z][a-z0-9]*                {
  15.                                                 strcpy(yylval.nameval, yytext);
  16.                                            //        fprintf(stderr, "-----%s\n", *yytext);
  17.                                                 return NAME;
  18.                                         }

  19. [<>=]                                {
  20.                                                 yylval.compval = yytext[0];
  21.                                                 return COMPARE;
  22.                                         }

  23. [\n]                {        return *yytext;
  24.                                         }

  25. [ \t]                                ;

  26. .                                        {
  27.                                                 yyerror("Unknown Character!");
  28.                                         }
  29. %%

  30. int yywrap(void)
  31. {
  32.         return 1;
  33. }
复制代码


sql.y如下:

  1. %{
  2.         #include <stdio.h>
  3.         void yyerror(char *s);
  4.         int yylex(void);

  5. %}

  6. %union {
  7.                         int intval;
  8.                         char nameval[50];
  9.                         char compval;
  10.                 };

  11. %token <intval> INTEGER
  12. %token <nameval> NAME
  13. %token <compval> COMPARE
  14. %token CREATE TABLE

  15. %%
  16. createtablestatement:
  17.                 | createtablestatement '\n'
  18.                 | CREATE TABLE NAME '\n' {printf("%s\n", $3);}
  19.                 ;

  20. %%
  21. void yyerror(char *s)
  22. {
  23.         fprintf(stderr," %s\n", s);
  24. }

  25. int main(void)
  26. {
  27.         yyparse();
  28. }
复制代码


编译运行如下:

lex sql.l
yacc -d sql.y
gcc -o create lex.yy.c y.tab.c -ll

$./create
CREATE TABLE aaaa
aaaa
CREATE TABLE bbbb
parse error
$

我想问一下为啥我第一次语法分析能成功,第二次就有问题呢?该怎么改呢?请知道的大虾指教,谢谢!

论坛徽章:
0
2 [报告]
发表于 2008-10-04 11:52 |只看该作者
顶一下,大虾帮忙阿!

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
3 [报告]
发表于 2008-10-04 13:12 |只看该作者
因为你的起始符号为
createtablestatement,
于是你所有的输入在语法不出错的时候要被规约为createtablestatement
CREATE TABLE aaaa
CREATE TABLE bbbb
这样的输入当然不符合你的语法
你要干的是造一个新的符号作为起始符号(当然,依然用createtablestatement也可),把原来的一组createtablestatement串进去

论坛徽章:
0
4 [报告]
发表于 2008-10-04 14:33 |只看该作者

回复 #3 cjaizss 的帖子

小弟驽钝,没有理解你的意思。
您能说得更具体点吗?帮着改一下可以吗?

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
5 [报告]
发表于 2008-10-04 15:01 |只看该作者
在yacc语言里,两个%%之后紧接着的符号是start symbol,也就是你的所有输入都会被规约为这个符号.
你可以在前面加上这句试下
start:createtablestatement |start createtablestatement;

论坛徽章:
0
6 [报告]
发表于 2008-10-05 09:37 |只看该作者
多谢版主的指点,我今天完善了下这个程序,又碰到些问题,烦请您再指点一下。

sql.l


  1. %{
  2.         #include "sql.h"
  3.         #include "y.tab.h"
  4.         #include <stdlib.h>
  5.         #include <string.h>
  6.         void yyerror(char *);
  7. %}

  8. %%
  9. CREATE                                {  return CREATE;}

  10. TABLE                                {  return TABLE;}

  11. INT                 {
  12.                                                 strcpy(yylval.attr_type, yytext);
  13.                                                 return TYPE;
  14.                                         }

  15. STR20                                {
  16.                                                 strcpy(yylval.attr_type, yytext);
  17.                                                 return TYPE;
  18.                                         }

  19. [0-9]+                                {
  20.                                                 yylval.intval = atoi(yytext);
  21.                                                 return INTEGER;
  22.                                         }       

  23. [a-z][a-z0-9]*                {
  24.                                                 strcpy(yylval.attr_name, yytext);
  25.                                            //        fprintf(stderr, "-----%s\n", *yytext);
  26.                                                 return NAME;
  27.                                         }
  28. [()\n]                                {
  29.                                                 return *yytext;
  30.                                         }
  31. [ \t]                                ;

  32. .                                        {
  33.                                                 yyerror("Unknown Character!");
  34.                                         }
  35. %%

  36. int yywrap(void)
  37. {
  38.         return 1;
  39. }
复制代码


sql.y:


  1. %{
  2.         #include <stdio.h>
  3.         #include <string.h>
  4.         #include "sql.h"
  5.         int i  = 0;
  6.         struct attr_name_type array[20];
  7.         void yyerror(char *s);
  8.         int yylex(void);
  9.     struct attr_name_type copy(char *b, char *c);
  10.         struct attr_name_type * copy_to_list(struct attr_name_type a);
  11. %}

  12. %union {
  13.                         int intval;
  14.                         char attr_type[10];
  15.                         char attr_name[20];
  16.                         struct attr_name_type nametype;
  17.                         struct attr_name_type *list;
  18.                 };

  19. %token <intval> INTEGER
  20. %token <attr_name> NAME
  21. %token <attr_type> TYPE
  22. %token CREATE TABLE

  23. %type <attr_type> type
  24. %type <attr_name> name
  25. %type <nametype> attrnametype
  26. %type <list> attributelist
  27. %%
  28. start:
  29. createtablestatement |start createtablestatement;

  30. createtablestatement:
  31.                 CREATE TABLE name left_bracket attributelist ')' '\n'        {
  32.                                                                                                 printf("table name: %s\n", $3);
  33.                                                                                                 printf("NAME        TYPE\n");
  34.                                                                                                 int j;
  35.                                                                                                 for(j = 0; j < i; j++)
  36.                                                                                                 {
  37.                                                                                                         printf("%s        %s\n", ($5[j]).name, ($5[j]).type);
  38.                                                                                                 }

  39.                                                                                                 i = 0;
  40.                                                                                          }
  41.                 ;

  42. attributelist:
  43.                         attrnametype { //zhi zhixing yici.
  44.                                                         $$ = copy_to_list($1);
  45.                                                 //        printf("First added: %s        %s\n", $$[i - 1].name, $$[i - 1].type);
  46.                                                  }


  47.                         | attributelist attrnametype {  //wang zhebianzou
  48.                                                                                         copy_to_list($2);
  49.                                                                                         $$ = $1;
  50.                                                                                  }
  51.                         ;

  52. attrnametype:
  53.                         name type        {
  54.                                             $$ = copy($1, $2);
  55.                         }
  56.                         | attrnametype '\n'                               
  57.             ;
  58. left_bracket:
  59.      '('
  60.          | left_bracket '\n'
  61.          ;
  62. name: NAME
  63.       | name '\n'
  64.           ;
  65. type: TYPE
  66.                 ;


  67. %%
  68. void yyerror(char *s)
  69. {
  70.         fprintf(stderr," %s\n", s);
  71. }

  72. struct attr_name_type * copy_to_list(struct attr_name_type a)
  73. {
  74. //        memmove(&(a[i]), &b, sizeof(struct attr_name_type));
  75.     strcpy(array[i].name, a.name);
  76.         strcpy(array[i].type, a.type);
  77.         i++;

  78.         return array;
  79. }

  80. struct attr_name_type copy(char *b, char *c)
  81. {
  82.         struct attr_name_type a;
  83.         strcpy(a.name, b);
  84.         strcpy(a.type, c);

  85.         return a;
  86. }
  87.                                                

  88. int main(void)
  89. {
  90.         yyparse();
  91. }
复制代码


sql.h:


  1. struct attr_name_type
  2. {
  3.                     char type[10];
  4.                           char name[20];
  5. };
复制代码



编译运行如下:
/2$ lex sql.l
/2$ yacc -d sql.y
/2$ gcc -o create lex.yy.c y.tab.c -ll
/2$ ./create
CREATE TABLE aaa
(
bbb INT
ccc INT)
table name: aaa
NAME        TYPE
bbb        INT
ccc        INT


这其中,
CREATE TABLE aaa
(
bbb INT
ccc INT)输入,下面是输出。

它建立了一个名字为aaa的表,有两个类型为int的参数bbb ccc.

不过我的程序如果这样输出时会有错误:

先输入一个或多个回车以后在输入
CREATE TABLE aaa
(
bbb INT
ccc INT)
就不能很好地分析了。
该怎么改才能让他支持可以先输入回车呢?请指点迷津,多谢了!

[ 本帖最后由 susesuse 于 2008-10-5 14:34 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP