테스트용으로 한번 만들어 본것
파서에서는 각 문법을 인식했을 때마다 씨언어로 동작을 작성할 수 있다.
평소에 코딩이 할 일이 있을 때 lex yacc이 필요하면 이런식으로 활용 할 수 있다.
/**************************************
* 렉스 select.l
**************************************/
%{
#include "y.tab.h"
int lineno = 1;
%}
%%
CREATE { return CREATE; }
TABLE { return TABLE; }
VIEW { return VIEW; }
SELECT { return SELECT; }
FROM { return FROM; }
WHERE { return WHERE; }
AND { return AND; }
OR { return OR; }
NOT { return NOT; }
COUNT { return FUNC; }
SUM { return FUNC; }
MAX { return FUNC; }
MIN { return FUNC; }
AVG { return FUNC; }
INTEGER { return INTEGER; }
CHARACTER { return CHARACTER; }
DOUBLE { return DOUBLE; }
NULLX { return NULLX; }
UNIQUE { return UNIQUE; }
REFERENCES { return REFERENCES; }
PRIMARY { return PRIMARY; }
FOREIGN { return FOREIGN; }
KEY { return KEY; }
VIEW { return VIEW; }
AS { return AS; }
UPDATE { return UPDATE; }
SET { return SET; }
GROUP { return GROUP; }
BY { return BY; }
"=" |
"<>" |
"<" |
">" |
"<=" |
">=" { return COMPARE; }
[-+*/:(),.;] { return yytext[0]; }
[a-zA-Z][_a-zA-Z0-9]* { yylval.sval = strdup(yytext); return NAME; }
[0-9]+ { yylval.dval = atof(yytext); return NUMBER; }
'[^'\n]*' { yylval.sval = strdup(yytext); return STRING; }
\n { lineno++; }
[ \t] ;
%%
yyerror(char *s)
{
printf(" line %d: %s at'%s':\n",lineno,s,yytext);
}
main(int argc , char **argv)
{
if( argc > 1 )
{
FILE *fp = fopen(argv[1] , "r" );
if(!fp)
{
printf("FILE OPEN ERROR !\n");
exit(1);
}
yyin = fp;
}
if( !yyparse() )
printf(" SQL parse worked \n");
else
printf(" SQL parse failed \n");
}
/**************************************
* 야크 select.y
**************************************/
%{
#include "sym_table.h"
%}
%union {
double dval;
char *sval;
}
%token <sval> NAME
%token <sval> STRING
%token <dval> NUMBER
%left OR
%left AND
%left NOT
%left COMPARE
%left '+' '-'
%left '*' '/'
%nonassoc UMINUS
%token SELECT WHERE FROM FUNC CREATE TABLE VIEW UNIQUE AS UPDATE SET GROUP
%token NULLX INTEGER CHARACTER DOUBLE PRIMARY FOREIGN REFERENCES KEY BY
%%
sql_list :
sql ';' {
input_stack("sql");
input_stack("sql_list"); sql_end(); }
| sql_list sql ';'
;
sql : create_schema
| manipulative_stat { input_stack("manipulative_stat"); }
;
create_schema :
create_table { input_stack("create_schema"); }
| create_view
;
/* create_table */
create_table :
CREATE TABLE table_name '(' table_element_list ')'
;
table_element_list :
table_element
| table_element_list ',' table_element
;
table_name :
NAME {
input_stack($1);
input_stack("NAME");
}
| NAME '.' NAME
;
table_element :
variable
| key
;
variable : NAME data_type
| NAME data_type data_opt
;
data_type : CHARACTER
| CHARACTER '(' NUMBER ')'
| INTEGER
| INTEGER '(' NUMBER ')'
| DOUBLE
| DOUBLE '(' NUMBER ')'
;
data_opt : NOT NULLX
| NOT NULLX UNIQUE
| NOT NULLX PRIMARY KEY
;
key : PRIMARY KEY '(' NAME ')'
| FOREIGN KEY '(' NAME ')' REFERENCES NAME
| UNIQUE '(' NAME ')'
;
/* create_view */
create_view :
CREATE VIEW NAME '(' name ')'AS manipulative_stat
| UPDATE NAME SET NAME COMPARE update_cond where
update_cond :
NAME '+' cond
| NAME '-' cond
| NAME '*' cond
| NAME '/' cond
| NUMBER
/* query list */
manipulative_stat :
select_stat { input_stack("select_stat"); }
;
select_stat :
SELECT name select_cond {
input_stack("select_cond");
input_stack("name");
input_stack("SELECT");
}
;
select_cond :
from
where
group_by {
input_stack("group_by");
input_stack("where");
input_stack("from");
}
;
from : FROM name { input_stack("name");
input_stack("FROM"); }
;
where : { input_stack("empty string"); }
|
WHERE condition { input_stack("condition");
input_stack("WHERE");
}
;
group_by : { input_stack("empty string"); }
|
GROUP BY name
;
condition : comparision conj condition
| comparision { input_stack("comparision"); }
;
comparision: NAME COMPARE cond { input_stack($1);
input_stack("cond");
input_stack("COMPARE");
input_stack("NAME"); }
;
cond : NAME {
input_stack($1);
input_stack("NAME"); }
| NUMBER {
input_stack("NUMBER"); }
| STRING {
input_stack($1);
input_stack("STRING"); }
;
name :
table_name { input_stack("table_name"); }
| name ',' table_name
;
conj : AND
| OR
| NOT
;
%%
sql_end()
{
show_stack();
printf("\n parsing complete \n");
exit(1);
}
'Programming > LEX & YACC' 카테고리의 다른 글
LEX 와 YACC 의 동작 원리 (0) | 2009.08.14 |
---|---|
간단한 렉스 프로그램 ( Flex & C++ ) (0) | 2009.08.13 |
YACC 문법 구조 (0) | 2009.08.13 |
LEX 의 정규 표현식 (0) | 2009.08.13 |
LEX 의 구조 (1) | 2009.08.12 |