📄 spl.y.c
字号:
#ifdef GENERATE_AST { list_clear(&dag_forest); t = new_tree(TAIL, NULL, NULL, NULL); list_append(&ast_forest, t); /* generate dag forest. */ gen_dag(&ast_forest, &dag_forest); /* emit asm code. */ emit_code(&dag_forest); }#else emit_routine_epilogue(top_symtab_stack());#endif pop_symtab_stack();};procedure_head:kPROCEDURE{#ifdef GENERATE_AST list_clear(&ast_forest); list_clear(¶_list);#endif ptab = new_symtab(top_symtab_stack()); push_symtab_stack(ptab);}yNAME parameters{ ptab = top_symtab_stack(); strncpy(ptab->name, $3, NAME_LEN); sprintf(ptab->rname, "rtn%03d",ptab->id); ptab->defn = DEF_PROC; p = new_symbol($3, DEF_PROC, TYPE_VOID); add_symbol_to_table(ptab,p); reverse_parameters(ptab);#ifdef GENERATE_AST { Tree header; header = new_tree(HEADER, find_type_by_id(TYPE_VOID), NULL, NULL); header->u.header.para = ¶_list; list_append(&ast_forest, header); now_function = new_tree(ROUTINE, find_type_by_id(TYPE_VOID), header, NULL); }#endif };parameters:oLP para_decl_list oRP{ ptab = top_symtab_stack(); ptab->local_size = 0;}|;para_decl_list:para_decl_list oSEMI para_type_list|para_type_list;para_type_list: val_para_list oCOLON simple_type_decl{ ptab = top_symtab_stack(); for(p = $1; p ;){ if($3->type_id == TYPE_SUBRANGE) p->type = $3->first->type; else if ($3->type_id == TYPE_ENUM) p->type = find_type_by_id(TYPE_INTEGER); else p->type = find_type_by_id($3->type_id); p->type_link = $3; p->defn = DEF_VALPARA; q = p; p = p->next; q->next = NULL; add_symbol_to_table(ptab,q);#ifdef GENERATE_AST /* append to paralist. */ list_append(¶_list, q);#endif } $1 = NULL;}| var_para_list oCOLON simple_type_decl{ ptab = top_symtab_stack(); for(p = $1; p;){ if($3->type_id == TYPE_SUBRANGE) p->type = $3->first->type; else if($3->type_id == TYPE_ENUM) p->type = find_type_by_id(TYPE_INTEGER); else p->type = find_type_by_id($3->type_id); p->type_link = $3; p->defn = DEF_VARPARA; q = p; p = p->next; q->next=NULL; add_symbol_to_table(ptab,q);#ifdef GENERATE_AST /* append to para_list. */ list_append(¶_list, q);#endif } $1 = NULL;};val_para_list:name_list;var_para_list:kVAR name_list{ $$ = $2;};routine_body:compound_stmt;stmt_list:stmt_list stmt oSEMI|stmt_list error oSEMI|;stmt:cINTEGER oCOLON non_label_stmt| non_label_stmt;non_label_stmt:assign_stmt| proc_stmt| compound_stmt| if_stmt| repeat_stmt| while_stmt| for_stmt| case_stmt| goto_stmt|;assign_stmt:yNAME oASSIGN expression{ p = find_symbol(top_symtab_stack(), $1); if (p == NULL) { parse_error("Undefined identifier", $1); p = install_temporary_symbol($1, DEF_VAR, TYPE_INTEGER); } if(p->type->type_id == TYPE_ARRAY ||p->type->type_id == TYPE_RECORD) { parse_error("lvalue expected",""); /* return 0; */ } if (p && p->defn != DEF_FUNCT) { #ifdef GENERATE_AST if(p->type->type_id != $3->result_type->type_id) #else if(p->type->type_id != $3) #endif { parse_error("type mismatch",""); /* return 0; */ } } else { ptab = find_routine($1); if(ptab) { #ifdef GENERATE_AST if(ptab->type->type_id != $3->result_type->type_id) #else if(ptab->type->type_id != $3) #endif { parse_error("type mismatch",""); /* return 0; */ } } else{ parse_error("Undeclared identifier.",$1); #ifdef GENERATE_AST install_temporary_symbol($1, DEF_VAR, $3->result_type->type_id); #else install_temporary_symbol($1, DEF_VAR, $3); #endif /* return 0; */ } }#ifdef GENERATE_AST t = address_tree(NULL, p); $$ = assign_tree(t, $3); /* append to forest. */ list_append(&ast_forest, $$); #else if (p && p->defn != DEF_FUNCT) { do_assign(p, $3); } else { do_function_assign(ptab, $3); }#endif}|yNAME oLB{ p = find_symbol(top_symtab_stack(), $1); if(!p || p->type->type_id != TYPE_ARRAY){ parse_error("Undeclared array name",$1); return 0; } push_term_stack(p);#ifdef GENERATE_AST#else emit_load_address(p); emit_push_op(TYPE_INTEGER);#endif}expression oRB{ p = top_term_stack();#ifdef GENERATE_AST p = find_symbol(top_symtab_stack(), $1); if(!p || p->type->type_id != TYPE_ARRAY){ parse_error("Undeclared array name",$1); return 0; } t = array_factor_tree(p, $4); t = address_tree(t, p); push_ast_stack(t);#else do_array_factor(p);#endif}oASSIGN expression{#ifdef GENERATE_AST t = pop_ast_stack(); $$ = assign_tree(t, $8); list_append(&ast_forest, $$);#else p = pop_term_stack(); do_assign(p, $8);#endif}|yNAME oDOT yNAME{ p = find_symbol(top_symtab_stack(),$1); if(!p || p->type->type_id != TYPE_RECORD){ parse_error("Undeclared record vaiable",$1); return 0; } q = find_field(p,$3); if(!q || q->defn != DEF_FIELD){ parse_error("Undeclared field",$3); return 0; }#ifdef GENERATE_AST t = field_tree(p, q); t = address_tree(t, q); push_ast_stack(t);#else emit_load_address(p); emit_push_op(TYPE_INTEGER); do_record_factor(p,q); push_term_stack(p); push_term_stack(q);#endif}oASSIGN expression{#ifdef GENERATE_AST t = pop_ast_stack(); $$ = assign_tree(t, $6); list_append(&ast_forest, $$);#else q = pop_term_stack(); p = pop_term_stack(); do_assign(q, $6);#endif};proc_stmt:yNAME{ ptab = find_routine($1); if(!ptab || ptab->defn != DEF_PROC){ parse_error("Undeclared procedure",$1); return 0; }#ifdef GENERATE_AST $$ = call_tree(ptab, NULL); list_append(&ast_forest, $$);#else do_procedure_call(ptab);#endif}|yNAME{ ptab = find_routine($1); if(!ptab || ptab->defn != DEF_PROC){ parse_error("Undeclared procedure",$1); return 0; } push_call_stack(ptab);}oLP args_list oRP{#ifdef GENERATE_AST $$ = call_tree(top_call_stack(), args); list_append(&ast_forest, $$);#else do_procedure_call(top_call_stack());#endif pop_call_stack();}|SYS_PROC{#ifdef GENERATE_AST $$ = sys_tree($1->attr, NULL); list_append(&ast_forest, $$);#else do_sys_routine($1->attr, 0);#endif}|SYS_PROC { rtn = find_sys_routine($1->attr); if(rtn) arg = rtn->args; else { arg = NULL; } push_call_stack(rtn);}oLP expression_list oRP {#ifdef GENERATE_AST $$ = sys_tree($1->attr, $4); list_append(&ast_forest, $$);#else do_sys_routine($1->attr, $4);#endif pop_call_stack();}|pREAD oLP factor oRP{ if(!$3){ parse_error("too few parameters in call to", "read"); return 0; }#ifdef GENERATE_AST if (generic($3->op) == LOAD) t = address_tree(NULL, $3->u.generic.sym); else t = address_tree($3, $3->u.generic.sym); $$ = sys_tree(pREAD, t); list_append(&ast_forest, $$);#else emit_load_address($3); do_sys_routine(pREAD, $3->type->type_id);#endif};compound_stmt:kBEGIN{#ifdef GENERATE_AST /* block begin. */ t = new_tree(BLOCKBEG, NULL, NULL, NULL); list_append(&ast_forest, t);#endif}stmt_listkEND{#ifdef GENERATE_AST /* block end. */ t = new_tree(BLOCKEND, NULL, NULL, NULL); list_append(&ast_forest, t);#endif};if_stmt:kIF {#ifdef GENERATE_AST push_lbl_stack(if_label_count++);#endif}expression kTHEN{#ifdef GENERATE_AST snprintf(mini_buf, sizeof(mini_buf) - 1, "if_false_%d", top_lbl_stack()); mini_buf[sizeof(mini_buf) - 1] = 0; new_label = new_symbol(mini_buf, DEF_LABEL, TYPE_VOID); t = cond_jump_tree($3, false, new_label); list_append(&ast_forest, t);#else do_if_test();#endif}stmt{#ifdef GENERATE_AST snprintf(mini_buf, sizeof(mini_buf) - 1, "if_false_%d", top_lbl_stack()); mini_buf[sizeof(mini_buf) - 1] = 0; new_label = new_symbol(mini_buf, DEF_LABEL, TYPE_VOID); t = label_tree(new_label); push_ast_stack(t); snprintf(mini_buf, sizeof(mini_buf) - 1, "if_exit_%d", top_lbl_stack()); mini_buf[sizeof(mini_buf) - 1] = 0; exit_label = new_symbol(mini_buf, DEF_LABEL, TYPE_VOID); /* append jump tree. */ t = jump_tree(exit_label); list_append(&ast_forest, t); /* append label tree. */ t = pop_ast_stack(); list_append(&ast_forest, t);#else do_if_clause();#endif}else_clause{#ifdef GENERATE_AST /* append exit label. */ snprintf(mini_buf, sizeof(mini_buf) - 1, "if_exit_%d", top_lbl_stack()); mini_buf[sizeof(mini_buf) - 1] = 0; exit_label = new_symbol(mini_buf, DEF_LABEL, TYPE_VOID); t = label_tree(exit_label); list_append(&ast_forest, t); pop_lbl_stack();#else do_if_exit();#endif}|kIF error { printf("expression expected.\n");}kTHEN { printf("then matched.\n");}stmt else_clause;else_clause:kELSE stmt|;repeat_stmt:kREPEAT{#ifdef GENERATE_AST push_lbl_stack(repeat_label_count++); snprintf(mini_buf, sizeof(mini_buf) - 1, "repeat_%d", repeat_label_count - 1); mini_buf[sizeof(mini_buf) - 1] = 0; new_label = new_symbol(mini_buf, DEF_LABEL, TYPE_VOID); t = label_tree(new_label); list_append(&ast_forest, t);#else do_repeat_start();#endif}stmt_list kUNTIL expression{#ifdef GENERATE_AST snprintf(mini_buf, sizeof(mini_buf) - 1, "repeat_%d", top_lbl_stack()); mini_buf[sizeof(mini_buf) - 1] = 0; new_label = new_symbol(mini_buf, DEF_LABEL, TYPE_VOID); t = cond_jump_tree($5, false, new_label); list_append(&ast_forest, t); pop_lbl_stack();#else do_repeat_exit();#endif};while_stmt:kWHILE{#ifdef GENERATE_AST push_lbl_stack(while_label_count++); snprintf(mini_buf, sizeof(mini_buf) - 1, "while_test_%d", while_label_count - 1); mini_buf[sizeof(mini_buf) - 1] = 0; test_label = new_symbol(mini_buf, DEF_LABEL, TYPE_VOID); t = label_tree(test_label); list_append(&ast_forest, t);#else do_while_start();#endif}expression kDO{#ifdef GENERATE_AST snprintf(mini_buf, sizeof(mini_buf) - 1, "while_exit_%d", top_lbl_stack()); mini_buf[sizeof(mini_buf) - 1] = 0; exit_label = new_symbol(mini_buf, DEF_LABEL, TYPE_VOID); t = cond_jump_tree($3, false, exit_label); list_append(&ast_forest, t);#else do_while_expr();#endif}stmt{#ifdef GENERATE_AST /* generate while_exit_%d label tree and push. */ snprintf(mini_buf, sizeof(mini_buf) - 1, "while_exit_%d", top_lbl_stack()); mini_buf[sizeof(mini_buf) - 1] = 0; exit_label = new_symbol(mini_buf, DEF_LABEL, TYPE_VOID); t = label_tree(exit_label); push_ast_stack(t); snprintf(mini_buf, sizeof(mini_buf) - 1, "while_test_%d", top_lbl_stack()); mini_buf[sizeof(mini_buf) - 1] = 0; test_label = new_symbol(mini_buf, DEF_LABEL, TYPE_VOID); /* jump to test tree. */ t = jump_tree(test_label); list_append(&ast_forest, t); /* pop while_exit_%d label tree and append. */ t = pop_ast_stack(); list_append(&ast_forest, t); pop_lbl_stack();#else do_while_exit();#endif};for_stmt:kFOR yNAME oASSIGN expression{ p = find_symbol(top_symtab_stack(),$2); if(!p || p->defn != DEF_VAR) { parse_error("lvalue expected",""); return 0; } if(p->type->type_id == TYPE_ARRAY ||p->type->type_id == TYPE_RECORD) { parse_error("lvalue expected",""); return 0; }#ifdef GENERATE_AST /* assign tree */ t = address_tree(NULL, p); push_ast_stack(t); list_append(&ast_forest, assign_tree(t, $4)); /* label tree. */ push_lbl_stack(for_label_count++); snprintf(mini_buf, sizeof(mini_buf) - 1, "for_test_%d", for_label_count - 1); mini_buf[sizeof(mini_buf) - 1] = 0; test_label = new_symbol(mini_buf, DEF_LABEL, TYPE_VOID); t = label_tree(test_label); list_append(&ast_forest, t);#else do_for_start(p);#endif}direction expression kDO{#ifdef GENERATE_AST snprintf(mini_buf, sizeof(mini_buf) - 1, "for_exit_%d", top_lbl_stack()); mini_buf[sizeof(mini_buf) - 1] = 0; exit_label = new_symbol(mini_buf, DEF_LABEL, TYPE_VOID); p = find_symbol(top_symtab_stack(),$2); t = id_factor_tree(NULL, p); if ($6 == kTO) { t = compare_expr_tree(LE, t, $7); } else { t = compare_expr_tree(GE, t, $7); } t = cond_jump_tree(t, false, exit_label); list_append(&ast_forest, t);#else do_for_test($6);#endif}stmt{#ifdef GENERATE_AST t = pop_ast_stack(); if ($6 == kTO) { t = incr_one_tree(t); } else { t = decr_one_tree(t); } list_append(&ast_forest, t); /* jump ast. */ snprintf(mini_buf, sizeof(mini_buf) - 1, "for_test_%d", top_lbl_stack()); mini_buf[sizeof(mini_buf) - 1] = 0; test_label = new_symbol(mini_buf, DEF_LABEL, TYPE_VOID); t = jump_tree(test_label); list_append(&ast_forest, t); /* add label ast. */ snprintf(mini_buf, sizeof(mini_buf) - 1, "for_exit_%d", top_lbl_stack()); mini_buf[sizeof(mini_buf) - 1] = 0; exit_label = new_symbol(mini_buf, DEF_LABEL, TYPE_VOID); t = label_tree(exit_label); list_append(&ast_forest, t); pop_lbl_stack();#else do_for_exit();#endif};direction:kTO{ $$ = kTO;}|kDOWNTO{ $$ = kDOWNTO;};case_stmt:kCASE {#ifdef GENERATE_AST push_lbl_stack(switch_label_count++); snprintf(mini_buf, sizeof(mini_buf) - 1, "switch_test_%d", switch_label_count - 1); mini_buf[sizeof(mini_buf) - 1] = 0; test_label = new_symbol(mini_buf, DEF_LABEL, TYPE_VOID); case_label_count = 0; t = jump_tree(test_label); list_append(&ast_forest, t); NEW0(case_list, STMT); push_case_ast_stack(case_list); case_label_count = 0; push_case_stack(case_label_count++); /* list_clear(&case_list); */#endif}expression kOF{#ifdef GENERATE_AST#else do_case_start();#endif}case_expr_list{#ifdef GENERATE_AST snprintf(mini_buf, sizeof(mini_buf) - 1, "switch_test_%d", top_lbl_stack()); mini_buf[sizeof(mini_buf) - 1] = 0; test_label = new_symbol(mini_buf, DEF_LABEL, TYPE_VOID); t = label_tree(test_label); list_append(&ast_forest, t); case_list = pop_case_ast_stack(); { int n = list_length(case_list); Tree *cases = (Tree *)list_ltov(case_list, PERM); int i; for (i = 0; i < n; i += 2) { new_label = cases[i]->u.label.label; t = compare_expr_tree(EQ, $3, cases[i + 1]); t = cond_jump_tree(t, true, new_label); list_append(&ast_forest, t); } } snprintf(mini_buf, sizeof(mini_buf) - 1, "switch_exit_%d", top_lbl_stack()); mini_buf[sizeof(mini_buf) - 1] = 0; exit_label = new_symbol(mini_buf, DEF_LABEL, TYPE_VOID); t = label_tree(exit_label); list_append(&ast_forest, t); pop_lbl_stack();#else do_case_test();#endif}kEND;case_expr_list:case_expr_list case_expr|case_expr;case_expr:const_value{#ifdef GENERATE_AST case_label_count = pop_case_stack(); snprintf(mini_buf, sizeof(mini_buf) - 1, "case_%d_%d", top_lbl_stack(), case_label_count++); mini_buf[sizeof(mini_buf) - 1] = 0; push_case_stack(case_label_count); new_label = new_symbol(mini_buf, DEF_LABEL, TYPE_VOID); t = label_tree(new_label); list_append(&ast_forest, t); case_list = top_case_ast_stack(); list_append(case_list, t); t = const_tree($1); list_append(case_list, t);#else add_case_const($1);#endif}oCOLON stmt{#ifdef GENERATE_AST
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -