%{
#
include
<stdlib.h>
#
include
<stdarg.h>
#
include
<string.h>
#
include
<stdio.h>
#
include
<malloc.h>
char * parsetreeroot=NULL;
extern
"C"
int yylex();
extern
"C"
int yyparse();
extern
"C"
void yyerror(
const
char *s, ...);
char globalInputText[10000];
int globalReadOffset;
int readInputForLexer( char *buffer, int *numBytesRead, int maxBytesToRead );
char * mystrcat(char *s1,char *s2)
{
char *p1=(char *)malloc(
strlen
(s1)+
strlen
(s2)+1);
strcpy(p1,s1);
strcat(p1,s2);
return
p1;
}
%}
%locations
%union {
int
intval
;
double
floatval
;
char *
strval
;
int subtok;
}
%token <
strval
> NAME
%token <
strval
> STRING
%token <
strval
> INTNUM
%token <
strval
> BOOL
%token <
strval
> APPROXNUM
%token <
strval
> USERVAR
%type <
strval
> stmt_root create_stmt para_list definition data_type pro_block pro_parameters declare_list set_list
%type <
strval
> assign_var pro_body pro_stmt_list sql_stmt expr
%right ASSIGN
%left OR
%left XOR
%left ANDOP
%left NOT '!'
%left BETWEEN
%left <subtok> COMPARISON
%left '|'
%left '&'
%left <subtok> SHIFT
%left '+' '-'
%left '*' '/' '%' MOD
%left '^'
%token CREATE
%token PROCEDURE
%token PRONAME
%token DECLARE
%token SET
%token BEGINT
%token
END
%token SQL
%token INT
%token VARCHAR
%token
DATE
%token TIME
%token DOUBLE
%token IF
%token NOT
%token EXISTS
%token THEN
%token ELSE
%token ENDIF
%token FOR
%token WHEN
%token WHILE
%start stmt_root
%%
stmt_root: create_stmt pro_block { $$=mystrcat(
$1
,
$2
); parsetreeroot=$$;}
;
create_stmt: CREATE PROCEDURE NAME '(' para_list ')'
{
char *temp=mystrcat(
"create procedure "
,
$3
);
temp=mystrcat(temp,
"("
);
temp=mystrcat(temp,
$5
);
$$=mystrcat(temp,
")(create)\n"
);
}
;
para_list: definition { $$=
$1
; }
|definition ',' para_list
{
char *temp=mystrcat(
$1
,
","
);
$$=mystrcat(temp,
$3
);
}
;
definition: USERVAR data_type
{
char *temp=mystrcat(
$1
,
" "
);
$$=mystrcat(temp,
$2
);
}
;
data_type:
DATE
{$$=
"date"
; }
| TIME {$$=
"time"
; }
| VARCHAR '(' INTNUM ')' {$$=
"varchar"
; }
| INT {$$=
"int"
; }
| DOUBLE {$$=
"double"
; }
;
pro_block: BEGINT pro_parameters pro_body
END
{
char *temp=mystrcat(
"begin\n"
,
$2
);
temp=mystrcat(temp,
""
);
temp=mystrcat(temp,
$3
);
$$=mystrcat(temp,
"end"
);
}
;
pro_parameters: declare_list ';' { $$=mystrcat(
$1
,
";(declare)\n"
);}
|pro_parameters declare_list ';'
{
char *temp=mystrcat(
$1
,
$2
);
$$=mystrcat(temp,
";(declare)\n"
);
}
|pro_parameters set_list ';'
{
char *temp=mystrcat(
$1
,
$2
);
$$=mystrcat(temp,
";(set)\n"
);
}
;
declare_list:
|DECLARE definition
{
$$=mystrcat(
"declare "
,
$2
);
}
|declare_list ',' definition
{
char *temp=mystrcat(
$1
,
","
);
$$=mystrcat(temp,
$3
);
}
;
set_list:
|SET assign_var
{
$$=mystrcat(
"set "
,
$2
);
}
| set_list ',' assign_var
{
char *temp=mystrcat(
$1
,
","
);
$$=mystrcat(temp,
$3
);
}
;
assign_var : USERVAR COMPARISON expr
{
char *temp=mystrcat(
$1
,
"="
);
$$=mystrcat(temp,
$3
);
}
;
expr: NAME { $$=
$1
;}
| STRING { $$=
$1
;}
| INTNUM { $$=
$1
;}
| APPROXNUM { $$=
$1
;}
| BOOL { $$=
$1
;}
;
pro_body : pro_stmt_list { $$=
$1
; }
;
pro_stmt_list: sql_stmt {$$=
$1
; }
|pro_stmt_list sql_stmt
{
$$=mystrcat(
$1
,
$2
);
}
;
sql_stmt:
|SQL NAME ';' { $$=mystrcat(
$2
,
";(sql)\n"
);}
;
%%
int readInputForLexer( char *buffer, int *numBytesRead, int maxBytesToRead ) {
int numBytesToRead = maxBytesToRead;
int bytesRemaining =
strlen
(globalInputText)-globalReadOffset;
int i;
if
( numBytesToRead > bytesRemaining ) { numBytesToRead = bytesRemaining; }
for
( i = 0; i < numBytesToRead; i++ ) {
buffer[i] = globalInputText[globalReadOffset+i];
}
*numBytesRead = numBytesToRead;
globalReadOffset += numBytesToRead;
return
0;
}
void yyerror(
const
char *s, ...)
{
fprintf
(stderr,
"error: %s\n"
, s);
}
void zzerror(
const
char *s, ...)
{
extern int yylineno;
va_list ap;
va_start(ap, s);
fprintf
(stderr,
"%d: error: "
, yylineno);
vfprintf(stderr, s, ap);
fprintf
(stderr,
"\n"
);
}
int yywrap(void)
{
return
1;
}
char* getsql()
{
return
parsetreeroot;
}
这部分就是对上一个识别出来的词 进行顺序上的确定,构成一个完整的语法