📄 check.c
字号:
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "struct.h"
#include "error.h"
/*------------------------------用来进行语法树的显示------------------------------*/
void show_condition(_conditions_type *con) /*用来显示条件语法树中的一个叶节点*/
{ /*即比较符号的左半边或右半边*/
switch (con->type)
{case '2':
{printf("type:table_field_ ,table: %s, field: %s\n",con->table,con->value);
break;
}
case '1':
{printf("type: char,string: %s\n",con->value);
break;
}
case '0':
{printf("type: int,number: %s-%d\n",con->value,con->intval);
break;
}
}
}
void conditionsexe(_conditions_type *con) /*用来显示where子句*/
{
_conditions_type *stack[20]; /*堆栈,存放中间节点*/
int st_int[20]; /*辅助堆栈,用来标识对应stack堆栈中节点的左右节点的入栈情况*/
int p=0;
stack[p]=con;
st_int[p]=0;
do
{
switch (stack[p]->comp_op)
{case 'a':
case 'o':
{
switch (st_int[p])
{case 0 : /*表示没有子节点入栈了*/
{p++;
stack[p]=stack[p-1]->left;
st_int[p]=0;
break;
}
case 1 : /*表示左节点入栈了*/
{p++;
stack[p]=stack[p-1]->right;
st_int[p]=0;
break;
}
case 2 : /*表示右节点入栈了*/
{printf("%c\n",stack[p]->comp_op);
p--;
if (p>=0) st_int[p]++;
break;
}
}
break;
}
case '<':
case '>':
case '=':
{ /*说明已经到了叶节点,该显示了*/
show_condition(stack[p]->left);
show_condition(stack[p]->right);
printf("%c\n",stack[p]->comp_op); /*显示晚左右叶节点,显示比较符号*/
p--;
if (p>=0) st_int[p]++;
break;
}
}
}while(p!=-1);
}
void selectexe(_selectstruct_type *ss) /*用来检测select语句的语法树是否正确*/
{
_selectedfields_type *sf1;
_selectedtables_type *st1;
printf("fields_star: ");
sf1=ss->sf;
do
{
if (sf1->table!=NULL)
{ printf("%s.",sf1->table);}
printf("%s",sf1->field);
if (sf1->next_sf==NULL) break;
sf1=sf1->next_sf;
printf(",");
}while(1);
printf("\n");
printf("tables: ");
st1=ss->st;
do
{ printf("%s",st1->table);
if(st1->next_st==NULL) break;
st1=st1->next_st;
printf(",");
}while(1);
printf("\n");
if (ss->cons!=NULL) conditionsexe(ss->cons);
}
void createexe(_createstruct_type *cs) /*用来检测create语句的语法树是否正确*/
{
_createfieldsdef_type *cfdef1;
printf("table: %s\n",cs->table);
cfdef1=cs->fdef;
printf("fieldsdefinition: ");
do
{
printf("%s-%s-%s",cfdef1->field,cfdef1->type,cfdef1->length);
if (cfdef1->next_fdef==NULL) break;
cfdef1=cfdef1->next_fdef;
printf(",");
}while(1);
printf("\n");
}
void insertexe(_insertstruct_type *is) /*用来检测insert语句的语法树是否正确*/
{
_insertfields_type *ifs1;
_insertvalues_type *iv1;
printf("table: %s\n",is->table);
if (is->ifs!=NULL)
{ ifs1=is->ifs;
printf("fields: ");
do
{
printf("%s",ifs1->field);
if (ifs1->next_if==NULL) break;
ifs1=ifs1->next_if;
printf(",");
}while(1);
printf("\n");
}
iv1=is->iv;
printf("values: ");
do
{
printf("%s--%c",iv1->value,iv1->type);
if (iv1->next_iv==NULL) break;
iv1=iv1->next_iv;
printf(",");
}while(1);
printf("\n");
}
void deleteexe(_deletestruct_type *ds) /*用来检测delete语句的语法树是否正确*/
{
printf("table: %s",ds->table);
printf("\n");
if (ds->cons!=NULL) conditionsexe(ds->cons);
}
/*------------------------------用来显示数据字典的相关信息-----------------------*/
void show_tables(_tab_dic_type *tab,int tab_num) /*用来显示已经存在的表*/
{
int i=0,j=0;
for (i=0;i<tab_num;i++)
// for (j=0;j<tab_num;j++)
{
if(is_a_table_dropped(tab[i].tab_name)==0)
{
printf("TABLE_%d:\t%s\n",j+1,tab[i].tab_name);
j++;
}
}
}
void show_tab_dic(_tab_dic_type *tab,int tab_num) /*详细显示表字典表的信息*/
{
int i=0;
printf("表名\t表序号\t首地址块\t字段数\t记录数\t记录长度\n");
for (i=0;i<tab_num;i++)
{
if(is_a_table_dropped(tab[i].tab_name)==1)
continue;
printf("%s\t%d\t%d\t\t%d\t%d\t%d\n",
tab[i].tab_name,tab[i].tab_id,tab[i].first_free_block,tab[i].col_num,tab[i].row_num,tab[i].row_len);
}
}
int get_tab_id(_tab_dic_type *tab,int tab_num,char *table) /*用来取得一个表的表序号*/
{
int i=0;
for (i=0;i<tab_num;i++)
{if (strcmp(table,tab[i].tab_name)==0)
return(tab[i].tab_id);
}
return(0);
}
void show_col_dic(_tab_dic_type *tab,int tab_num,_col_dic_type *col,int col_num,char *table)
{ /*用来显示一个选定表的字段信息*/
int i=0;
int tab_id;
int type;
char *type_name[5]={"整型","字符串"," ","日期"};
tab_id=get_tab_id(tab,tab_num,table);
printf("表_%d:%s\t的字段信息\n",tab_id,table);
printf("名称\t类型\t长度\n");
// printf("名称\t序号\t类型\t长度\n");
for (i=0;i<col_num;i++)
{
if (tab_id==col[i].tab_id)
{
type=col[i].col_type ;
printf("%s\t%s\t%d\n",col[i].col_name,type_name[type],col[i].col_length);
}
}
}
/*--------------------------------进行语法树的初步语义检查----------------------------*/
/*主要就是根据数据字典,对不符合语义的语句给以出错处理*/
char *is_an_exist_table(_tab_dic_type *tab,int tab_num,char *table)
/*判断所用的表名是不是数据字典中已经有的*/
{
int i=0;
for (i=0;i<tab_num;i++)
{if (strcmp(table,tab[i].tab_name)==0)
return(""); /*在字典表中找到了相应的表名*/
}
return(ERROR0001); /*没有找到*/
}
char *is_the_col_in_this_table(char *col,char *default_table,char *used_table,_dic_type *dic)
/*判断一个列是不是在对应的表中*/
{ /*当default_table不为空时,就一定和used_table是一个*/
int i=0;
int tab_id;
tab_id=get_tab_id(dic->tab,dic->tab_num,used_table);
for (i=0;i<dic->col_num;i++)
{
if (tab_id==dic->col[i].tab_id && strcmp(col,dic->col[i].col_name)==0)
{ /*如果字典表中有对应的列和选择的列一致*/
if (strcmp(default_table,"")==0)
{
strcpy(default_table,used_table);
}
return("");
}
}
if (strcmp(default_table,"")==0) /*没有找到相应的列*/
{
return(ERROR0003); /*找不到相应列对应的默认表名*/
}
else
{
return(ERROR0004); /*表名和列名不对应*/
}
}
int is_a_table_dropped(char *table)
{
if(table[0]=='$')
// printf("table=%s,type=1\t",table);
return(1);
else
// printf("table=%s,type=0\t",table);
return(0);
}
char *is_a_table_selected(_selectedtables_type *st,char *table)
{ /*判断一个要用的表是不是已经选择出来的表中的*/
_selectedtables_type *st1;
st1=st;
do
{
if (strcmp(table,st1->table)==0) /*如果找到了匹配的表名*/
return("");
if (st1->next_st==NULL)
{
return(ERROR0002); /*使用了一个没有被选择的表*/
}
st1=st1->next_st;
}while(1);
}
char *is_a_right_col_used(char *col,char *table,_selectedtables_type *st,_dic_type *dic)
{ /*用来判断一个列是否是属于已经被选择了的若干表中的*/
_selectedtables_type *st1;
char *error_var="";
int match_tab_num=0;
st1=st;
if (strcmp(table,"")!=0) /*如果所选择的列给出了是属于哪个表的*/
{ /*先判断是否用的表属于选择出的表组合*/
error_var=is_a_table_selected(st1,table);
if (strcmp(error_var,"")!=0)
{ return(error_var);
}
/*再判断后面的字段名是不是属于前面的表中的*/
error_var=is_the_col_in_this_table(col,table,table,dic);
if (strcmp(error_var,"")!=0)
{ return(error_var);
}
return("");
}
else /*如果并没有给出所选择的列是属于哪个表的*/
{
do /*对于所选择的表组合中的每一个表进行判断*/
{
error_var=is_the_col_in_this_table(col,table,st1->table,dic);
if (strcmp(error_var,"")==0)
{ match_tab_num++;
if (match_tab_num>1) /*多于一个表中含有此子段,归属不确定*/
{
return(ERROR0005);
}
}
if (st1->next_st==NULL)
{ if(strcmp(table,"")==0)
{ return(error_var); /*如果到了结束也没有找到*/
}
else break;
}
st1=st1->next_st;
}while(1);
return("");
}
}
char get_type_of_col(_dic_type *dic,char *table,char *col) /*取得列的类型*/
{
int i=0;
int tab_id;
tab_id=get_tab_id(dic->tab,dic->tab_num,table);
for (i=0;i<dic->col_num;i++)
{
if (tab_id==dic->col[i].tab_id && strcmp(col,dic->col[i].col_name)==0)
{ /*如果字典表中有对应的列和选择的列一致*/
return(dic->col[i].col_type+'0');
}
}
return(0);
}
_col_dic_type *get_info_of_a_col(_dic_type *dic,char *table,char *col)
{
int i=0;
int tab_id;
tab_id=get_tab_id(dic->tab,dic->tab_num,table);
for (i=0;i<dic->col_num;i++)
{
if (tab_id==dic->col[i].tab_id && strcmp(col,dic->col[i].col_name)==0)
{ /*如果字典表中有对应的列和选择的列一致*/
return(&dic->col[i]);
}
}
return(0);
}
char *one_select_con_check(_dic_type *dic,_selectedtables_type *st,_conditions_type *cons)
{ /*检查一个条件比较式的正确性*/
char left_type,right_type;
_conditions_type *left,*right;
char *error_var;
left=cons->left;
right=cons->right;
/*先判断左半边是否是正确的字段*/
error_var=is_a_right_col_used(left->value,left->table,st,dic);
if (strcmp(error_var,"")!=0)
{ return(error_var);
}
left_type=get_type_of_col(dic,left->table,left->value); /*获得字段的类型*/
if (right->type=='2') /*表示右节点也是字段*/
{ /*判断右半边是否是正确的字段*/
error_var=is_a_right_col_used(right->value,right->table,st,dic);
if (strcmp(error_var,"")!=0)
{ return(error_var);
}
right_type=get_type_of_col(dic,right->table,right->value); /*获得字段的类型*/
}
else
{ right_type=right->type; /*如果不是字段,也要获得字段的类型*/
}
// if (left_type!=right_type) /*左右两边的类型不匹配*/
// { return(ERROR0006);
// }
if ((cons->comp_op=='>' || cons->comp_op=='<') && right_type=='1') /*企图用<,>来判断字符串*/
{ return(ERROR0007);
}
return("");
}
char *select_cons_check(_dic_type *dic,_selectstruct_type *ss)
{
_conditions_type *stack[20]; /*堆栈,存放中间节点*/
int st_int[20]; /*辅助堆栈,用来标识对应stack堆栈中节点的左右节点的入栈情况*/
int p=0;
char *error_var;
stack[p]=ss->cons;
st_int[p]=0;
do
{
switch (stack[p]->comp_op)
{case 'a':
case 'o':
{
switch (st_int[p])
{case 0 : /*表示没有子节点入栈了*/
{p++;
stack[p]=stack[p-1]->left;
st_int[p]=0;
break;
}
case 1 : /*表示左节点入栈了*/
{p++;
stack[p]=stack[p-1]->right;
st_int[p]=0;
break;
}
case 2 : /*表示右节点入栈了*/
{
p--;
if (p>=0) st_int[p]++;
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -