vieyahn2017 / goto

GO C C++ Rust
0 stars 1 forks source link

【C】lex - yacc (bison) - test #12

Closed vieyahn2017 closed 10 months ago

vieyahn2017 commented 10 months ago

lex - yacc

vieyahn2017 commented 10 months ago

Yacc文件如下:

%{
#include <stdio.h>
%}
%token NAME NUMBER
%left '+' '-'
%start statement
%%
statement : NAME '=' expression
| expression{printf("=%d\n", $1);}
;
expression : expression '+' NUMBER{$$ = $1 + $3;}
|           expression '-' NUMBER{$$ = $1 - $3;}
|           NUMBER  {$$ = $1;}
;
%%
main()
{
    yyparse();
}

yyerror(s)
    char *s;
{
    printf("%s\n",s);
}
vieyahn2017 commented 10 months ago

localhost:/yh1/3 # vi cal.y localhost:/yh1/3 # bison -d cal.y localhost:/yh1/3 # ll total 48 -rw-------. 1 root root 40510 Jan 18 03:10 cal.tab.c -rw-------. 1 root root 2565 Jan 18 03:10 cal.tab.h -rw-------. 1 root root 359 Jan 18 03:10 cal.y

vieyahn2017 commented 10 months ago

Lex文件如下:

%{
/*cal */
#include "cal.tab.h"
extern int yylval;
%}
%%
[0-9]+  {yylval=atoi(yytext);return NUMBER;}
[ \t];
\n  return 0;
.   return yytext[0];
%%

int yywrap()
{
    return 1;
}
vieyahn2017 commented 10 months ago

用法: flex cal.l gcc lex.yy.c cal.tab.c -o calc

localhost:/yh1/3 # flex cal.l localhost:/yh1/3 # ll total 96 -rw-------. 1 root root 181 Jan 18 03:11 cal.l -rw-------. 1 root root 40510 Jan 18 03:10 cal.tab.c -rw-------. 1 root root 2565 Jan 18 03:10 cal.tab.h -rw-------. 1 root root 359 Jan 18 03:10 cal.y -rw-------. 1 root root 44462 Jan 18 03:12 lex.yy.c

有警告 localhost:/yh1/3 # gcc lex.yy.c cal.tab.c -o calc cal.tab.c: In function ‘yyparse’: cal.tab.c:1018:16: warning: implicit declaration of function ‘yylex’ [-Wimplicit-function-declaration] yychar = yylex (); ^~~~~ cal.tab.c:1177:7: warning: implicit declaration of function ‘yyerror’; did you mean ‘yyerrok’? [-Wimplicit-function-declaration] yyerror (YY_("syntax error")); ^~~ yyerrok cal.y: At top level: cal.y:16:1: warning: return type defaults to ‘int’ [-Wimplicit-int] main() ^~~~ cal.y:21:1: warning: return type defaults to ‘int’ [-Wimplicit-int] yyerror(s) ^~~

vieyahn2017 commented 10 months ago

测试 localhost:/yh1/3 # ./calc 9+4-5 =8 localhost:/yh1/3 # ./calc dsds syntax error

vieyahn2017 commented 10 months ago

结束语

在PG中,也通过Lex和Yacc的配合使用进行SQL语句的词法分析和语法分析。在PG源码中,包含scan.l和gram.y两个文件,并且已经预生成了对应的C文件scan.c和gram.c。如果重新修改scan.l和gram.y,那么需要在编译PG的时候,就会重新生成scan.c和gram.c

vieyahn2017 commented 10 months ago

各数据库使用的语法分析方式 sqlite :lemo (LR) pg:yacc (LR) opengauss:yacc (LR) mysql:bison (LR) h2db:递归下降法

vieyahn2017 commented 10 months ago

语法分析实战 使用bison解析删表语句 : drop table [if exists] a;

为了简单起见,使用首字母代替TOKEN,并且假设表名也是单字符的。

drop table [if exists] a; => d t [i e] a;

步骤

1)建立parse_drop_table.y文件

输入如下代码:

%{
  #include<stdio.h>
  int yylex();
  void yyerror(const char *);
%}
%%
sqls: sql
    | sql sqls;
sql: drop_table_header if_exists table_name ';' '\n' {printf("%d, %c\n", $2, $3);}
   | '\n' {printf("empty sql!\n");}
;
drop_table_header: 'd' 't';
if_exists: 'i' 'e' {$$=1;}
          |  {$$=0;}
;
table_name: 'a' {$$='a';}
          | 'b' {$$='b';}
;
%%
int yylex() {
    return getchar();
}
void yyerror(const char *errmsg) {
    fprintf(stderr, "%s\n", errmsg);
}
int main() {
    return yyparse();
}

2)使用bison处理语法文件,得到语法解析c文件,一般是后缀为tab.c的文件

bison parse_drop_table.y 3)使用gcc编译语法解析c文件

gcc parse_drop_table.tab.c 4)测试

执行:./a.out 输入:dtiea; 输出:1, a 输入:dtb; 输出:0, b 输入:dta; 输出:0, a 发现可以正常处理简化后的drop table语句,并得到if_exists和table_name。