static int parser_condition(symbItem **src1,symbItem **src2,string &oprname)//传进lable1 { if(!parser_expression()) { string testset[]={"","<","<=",">",">=","=","<>"}; parser_test(testset,7); if(lex_sym=="") { global_error("relational operators","nothing"); return 0; } } else { *src1=operand_stack.top(); operand_stack.pop(); } oprname=lex_sym; if(!if_ralation_opr(oprname)) { global_error("relational operators","nothing"); return 0; } lex_getsym(); if(!parser_expression()) return 0; *src2=operand_stack.top(); operand_stack.pop(); #ifdef PARSER_DEBUG cout << "条件" << endl; #endif return 1; }
int add_column(screen_t* const s, char* header, char* format, char* desc, char* expr) { int col_width, err=0; int n = s->num_columns; expression* e = parser_expression(expr); if (e == NULL || e->type == ERROR) { free_expression(e); error_printf("Invalid expression in column '%s', screen '%s': column ignored\n", header, s->name); return -1; } check_counters_used(e, s, &err); if( err > 0 ) { free_expression(e); return -1; } if (n == s->num_alloc_columns) { s->columns = realloc(s->columns, sizeof(column_t) * (n + alloc_chunk)); s->num_alloc_columns += alloc_chunk; } init_column(&s->columns[n]); s->columns[n].expression = e; s->columns[n].header = strdup(header); s->columns[n].format = strdup(format); col_width = strlen(header); /* setup an empty field with proper width */ s->columns[n].empty_field = malloc(col_width + 1); memset(s->columns[n].empty_field, ' ', col_width - 1); s->columns[n].empty_field[col_width - 1] = '-'; s->columns[n].empty_field[col_width] = '\0'; /* setup an error field with proper width */ s->columns[n].error_field = malloc(col_width + 1); memset(s->columns[n].error_field, ' ', col_width - 1); s->columns[n].error_field[col_width - 1] = '?'; s->columns[n].error_field[col_width] = '\0'; if (desc) s->columns[n].description = strdup(desc); else s->columns[n].description = strdup("(unknown)"); s->num_columns++; return n; }
/* Adding a new counter in counters list */ int add_counter(screen_t* const s, char* alias, char* config, char* type) { uint64_t int_conf = 0; uint32_t int_type = 0; int err=0; int n; expression* expr = NULL; if (s->num_counters >= MAX_EVENTS) { error_printf("Too many counters (max %d) in screen '%s', ignoring '%s'\n" "(change MAX_EVENTS and recompile)\n", MAX_EVENTS, s->name, alias); return -1; } int_type = get_counter_type(type, &err); if (err > 0) { /* error*/ error_printf("Bad type '%s': ignoring counter '%s'\n", type, alias); return -1; } /* Parse the configuration */ expr = parser_expression(config); err=0; int_conf = evaluate_counter_expression(expr, &err); free_expression(expr); if (err > 0) { /* error*/ error_printf("Bad config '%s': ignoring counter '%s'\n", config, alias); return -1; } n = s->num_counters; /* check max available hw counter */ if (n == s->num_alloc_counters) { s->counters = realloc(s->counters, sizeof(counter_t) * (n + alloc_chunk)); s->num_alloc_counters += alloc_chunk; } /* initialisation */ s->counters[n].used = 0; s->counters[n].type = int_type; s->counters[n].config = int_conf; s->counters[n].alias = strdup(alias); s->num_counters++; return n; }
static int parser_statement(symbItem *forbid) { symbItem *tmp; if(lex_sym=="ident") { tmp=symbtable_check(lex_token); if(tmp==NULL) { global_error("legal ident",lex_token); return 0; } if(tmp==forbid)//该标识符不可以被赋值 { global_error("this ident\""+tmp->name+"\"can not be changed."); return 0; } if(tmp->kind=="const") { global_error(tmp->name+" can not be changed."); return 0; } else if(tmp->kind=="var"||tmp->kind=="parameter") { lex_getsym(); if(lex_sym==":="||lex_sym=="=") { if(lex_sym=="=") global_error(":=","="); } else { global_error(":=",lex_sym); return 0; } lex_getsym(); if(!parser_expression()) { return 0; } symbItem *expre=operand_stack.top(); operand_stack.pop(); if(expre->kind=="const") expre=parser_create_new_const(expre); if(tmp->type=="char"&&expre->type=="integer") { global_error("integer can not be asssigned to a char"); // mark_i=0; } global_new_quadruple("assign",expre,NULL,tmp); } else if(tmp->kind=="array") {//tmp [src1] symbItem *src2; lex_getsym(); if(lex_sym!="[") { global_error("[",lex_sym); return 0; } lex_getsym(); if(!parser_expression()) { string testset[]={"","]",":="}; parser_test(testset,3); if(lex_sym=="") { global_error("]","nothing"); return 0; } } else { src2=operand_stack.top(); operand_stack.pop(); if(src2->kind=="const") src2=parser_create_new_const(src2); } if(lex_sym!="]") { global_error("]",lex_sym); return 0; } lex_getsym(); if(lex_sym==":="||lex_sym=="=") { if(lex_sym=="=") global_error(":=",lex_sym); } else { global_error(":=",lex_sym); return 0; } lex_getsym(); if(!parser_expression()) return 0; symbItem *ans=operand_stack.top(); operand_stack.pop(); if(ans->kind=="const") ans=parser_create_new_const(ans); if(tmp->type=="char"&&ans->type=="integer") { global_error("integer can not be asssigned to a char"); } global_new_quadruple("sarray",tmp,src2,ans);//tmp[src2]=ans } else if(tmp->kind=="function")//函数标示符=表达式 {//函数标识符只能是本层函数或者他的父层函数 if(!symbtable_if_can_change_func(tmp->name)) { global_error("function \""+tmp->name+"\" can not be changed in this scope."); return 0; } lex_getsym(); if(lex_sym!="="&&lex_sym!=":=") { global_error(":=",lex_sym); return 0; } if(lex_sym=="=") global_error(":=",lex_sym); lex_getsym(); if(!parser_expression()) return 0; symbItem *src1=operand_stack.top(); operand_stack.pop(); if(src1&&src1->kind=="const") src1=parser_create_new_const(src1); if(src1->type=="integer"&&tmp->type=="char") global_error("integer can not be assigined to a char "); global_new_quadruple("assign",src1,NULL,tmp); } else if(tmp->kind=="procedure")//过程调用语句,tmp已经经过差表 { if(!tmp->size) { lex_getsym(); if(lex_sym=="(") { global_error("no parameter",lex_sym); return 0; } } else { lex_getsym(); if(!parser_realparameterlist(tmp)) return 0; } global_new_quadruple("call",tmp,NULL,NULL); } else { global_error("no possible."); return 0; } } else if(lex_sym=="if")// { symbItem *lable1,*lable2,*src1,*src2; string oprname; lable1=parser_create_new_lable(); lex_getsym(); if(!parser_condition(&src1,&src2,oprname)) { string testset[]={"","then","else"}; parser_test(testset,3); if(lex_sym=="") { global_error("then","nothing"); return 0; } } else { oprname=global_anti_ralation[oprname]; if(src1&&src1->kind=="const") src1=parser_create_new_const(src1); if(src2&&src2->kind=="const") src2=parser_create_new_const(src2); global_new_quadruple(oprname,src1,src2,lable1); } if(lex_sym!="then") { global_error("then",lex_sym);//容忍缺then的行为 } else lex_getsym(); if(!parser_statement(NULL)) { return 0;//???? } if(lex_sym!="else") { global_new_quadruple("lab",lable1,NULL,NULL); } else { lable2=parser_create_new_lable(); global_new_quadruple("jmp",lable2,NULL,NULL); global_new_quadruple("lab",lable1,NULL,NULL); lex_getsym(); if(!parser_statement(NULL)) return 0; global_new_quadruple("lab",lable2,NULL,NULL); } } else if(lex_sym=="begin") { lex_getsym(); if(!parser_compoundstatement()) return 0; } else if(lex_sym=="do") { symbItem *lable1=parser_create_new_lable(); symbItem *src1,*src2; string oprname; global_new_quadruple("lab",lable1,NULL,NULL); lex_getsym(); if(!parser_statement(NULL)) { string testset[]={"","while"}; parser_test(testset,2); if(lex_sym=="") { global_error("while","nothing"); return 0; } } if(lex_sym!="while") { global_error("while",lex_sym); return 0; } lex_getsym(); if(!parser_condition(&src1,&src2,oprname)) return 0; oprname=global_ralation[oprname]; if(src1&&src1->kind=="const") src1=parser_create_new_const(src1); if(src2&&src2->kind=="const") src2=parser_create_new_const(src2); global_new_quadruple(oprname,src1,src2,lable1); } else if(lex_sym=="write") { string testset[]={"",")"}; lex_getsym(); if(lex_sym!="(") { global_error("(",lex_sym); string testset2[]={"",")"}; parser_test(testset2,2); if(lex_sym=="") { global_error(")","nothing"); return 0; } } else lex_getsym(); if(lex_sym=="string") { symbItem *item=new symbItem(); item->name=lex_token; my_write_string.push(lex_token); item->value=my_writes_num++; item->kind="constpool"; item->type="string";//digit,char,string,lable item->link=NULL; global_const_pool.push(item); global_new_quadruple("writes",item,NULL,NULL); lex_getsym(); if(lex_sym==",") { lex_getsym(); if(!parser_expression()) { parser_test(testset,2); if(lex_sym=="") { global_error(")","nothing"); return 0; } } else { symbItem *src=operand_stack.top(); if(src->kind=="const") src=parser_create_new_const(src); global_new_quadruple("writee",src,NULL,NULL); operand_stack.pop(); } } } else//表达式 { if(!parser_expression()) { parser_test(testset,2); if(lex_sym=="") { global_error(")","nothing"); return 0; } } else { symbItem *src=operand_stack.top(); if(src->kind=="const") src=parser_create_new_const(src); global_new_quadruple("writee",src,NULL,NULL); operand_stack.pop(); } } if(lex_sym!=")") { global_error(")",lex_sym); return 0; } lex_getsym(); } else if(lex_sym=="read")//func,var,para? { lex_getsym(); int flag=0; if(lex_sym!="(") { global_error("(",lex_sym); return 0; } do{ lex_getsym(); if(lex_sym!="ident") { global_error("ident",lex_sym); flag=1; } else//"ident" { symbItem *ans=symbtable_check(lex_token); if(ans==NULL) { global_error(lex_token+" is not declared in this scope."); flag=1; } else { if(ans->kind=="const") { global_error("const \""+ans->name+"\" can not be changed"); flag=1; } else if(ans->kind=="procedure") { global_error("procedure \""+ans->name+"\" can not be changed"); flag=1; } else if(ans->kind=="function"&&!symbtable_if_can_change_func(ans->name)) { global_error("function \""+ans->name+"\" can not be changed in this scope."); flag=1; } else { global_new_quadruple("read",ans,NULL,NULL); } } } if(flag) { string testset[]={"",",",")"}; parser_test(testset,3); if(lex_sym=="") { global_error(")",lex_sym); return 0; } } else lex_getsym(); }while(lex_sym==","); if(lex_sym!=")") { global_error(")",lex_sym); return 0; } lex_getsym(); } else if(lex_sym=="for") { int downto=0; symbItem *tmp,*target,*lable1,*lable2; lex_getsym(); if(lex_sym!="ident") { global_error("ident",lex_sym); return 0; } tmp=symbtable_check(lex_token); int flag=0; if(tmp->kind=="const") { global_error("const \""+tmp->name+"\" can not be changed."); flag=1; } else if(tmp->kind=="procedure") { global_error("procedure \""+tmp->name+"\" can not be changed."); flag=1; } else { if(!parser_statement(NULL)) flag=1;//生成首次赋值语句。 } if(flag) { string testset[]={"","to","downto"}; parser_test(testset,3); if(lex_sym=="") { global_error("downto or to","nothing"); return 0; } } if(lex_sym!="downto"&&lex_sym!="to") { global_error("downto or to",lex_sym); return 0; } else downto=lex_sym=="downto"; lex_getsym(); if(!parser_expression()) { string testset[]={"","do"}; parser_test(testset,2); if(lex_sym=="") { global_error("do","nothing"); return 0; } } else { target=operand_stack.top(); operand_stack.pop(); if(target->kind=="const") target=parser_create_new_const(target); } if(lex_sym!="do") { global_error("do",lex_sym); // return 0; } lex_getsym(); lable1=parser_create_new_lable(); lable2=parser_create_new_lable(); global_new_quadruple("lab",lable1,NULL,NULL); string opr=downto?"jl":"jg"; global_new_quadruple(opr,tmp,target,lable2); if(!parser_statement(tmp)) return 0; opr=downto?"dec":"inc"; global_new_quadruple(opr,tmp,NULL,NULL); global_new_quadruple("jmp",lable1,NULL,NULL); global_new_quadruple("lab",lable2,NULL,NULL); } else { //空语句怎么处理,那就不处理好了? } #ifdef PARSER_DEBUG cout <<"语句"<< endl; #endif return 1; }
static int parser_factor() { symbItem *operand; if(lex_sym=="ident") { operand=symbtable_check(lex_token); if(operand==NULL) { global_error("legal ident",lex_token); return 0; } if(operand->kind=="array") { parser_create_new_var(operand); symbItem *ans=symbtable_now->last_item,*src2; lex_getsym(); if(lex_sym!="[") { global_error("[",lex_sym); return 0; } lex_getsym(); if(!parser_expression()) { string testset[]={"","]"}; parser_test(testset,2); if(lex_sym=="") { global_error("]","nothing"); return 0; } } else{ src2=operand_stack.top(); operand_stack.pop(); if(src2->kind=="const") src2=parser_create_new_const(src2); } if(lex_sym!="]") { global_error("]",lex_sym); return 0; } if(ans->type=="char"&&operand->type=="integer") { global_error("integer can not be asssigned to a char"); } global_new_quadruple("larray",operand,src2,ans);//ans=operand[src2] operand_stack.push(ans); lex_getsym(); } else if(operand->kind=="function") { parser_create_new_var(operand->type); symbItem *ans=symbtable_now->last_item; lex_getsym(); if(lex_sym=="("&&!operand->size) { global_error("no parameter",lex_sym); return 0; } else if(operand->size) { if(!parser_realparameterlist(operand)) return 0; } global_new_quadruple("call",operand,NULL,NULL); global_new_quadruple("assign",operand,NULL,ans); operand_stack.push(ans); } else if(operand->kind=="procedure") { global_error("factor","procedure "+operand->name); return 0; } else { operand_stack.push(operand);//获得操作数 lex_getsym(); } } else if(lex_sym=="(") { lex_getsym(); if(!parser_expression()) { string testset[]={"",")"}; parser_test(testset,2); if(lex_sym=="") { global_error(")","nothing"); return 0; } } if(lex_sym!=")") { global_error(")",lex_sym); return 0; } lex_getsym(); } else if(lex_sym=="digit") { symbItem *item=new symbItem(); item->name=numtostring(lex_value); item->value=lex_value; item->kind="constpool"; item->type="integer";//digit,char,string,lable item->link=NULL; operand_stack.push(item); global_const_pool.push(item);//放到常量池里面 lex_getsym(); } else { global_error("legal factor",lex_sym); return 0; } #ifdef PARSER_DEBUG cout << "因子" << endl; #endif return 1; }
//Require: item is func or proc //暂时不跳读,因为,一行而已。。本身久错了 static int parser_realparameterlist(symbItem *func_proc) {//func后面一定要紧跟着参数信息,这是四元式中操作数的一部分,虽然你没用到他的值,但你用到的是他的其他信息; //need to find the location of func or proc stack<symbItem*> para_stack; symbItem *src; if(lex_sym!="(") { global_error("(",lex_sym); return 0; } do{ lex_getsym(); if(!parser_expression()) { string testset[]={"",",",")"}; parser_test(testset,3); if(lex_sym=="") { global_error(")","nothing"); return 0; } } else { para_stack.push(operand_stack.top()); operand_stack.pop(); } }while(lex_sym==","); if((unsigned)func_proc->size!=para_stack.size()) { global_error("wrong num of parametes in \""+func_proc->name+"\"call."); return 0; }//good,我是指针我怕谁 //require: enough para item in the global_table int j=func_proc->size; symbItem *k=func_proc->link; if(func_proc->name==symbtable_now->name)//调用自身此时符号表没调整。 k=symbtable_now->first_item; else if(j&&(k==NULL||k->kind!="parameter"))//这里子表没有撤回的情况有很多,不过一旦动用了这条分支,意味着死循环 { symbTable *tmp=symbtable_now; while(tmp->name!=func_proc->name) tmp=tmp->father; k=tmp->first_item; } int mark_i=0; stack<symbItem*> paras; symbItem *twx=k; for(int i=1;i<=j;i++) { paras.push(twx); twx=twx->link; } for(int i=1;i<=j;i++)//k是顺着来的而栈里的参数是反着来的。。 { src=para_stack.top(); para_stack.pop(); if(paras.top()->type=="char"&&src->type=="integer") { global_error("parameter type error:char","integer:"); mark_i=1; } if(paras.top()->para_ifvar&¶s.top()->type=="integer"&&src->type=="char") { global_error("real parameter type error,integer","char"); } paras.pop(); if(k->para_ifvar&&src->kind!="const")//可能撤表了也可能没撤 { if(src->kind=="var"&&src->name[0]=='_') { global_error("legal var parameter","expression"); mark_i=1; } else global_new_quadruple("rpara",src,func_proc,NULL); } else if(k->para_ifvar&&src->kind=="const") { global_error("legal var parameter","const"); mark_i=1; } else { if(src->kind=="const") src=parser_create_new_const(src); global_new_quadruple("fpara",src,func_proc,NULL); } if(k==NULL) cout << "are you kidding me!" <<endl; k=k->link;//Require k<>NULL; } if(lex_sym!=")") { global_error(")",lex_sym); return 0; } lex_getsym(); #ifdef PARSER_DEBUG cout << "实在参数表" << endl; #endif /* if(mark_i) return 0;*/ return 1; }