zoukankan      html  css  js  c++  java
  • 语义分析和中间代码生成——哈工大编译原理课程(三)

       1 /*
       2 Author:ZhouLiyan*
       3 Date:2016.08.01
       4 Loc:Haerbin Institute Of Technology
       5 */
       6 
       7 #include <stdio.h>
       8 #include <stdlib.h>
       9 #include <string.h>
      10 #include <ctype.h>
      11 #include <math.h>
      12 
      13 #include <token_analyze.h>
      14 #include <operator.h>
      15 #include <data_struct.h>
      16 #include <FourElemFormula.h>
      17 #include <table.h>
      18 #include <queue.h>
      19 #include <symboltable.h>
      20 #include <stack.h>
      21 #include <linkedlist.h>
      22 #include <debug.h>
      23 
      24 symtbl *initst;
      25 
      26 FILE *fp;   //获取文件的指针
      27 
      28 int newflag = 0;        //标志是否新读入一个token
      29 int tempcount = 0;
      30 
      31 stack s1;
      32 symstack s2;
      33 stack off;
      34 sstack tbl;
      35 queue idli;
      36 queue actualpali;
      37 intqueue indexli;
      38 
      39 pstack state = &s1;
      40 psymstack symbol = &s2;
      41 pstack offset = &off;
      42 psstack tblptr = &tbl;
      43 pqueue idlist = &idli;
      44 pqueue actualpalist = &actualpali;
      45 pintqueue indexlist = &indexli;
      46 Identifier *templink;           //存放临时变量的链表
      47 
      48 pFour fmlay[300]={NULL};           //typedef FourElemFormula* pFour
      49 int fmlap = 1;
      50 
      51 Token ReadToken();    /*make(返回结构体)从文件中读取一行,返回Token*/
      52 void Reduction_Goto(int k);     /*按第k个产生式规约*/
      53 Identifier* lookup(char *name,symtbl* nowsym);       /*返回name节点在符号表中的指针,如不存在返回null*/
      54 
      55 void gencode(int op,char *arg1,char *arg2,char* ret);
      56 void backpatch(LabelNode* lis,int labelnum);
      57 
      58 int main()
      59 {
      60     Token token = (Token)malloc(sizeof(To));
      61     int index;
      62     int statenum;
      63 
      64     MakeNull(state);
      65     MakeNullsym(symbol);
      66     MakeNull(offset);
      67     MakeNulls(tblptr);
      68     MakeNULLQueue(idlist);
      69     MakeNULLQueue(actualpalist);
      70     IntMakeNULLQueue(indexlist);
      71     initList(&templink);
      72 
      73     if(token_analyze() == 1)        //词法分析失败
      74     {
      75         return 0;
      76     }
      77 
      78 
      79     fp = fopen("lex.txt","r");
      80 
      81     token->symbolnum = 0;
      82     push(state,0);
      83     pushsym(symbol,token);
      84     //printf("stack				production");
      85 
      86     while(1)
      87     {
      88         //printf("
    ");
      89         //PrintStack(state);
      90         //printf("%c",'&');
      91         //PrintSymStack(symbol);
      92 
      93         if(newflag == 0)
      94         {
      95             token = ReadToken();
      96         }
      97         statenum = state->elem[state->top];
      98 
      99         if(yypact[statenum] == YYPACT_NINF)     /*按默认产生式规约*/
     100         {
     101             if(yydefact[statenum] == 0)
     102             {
     103                 printf("grammar error!
    ");
     104                 break;
     105             }
     106             else if(yydefact[statenum] == 1)
     107             {
     108                 printf("accept!
    ");
     109                 PrintSymTable(initst);
     110                 PrintFmla(fmlay,fmlap);
     111                 break;
     112             }
     113             else
     114             {
     115                 Reduction_Goto(yydefact[statenum]);
     116                 newflag = 1;
     117             }
     118         }
     119         else
     120         {
     121             index = yypact[statenum] + token->symbolnum;
     122             if((index >= LCHECK) || (yycheck[index] != token->symbolnum)) /*按默认产生式规约*/
     123             {
     124                 if(yydefact[statenum] == 0)
     125                 {
     126                     printf("grammar error!
    ");
     127                     break;
     128                 }
     129                 else if(yydefact[statenum] == 1)
     130                 {
     131                     printf("accept!
    ");
     132                     PrintSymTable(initst);
     133                     PrintFmla(fmlay,fmlap);
     134                     break;
     135                 }
     136                 else
     137                 {
     138                     Reduction_Goto(yydefact[statenum]);
     139                     newflag = 1;
     140                 }
     141             }
     142             else
     143             {
     144                 if(yytable[index] == YYTABLE_NINF)
     145                 {
     146                     printf("grammar error
    ");
     147                     break;
     148                 }
     149                 else if(yytable[index] == 0)
     150                 {
     151                     if(yydefact[statenum] == 0)
     152                     {
     153                         printf("grammar error!
    ");
     154                         break;
     155                     }
     156                     else if(yydefact[statenum] == 1)
     157                     {
     158                         printf("accept!
    ");
     159                         PrintSymTable(initst);
     160                         PrintFmla(fmlay,fmlap);
     161                         break;
     162                     }
     163                     else
     164                     {
     165                         Reduction_Goto(yydefact[statenum]);
     166                         newflag = 1;
     167                     }
     168                 }
     169                 else if(yytable[index] < 0)
     170                 {
     171                     Reduction_Goto(-yytable[index]);    /*按产生式规约,变负*/
     172                     newflag = 1;
     173                 }
     174                 else
     175                 {
     176                     push(state,yytable[index]);
     177                     pushsym(symbol,token);
     178                     newflag = 0;
     179                 }
     180             }
     181         }
     182     }
     183 
     184 
     185     clearFmlay(fmlay,fmlap);
     186     clearList(templink);
     187     fclose(fp);
     188     return 0;
     189 }
     190 
     191 
     192 void Reduction_Goto(int k)      /*按第k个产生式规约,k为正数,output文件编号加1才是k*/
     193 {
     194     int len = yyr2[k];
     195     int array[len];         /*array放产生式的右部各个元素*/
     196     int i,index;
     197     int symbolnum,statenum;
     198     Token t = (Token)malloc(sizeof(To));    //申请的空间不会被释放
     199     t->addr = NULL;
     200     t->offset = NULL;
     201     t->truelist = NULL;
     202     t->falselist = NULL;
     203     t->nextlist = NULL;
     204 
     205     symtbl *st;     /*翻译用的变量*/
     206     char id100[64];    //case 100
     207     char type47[64];
     208 
     209     int m;
     210     Identifier *temp = NULL;
     211 
     212     switch(k)
     213     {
     214     case 3:         //program: program_heading semicolon muldec_m1 block DOT
     215         {
     216             addwidth(tblptr->elem[tblptr->top],offset->elem[offset->top]);
     217             pops(tblptr);
     218             pop(offset);
     219             break;
     220         }
     221     case 4:         //muldec_m1: /* empty */
     222         {
     223             st = mktable(NULL);
     224             initst = st;
     225             pushs(tblptr,st);
     226             push(offset,0);
     227             break;
     228         }
     229     case 6:     //identifier_list: identifier_list comma identifier
     230         {
     231             Enqueue(idlist,symbol->elem[symbol->top]->name);
     232             break;
     233         }
     234     case 7:     //identifier_list:identifier
     235         {
     236             Enqueue(idlist,symbol->elem[symbol->top]->name);
     237             break;
     238         }
     239     case 9:    //constant: non_string
     240         {
     241             t->i = symbol->elem[symbol->top]->i;
     242             break;
     243         }
     244     case 10:    //constant: sign non_string
     245         {
     246             if(symbol->elem[symbol->top+1]->type == 0)
     247             {
     248                 t->i = symbol->elem[symbol->top]->i;
     249             }
     250             else    //==1
     251             {
     252                 t->i = -symbol->elem[symbol->top]->i;
     253             }
     254             break;
     255         }
     256     case 11:    //sign: PLUS
     257         {
     258             t->type = 0;
     259             break;
     260         }
     261     case 12:    //sign:MINUS
     262         {
     263             t->type = 1;
     264             break;
     265         }
     266     case 13:   // non_string: DIGSEQ
     267         {
     268             t->i = symbol->elem[symbol->top]->i;
     269             break;
     270         }
     271     case 14:        //type_denoter: identifier
     272         {
     273             strcpy(type47,symbol->elem[symbol->top]->name);
     274             if(strcmp(type47,"integer") == 0)
     275             {
     276                 t->type = 0;
     277                 t->i = 4;
     278             }
     279             else if(strcmp(type47,"real") == 0)
     280             {
     281                 t->type = 1;
     282                 t->i = 8;
     283             }
     284             break;
     285         }
     286     case 15:    //type_denoter:  new_type
     287         {
     288             t->type = symbol->elem[symbol->top]->type;
     289             t->i = symbol->elem[symbol->top]->i;
     290             break;
     291         }
     292     case 16:        //new_type:new_structured_type
     293         {
     294             t->type = symbol->elem[symbol->top]->type;
     295             t->i = symbol->elem[symbol->top]->i;
     296             break;
     297         }
     298     case 17:        //new_ordinal_type: subrange_type
     299         {
     300             t->i = symbol->elem[symbol->top]->i;
     301             t->type = symbol->elem[symbol->top]->type;
     302             break;
     303         }
     304     case 18:    //subrange_type: constant DOTDOT constant
     305         {
     306             t->i = symbol->elem[symbol->top]->i;
     307             t->type = symbol->elem[symbol->top+2]->i;
     308             break;
     309         }
     310     case 19:    //new_structured_type: structured_type
     311         {
     312             t->type = symbol->elem[symbol->top]->type;
     313             t->i = symbol->elem[symbol->top]->i;
     314             break;
     315         }
     316     case 20:    //structured_type: array_type
     317         {
     318             t->type = symbol->elem[symbol->top]->type;
     319             t->i = symbol->elem[symbol->top]->i;
     320             break;
     321         }
     322     case 21:        //array_type: ARRAY LBRAC index_list RBRAC OF component_type
     323         {
     324             t->type = symbol->elem[symbol->top]->type + 2;
     325             t->i = symbol->elem[symbol->top+3]->i * 4 * (symbol->elem[symbol->top]->type+1);
     326             break;
     327         }
     328     case 22:    //index_list: index_list comma index_type
     329         {
     330             t->i = symbol->elem[symbol->top+2]->i * (symbol->elem[symbol->top]->i - symbol->elem[symbol->top]->type+1);
     331             IntEnqueue(indexlist,symbol->elem[symbol->top]->type);
     332             IntEnqueue(indexlist,symbol->elem[symbol->top]->i);
     333             break;
     334         }
     335     case 23:    //index_list: index_type
     336         {
     337             t->i = symbol->elem[symbol->top]->i - symbol->elem[symbol->top]->type+1;
     338             IntEnqueue(indexlist,symbol->elem[symbol->top]->type);
     339             IntEnqueue(indexlist,symbol->elem[symbol->top]->i);
     340             break;
     341         }
     342     case 24:    //index_type: ordinal_type
     343         {
     344             t->i = symbol->elem[symbol->top]->i;
     345             t->type = symbol->elem[symbol->top]->type;
     346             break;
     347         }
     348     case 25:    //ordinal_type: new_ordinal_type
     349         {
     350             t->i = symbol->elem[symbol->top]->i;
     351             t->type = symbol->elem[symbol->top]->type;
     352             break;
     353         }
     354     case 26:    //component_type: type_denoter
     355         {
     356             t->type = symbol->elem[symbol->top]->type;
     357             break;
     358         }
     359     case 31:        //variable_declaration: identifier_list COLON type_denoter
     360         {
     361             while(Dequeue(idlist,id100) == 1)
     362             {
     363                 enter(tblptr->elem[tblptr->top],id100,symbol->elem[symbol->top]->type,offset->elem[offset->top],indexlist);
     364                 offset->elem[offset->top] = offset->elem[offset->top]+symbol->elem[symbol->top]->i;
     365             }
     366             break;
     367         }
     368     case 37:       //procedure_declaration:procedure_heading semicolon muldec_m2 procedure_block
     369         {
     370             st = tblptr->elem[tblptr->top];
     371             addwidth(st,offset->elem[offset->top]);
     372             pops(tblptr);
     373             pop(offset);
     374             enterproc(tblptr->elem[tblptr->top],symbol->elem[symbol->top+3]->name,st);    //需要词法分析器的第二个值id.name!!!!!
     375             break;
     376         }
     377     case 38:       //muldec_m2
     378         {
     379             st = mktable(tblptr->elem[tblptr->top]);
     380             pushs(tblptr,st);
     381             push(offset,0);
     382             break;
     383         }
     384     case 39:       //procedure_heading: procedure_identification
     385         {
     386             strcpy(t->name,symbol->elem[symbol->top]->name);
     387             break;
     388         }
     389     case 40:       //procedure_heading:procedure_identification formal_parameter_list
     390         {
     391             strcpy(t->name,symbol->elem[symbol->top+1]->name);
     392             break;
     393         }
     394     case 46:       //value_parameter_specification: identifier_list COLON identifier//just for correcting
     395         {
     396             MakeNULLQueue(idlist);
     397             break;
     398         }
     399     case 47:       //variable_parameter_specification: VAR identifier_list COLON identifier//just for correcting
     400         {
     401             MakeNULLQueue(idlist);
     402             break;
     403         }
     404     case 48:       //procedure_identification: PROCEDURE identifier
     405         {
     406             strcpy(t->name,symbol->elem[symbol->top]->name);
     407             break;
     408         }
     409 
     410 
     411 
     412     case 51:       //compound_statement: PBEGIN statement_sequence END
     413         {
     414             t->nextlist = symbol->elem[symbol->top+1]->nextlist;
     415             break;
     416         }
     417     case 52:       //statement_sequence: statement_sequence semicolon ctrl_m statement
     418         {
     419             backpatch(symbol->elem[symbol->top+3]->nextlist,symbol->elem[symbol->top+1]->quad);
     420             t->nextlist = symbol->elem[symbol->top]->nextlist;
     421             break;
     422         }
     423     case 53:       //statement_sequence: statement
     424         {
     425             t->nextlist = symbol->elem[symbol->top]->nextlist;
     426             break;
     427         }
     428     case 54:       //statement: open_statement
     429         {
     430             t->nextlist = symbol->elem[symbol->top]->nextlist;
     431             break;
     432         }
     433     case 55:       //statement: closed_statement
     434         {
     435             t->nextlist = symbol->elem[symbol->top]->nextlist;
     436             break;
     437         }
     438     case 56:       //open_statement: non_labeled_open_statement
     439         {
     440             t->nextlist = symbol->elem[symbol->top]->nextlist;
     441             break;
     442         }
     443     case 57:       //closed_statement: non_labeled_closed_statement
     444         {
     445             t->nextlist = symbol->elem[symbol->top]->nextlist;
     446             break;
     447         }
     448     case 60:       //non_labeled_closed_statement:compound_statement
     449         {
     450             t->nextlist = symbol->elem[symbol->top]->nextlist;
     451             break;
     452         }
     453     case 61:       //non_labeled_closed_statement: repeat_statement
     454         {
     455             t->nextlist = symbol->elem[symbol->top]->nextlist;
     456             break;
     457         }
     458     case 62:       //non_labeled_closed_statement:closed_if_statement
     459         {
     460             t->nextlist = symbol->elem[symbol->top]->nextlist;
     461             break;
     462         }
     463     case 63:       //non_labeled_closed_statement:closed_while_statement
     464         {
     465             t->nextlist = symbol->elem[symbol->top]->nextlist;
     466             break;
     467         }
     468     case 64:       //non_labeled_closed_statement: closed_for_statement
     469         {
     470             t->nextlist = symbol->elem[symbol->top]->nextlist;
     471             break;
     472         }
     473     case 66:       //non_labeled_open_statement:open_if_statement
     474         {
     475             t->nextlist = symbol->elem[symbol->top]->nextlist;
     476             break;
     477         }
     478     case 67:       //non_labeled_open_statement:open_while_statement
     479         {
     480             t->nextlist = symbol->elem[symbol->top]->nextlist;
     481             break;
     482         }
     483     case 68:       //non_labeled_open_statement: open_for_statement
     484         {
     485             t->nextlist = symbol->elem[symbol->top]->nextlist;
     486             break;
     487         }
     488 
     489     case 69:   //repeat_statement: REPEAT ctrl_m statement_sequence UNTIL repeat_n boolean_expression
     490         {
     491             backpatch(symbol->elem[symbol->top+3]->nextlist,symbol->elem[symbol->top+1]->quad);
     492             backpatch(symbol->elem[symbol->top]->falselist,symbol->elem[symbol->top+4]->quad);
     493             t->nextlist = symbol->elem[symbol->top]->truelist;
     494             break;
     495         }
     496 
     497     case 70:          //open_while_statement: WHILE ctrl_m boolean_expression DO ctrl_m open_statement
     498         {
     499             backpatch(symbol->elem[symbol->top]->nextlist,symbol->elem[symbol->top+4]->quad);
     500             backpatch(symbol->elem[symbol->top+3]->truelist,symbol->elem[symbol->top+1]->quad);
     501             t->nextlist = symbol->elem[symbol->top+3]->falselist;
     502             sprintf(id100,"%d",symbol->elem[symbol->top+4]->quad);
     503             gencode(GOTO,"-","-",id100);
     504             break;
     505         }
     506     case 71:       //closed_while_statement: WHILE ctrl_m boolean_expression DO ctrl_m closed_statement
     507         {
     508             backpatch(symbol->elem[symbol->top]->nextlist,symbol->elem[symbol->top+4]->quad);
     509             backpatch(symbol->elem[symbol->top+3]->truelist,symbol->elem[symbol->top+1]->quad);
     510             t->nextlist = symbol->elem[symbol->top+3]->falselist;
     511             sprintf(id100,"%d",symbol->elem[symbol->top+4]->quad);
     512             gencode(GOTO,"-","-",id100);
     513             break;
     514         }
     515     case 72:       //open_for_statement: FOR control_variable ASSIGNMENT initial_value direction final_value DO for_m open_statement
     516         {
     517             backpatch(symbol->elem[symbol->top]->nextlist,symbol->elem[symbol->top+1]->i);
     518             sprintf(id100,"%d",symbol->elem[symbol->top+1]->i);
     519             gencode(GOTO,"-","-",id100);
     520             t->nextlist = symbol->elem[symbol->top+1]->nextlist;
     521             break;
     522         }
     523     case 73:       //closed_for_statement: FOR control_variable ASSIGNMENT initial_value direction final_value DO for_m closed_statement
     524         {
     525             backpatch(symbol->elem[symbol->top]->nextlist,symbol->elem[symbol->top+1]->i);
     526             sprintf(id100,"%d",symbol->elem[symbol->top+1]->i);
     527             gencode(GOTO,"-","-",id100);
     528             t->nextlist = symbol->elem[symbol->top+1]->nextlist;
     529             break;
     530         }
     531     case 74:       //open_if_statement: IF boolean_expression THEN ctrl_m statement
     532         {
     533             backpatch(symbol->elem[symbol->top+3]->truelist,symbol->elem[symbol->top+1]->quad);
     534             mergelist(symbol->elem[symbol->top+3]->falselist,symbol->elem[symbol->top]->nextlist);
     535             t->nextlist = symbol->elem[symbol->top+3]->falselist;
     536             break;
     537         }
     538     case 75:   //open_if_statement: IF boolean_expression THEN ctrl_m closed_statement ctrl_n ELSE ctrl_m open_statement
     539         {
     540             backpatch(symbol->elem[symbol->top+7]->truelist,symbol->elem[symbol->top+5]->quad);
     541             backpatch(symbol->elem[symbol->top+7]->falselist,symbol->elem[symbol->top+1]->quad);
     542             mergelist(symbol->elem[symbol->top+3]->nextlist,symbol->elem[symbol->top]->nextlist);
     543             mergelist(symbol->elem[symbol->top+3]->nextlist,symbol->elem[symbol->top+4]->nextlist);
     544             t->nextlist = symbol->elem[symbol->top+3]->nextlist;
     545             break;
     546         }
     547     case 76:   //closed_if_statement: IF boolean_expression THEN ctrl_m closed_statement ctrl_n ELSE ctrl_m closed_statement
     548         {
     549             backpatch(symbol->elem[symbol->top+7]->truelist,symbol->elem[symbol->top+5]->quad);
     550             backpatch(symbol->elem[symbol->top+7]->falselist,symbol->elem[symbol->top+1]->quad);
     551             mergelist(symbol->elem[symbol->top+3]->nextlist,symbol->elem[symbol->top]->nextlist);
     552             mergelist(symbol->elem[symbol->top+3]->nextlist,symbol->elem[symbol->top+4]->nextlist);
     553             t->nextlist = symbol->elem[symbol->top+3]->nextlist;
     554             break;
     555         }
     556 
     557 
     558 
     559     case 77:           //assignment_statement: variable_access ASSIGNMENT expression
     560         {
     561             if(symbol->elem[symbol->top+2]->offset == NULL)
     562             {
     563                 gencode(ASSIGN,symbol->elem[symbol->top]->addr->name,"-",symbol->elem[symbol->top+2]->addr->name);
     564             }
     565             else
     566             {
     567                 gencode(OFFE,symbol->elem[symbol->top+2]->addr->name,symbol->elem[symbol->top+2]->offset->name,symbol->elem[symbol->top]->addr->name);
     568             }
     569             break;
     570         }
     571     case 78:               //variable_access: identifier
     572         {
     573             Identifier *idaddr = lookup(symbol->elem[symbol->top]->name,tblptr->elem[tblptr->top]);
     574             if(idaddr)
     575             {
     576                 t->addr = idaddr;
     577                 t->offset = NULL;
     578             }
     579             else
     580             {
     581                 printf("Variable %s wasn't defined in this procedure!
    ",symbol->elem[symbol->top]->name);
     582                 exit(1);
     583             }
     584             break;
     585         }
     586     case 79:           //variable_access: indexed_variable
     587         {
     588             t->addr = symbol->elem[symbol->top]->addr;
     589             t->offset = symbol->elem[symbol->top]->offset;
     590             break;
     591         }
     592     case 80:           //indexed_variable: index_expression_list RBRAC
     593         {
     594             t->addr = insertHeadList(&templink,&tempcount);
     595             t->offset = insertHeadList(&templink,&tempcount);
     596             itoa(*(symbol->elem[symbol->top+1]->offset->arrayex),id100,10);
     597             gencode(ASSIGN,id100,"-",t->addr->name);
     598             itoa(4*(symbol->elem[symbol->top+1]->offset->type-1),id100,10);
     599             gencode(MUL,symbol->elem[symbol->top+1]->addr->name,id100,t->offset->name);
     600             break;
     601         }
     602     case 81:           //index_expression_list: index_expression_list comma index_expression
     603         {
     604             temp = insertHeadList(&templink,&tempcount);
     605             m = symbol->elem[symbol->top+2]->i + 1;
     606             itoa(*(symbol->elem[symbol->top+2]->offset->arrayex+3+2*(m-1)),id100,10);
     607             gencode(MUL,symbol->elem[symbol->top+2]->addr->name,id100,temp->name);
     608             gencode(PLUS,temp->name,symbol->elem[symbol->top]->addr->name,temp->name);
     609             t->offset = symbol->elem[symbol->top+2]->offset;
     610             t->addr = temp;
     611             t->i = m;
     612             break;
     613         }
     614     case 82:          //index_expression_list: identifier LBRAC index_expression
     615         {
     616             Identifier *idaddr = lookup(symbol->elem[symbol->top+2]->name,tblptr->elem[tblptr->top]);
     617             if(idaddr == NULL)
     618             {
     619                 exit(1);
     620             }
     621             t->offset = idaddr;
     622             t->addr = symbol->elem[symbol->top]->addr;
     623             t->i = 1;
     624             break;
     625         }
     626     case 83:       //index_expression: expression
     627         {
     628             t->addr = symbol->elem[symbol->top]->addr;
     629             break;
     630         }
     631 
     632 
     633     case 84:       //procedure_statement: identifier params
     634         {
     635             m = 0;
     636             while(Dequeue(actualpalist,id100))
     637             {
     638                 m++;
     639                 gencode(PARAM,"-","-",id100);
     640             }
     641             sprintf(id100,"%d",m);
     642             if(strcmp(symbol->elem[symbol->top+1]->name,"read") == 0||strcmp(symbol->elem[symbol->top+1]->name,"readln") == 0)
     643             {
     644                 gencode(CALL,"SYSIN",id100,"-");
     645             }
     646             else if(strcmp(symbol->elem[symbol->top+1]->name,"write") == 0)     //1型
     647             {
     648                 gencode(CALL,"SYSOUT",id100,"1");
     649             }
     650             else if(strcmp(symbol->elem[symbol->top+1]->name,"writeln") == 0)   //2型
     651             {
     652                 gencode(CALL,"SYSOUT",id100,"2");
     653             }
     654             else
     655             {
     656                 gencode(CALL,symbol->elem[symbol->top+1]->name,id100,"-");
     657             }
     658             break;
     659         }
     660     case 85:       //procedure_statement: identifier
     661         {
     662             gencode(CALL,symbol->elem[symbol->top]->name,"0","-");
     663             break;
     664         }
     665     case 87:       //actual_parameter_list: actual_parameter_list comma actual_parameter
     666         {
     667             Enqueue(actualpalist,symbol->elem[symbol->top]->addr->name);
     668             break;
     669         }
     670     case 88:       //actual_parameter_list: actual_parameter
     671         {
     672             //MakeNULLQueue(actualpalist);
     673             Enqueue(actualpalist,symbol->elem[symbol->top]->addr->name);
     674             break;
     675         }
     676     case 89:       //actual_parameter: expression
     677         {
     678             t->addr = symbol->elem[symbol->top]->addr;
     679             break;
     680         }
     681 
     682 
     683     case 90:       //control_variable: identifier
     684         {
     685             strcpy(t->name,symbol->elem[symbol->top]->name);
     686             break;
     687         }
     688     case 91:       //initial_value: expression
     689         {
     690             t->addr = symbol->elem[symbol->top]->addr;
     691             break;
     692         }
     693     case 92:       //direction: TO
     694         {
     695             t->type = 0;
     696             break;
     697         }
     698     case 93:       //direction: DOWNTO
     699         {
     700             t->type = 1;
     701             break;
     702         }
     703     case 94:       //final_value: expression
     704         {
     705             t->addr = symbol->elem[symbol->top]->addr;
     706             break;
     707         }
     708 
     709 
     710     case 95:       //boolean_expression: expression
     711         {
     712             t->truelist = symbol->elem[symbol->top]->truelist;
     713             t->falselist = symbol->elem[symbol->top]->falselist;
     714             break;
     715         }
     716     case 96:       //expression: simple_expression
     717         {
     718             t->addr = symbol->elem[symbol->top]->addr;
     719             t->truelist = symbol->elem[symbol->top]->truelist;
     720             t->falselist = symbol->elem[symbol->top]->falselist;
     721             break;
     722         }
     723     case 97:       //expression: simple_expression relop simple_expression
     724         {
     725             t->truelist = makelist(fmlap);
     726             t->falselist = makelist(fmlap+1);
     727             switch(symbol->elem[symbol->top+1]->type)
     728             {
     729             case 0:     //EQUAL
     730                 {
     731                     gencode(EQ,symbol->elem[symbol->top+2]->addr->name,symbol->elem[symbol->top]->addr->name,"-");
     732                     break;
     733                 }
     734             case 1:     //NOTEQUAL
     735                 {
     736                     gencode(NE,symbol->elem[symbol->top+2]->addr->name,symbol->elem[symbol->top]->addr->name,"-");
     737                     break;
     738                 }
     739             case 2:     //LT
     740                 {
     741                     gencode(LT,symbol->elem[symbol->top+2]->addr->name,symbol->elem[symbol->top]->addr->name,"-");
     742                     break;
     743                 }
     744             case 3:     //GT
     745                 {
     746                     gencode(GT,symbol->elem[symbol->top+2]->addr->name,symbol->elem[symbol->top]->addr->name,"-");
     747                     break;
     748                 }
     749             case 4:     //LE
     750                 {
     751                     gencode(LE,symbol->elem[symbol->top+2]->addr->name,symbol->elem[symbol->top]->addr->name,"-");
     752                     break;
     753                 }
     754             case 5:     //GE
     755                 {
     756                     gencode(GE,symbol->elem[symbol->top+2]->addr->name,symbol->elem[symbol->top]->addr->name,"-");
     757                     break;
     758                 }
     759             }
     760             gencode(GOTO,"-","-","-");
     761             break;
     762         }
     763     case 98:       //simple_expression: term
     764         {
     765             t->addr = symbol->elem[symbol->top]->addr;
     766             t->truelist = symbol->elem[symbol->top]->truelist;
     767             t->falselist = symbol->elem[symbol->top]->falselist;
     768             break;
     769         }
     770     case 99:          //simple_expression: simple_expression addop boolean_m term
     771         {
     772             t->addr = insertHeadList(&templink,&tempcount);
     773             if(symbol->elem[symbol->top+2]->type == 0)          //+
     774             {
     775                 gencode(PLUS,symbol->elem[symbol->top+3]->addr->name,symbol->elem[symbol->top]->addr->name,t->addr->name);
     776             }
     777             if(symbol->elem[symbol->top+2]->type == 1)          //-
     778             {
     779                 gencode(SUB,symbol->elem[symbol->top+3]->addr->name,symbol->elem[symbol->top]->addr->name,t->addr->name);
     780             }
     781             if(symbol->elem[symbol->top+2]->type == 2)          //OR
     782             {
     783                 backpatch(symbol->elem[symbol->top+3]->falselist,symbol->elem[symbol->top+1]->quad);
     784                 clear_label_list(symbol->elem[symbol->top+3]->falselist);
     785                 mergelist(symbol->elem[symbol->top+3]->truelist,symbol->elem[symbol->top]->truelist);
     786                 t->truelist = symbol->elem[symbol->top+3]->truelist;
     787                 t->falselist = symbol->elem[symbol->top]->falselist;
     788             }
     789             break;
     790         }
     791     case 100:       //term: factor
     792         {
     793             t->addr = symbol->elem[symbol->top]->addr;
     794             t->truelist = symbol->elem[symbol->top]->truelist;
     795             t->falselist = symbol->elem[symbol->top]->falselist;
     796             break;
     797         }
     798     case 101:       //term: term mulop boolean_m factor //STAR SLASH DIV MOD AND
     799         {
     800             t->addr = insertHeadList(&templink,&tempcount);
     801             switch(symbol->elem[symbol->top+2]->s[0])
     802             {
     803             case '*':
     804                 {
     805                     gencode(MUL,symbol->elem[symbol->top+3]->addr->name,symbol->elem[symbol->top]->addr->name,t->addr->name);
     806                     break;
     807                 }
     808             case '/':
     809                 {
     810                     gencode(RDIV,symbol->elem[symbol->top+3]->addr->name,symbol->elem[symbol->top]->addr->name,t->addr->name);
     811                     break;
     812                 }
     813             case '\':
     814                 {
     815                     gencode(DIV,symbol->elem[symbol->top+3]->addr->name,symbol->elem[symbol->top]->addr->name,t->addr->name);
     816                     break;
     817                 }
     818             case '%':
     819                 {
     820                     gencode(MOD,symbol->elem[symbol->top+3]->addr->name,symbol->elem[symbol->top]->addr->name,t->addr->name);
     821                     break;
     822                 }
     823             case '&':
     824                 {
     825                     backpatch(symbol->elem[symbol->top+3]->truelist,symbol->elem[symbol->top+1]->quad);
     826                     clear_label_list(symbol->elem[symbol->top+3]->truelist);
     827                     t->truelist = symbol->elem[symbol->top]->truelist;
     828                     mergelist(symbol->elem[symbol->top+3]->falselist,symbol->elem[symbol->top]->falselist);
     829                     t->falselist = symbol->elem[symbol->top+3]->falselist;
     830                     break;
     831                 }
     832             }
     833             break;
     834         }
     835     case 102:       //factor: sign factor
     836         {
     837             t->addr = insertHeadList(&templink,&tempcount);
     838             if(symbol->elem[symbol->top+1]->type == 0)
     839             {
     840                 gencode(ASSIGN,symbol->elem[symbol->top]->addr->name,"-",t->addr->name);
     841             }
     842             if(symbol->elem[symbol->top+1]->type == 1)
     843             {
     844                 gencode(MINUS,symbol->elem[symbol->top]->addr->name,"-",t->addr->name);
     845             }
     846             break;
     847         }
     848     case 103:       //factor: exponentiation
     849         {
     850             t->addr = symbol->elem[symbol->top]->addr;
     851             t->truelist = symbol->elem[symbol->top]->truelist;
     852             t->falselist = symbol->elem[symbol->top]->falselist;
     853             break;
     854         }
     855     case 104:       //exponentiation: primary
     856         {
     857             t->addr = symbol->elem[symbol->top]->addr;
     858             t->truelist = symbol->elem[symbol->top]->truelist;
     859             t->falselist = symbol->elem[symbol->top]->falselist;
     860             break;
     861         }
     862     case 105:       //primary: variable_access
     863         {
     864             if(symbol->elem[symbol->top]->offset == NULL)       //简单变量
     865             {
     866                 t->addr = symbol->elem[symbol->top]->addr;
     867             }
     868             else
     869             {
     870                 t->addr = insertHeadList(&templink,&tempcount);
     871                 gencode(EOFF,symbol->elem[symbol->top]->addr->name,symbol->elem[symbol->top]->offset->name,t->addr->name);
     872             }
     873             break;
     874         }
     875     case 106:       //primary: unsigned_constant
     876         {
     877             t->addr = insertHeadList(&templink,&tempcount);
     878             if(symbol->elem[symbol->top]->type == 0)            //integer
     879             {
     880                 itoa(symbol->elem[symbol->top]->i,id100,10);
     881                 gencode(ASSIGN,id100,"-",t->addr->name);
     882             }
     883             if(symbol->elem[symbol->top]->type == 1)            //real
     884             {
     885                 sprintf(id100,"%f",symbol->elem[symbol->top]->f);
     886                 gencode(ASSIGN,id100,"-",t->addr->name);
     887             }
     888             if(symbol->elem[symbol->top]->type == 2)        //CHARACTER_STRING
     889             {
     890                 gencode(ASSIGN,symbol->elem[symbol->top]->s,"-",t->addr->name);
     891             }
     892             break;
     893         }
     894     case 107:       //primary: LPAREN expression RPAREN
     895         {
     896             t->addr = symbol->elem[symbol->top+1]->addr;
     897             t->truelist = symbol->elem[symbol->top+1]->truelist;
     898             t->falselist = symbol->elem[symbol->top+1]->falselist;
     899             break;
     900         }
     901     case 108:       //primary: NOT primary
     902         {
     903             t->truelist = symbol->elem[symbol->top]->falselist;
     904             t->falselist = symbol->elem[symbol->top]->truelist;
     905             break;
     906         }
     907 
     908 
     909     case 109:       //unsigned_constant: unsigned_number
     910         {
     911             if(symbol->elem[symbol->top]->type == 0)
     912             {
     913                 t->type = 0;
     914                 t->i = symbol->elem[symbol->top]->i;
     915             }
     916             if(symbol->elem[symbol->top]->type == 1)
     917             {
     918                 t->type = 1;
     919                 t->f = symbol->elem[symbol->top]->f;
     920             }
     921             break;
     922         }
     923     case 110:       //unsigned_constant: CHARACTER_STRING
     924         {
     925             t->type = 2;
     926             strcpy(t->s,symbol->elem[symbol->top]->s);
     927             break;
     928         }
     929     case 111:       //unsigned_number: unsigned_integer
     930         {
     931             t->type = 0;
     932             t->i = symbol->elem[symbol->top]->i;
     933             break;
     934         }
     935     case 112:       //unsigned_number: unsigned_real
     936         {
     937             t->type = 1;
     938             t->f = symbol->elem[symbol->top]->f;
     939             break;
     940         }
     941     case 113:       //unsigned_integer: DIGSEQ
     942         {
     943             t->i = symbol->elem[symbol->top]->i;
     944             break;
     945         }
     946     case 114:       //unsigned_real: REALNUMBER
     947         {
     948             t->f = symbol->elem[symbol->top]->f;
     949             break;
     950         }
     951 
     952     case 115:       //addop: PLUS
     953         {
     954             t->type = 0;
     955             break;
     956         }
     957     case 116:       //addop: MINUS
     958         {
     959             t->type = 1;
     960             break;
     961         }
     962     case 117:       //addop: OR
     963         {
     964             t->type = 2;
     965             break;
     966         }
     967     case 118:       //mulop: STAR
     968         {
     969             t->s[0] = '*';
     970             break;
     971         }
     972     case 119:       //mulop: SLASH
     973         {
     974             t->s[0] = '/';
     975             break;
     976         }
     977     case 120:       //mulop: DIV
     978         {
     979             t->s[0] = '\';
     980             break;
     981         }
     982     case 121:       //mulop: MOD
     983         {
     984             t->s[0] = '%';
     985             break;
     986         }
     987     case 122:       //mulop: AND
     988         {
     989             t->s[0] = '&';
     990             break;
     991         }
     992 
     993     case 123:       //relop: EQUAL
     994         {
     995             t->type = 0;
     996             break;
     997         }
     998     case 124:       //relop: NOTEQUAL
     999         {
    1000             t->type = 1;
    1001             break;
    1002         }
    1003     case 125:       //relop: LT
    1004         {
    1005             t->type = 2;
    1006             break;
    1007         }
    1008     case 126:       //relop: GT
    1009         {
    1010             t->type = 3;
    1011             break;
    1012         }
    1013     case 127:       //relop:LE
    1014         {
    1015             t->type = 4;
    1016             break;
    1017         }
    1018     case 128:       //relop: GE
    1019         {
    1020             t->type = 5;
    1021             break;
    1022         }
    1023 
    1024     case 129:       //identifier: IDENTIFIER
    1025         {
    1026             strcpy(t->name,symbol->elem[symbol->top]->name);
    1027             break;
    1028         }
    1029 
    1030     case 132:       //boolean_m: /* empty */
    1031         {
    1032             t->quad = fmlap;
    1033             break;
    1034         }
    1035     case 133:       //ctrl_m: /* empty */
    1036         {
    1037             t->quad = fmlap;
    1038             break;
    1039         }
    1040     case 134:       //ctrl_n: /* empty */
    1041         {
    1042             t->nextlist = makelist(fmlap);
    1043             gencode(GOTO,"-","-","-");
    1044             break;
    1045         }
    1046     case 135:       //repeat_n: /* empty */
    1047         {
    1048             t->quad = fmlap;
    1049             break;
    1050         }
    1051     case 136:       //for_m: /* empty */ stack:FOR control_variable ASSIGNMENT initial_value direction final_value DO ..
    1052         {
    1053             strcpy(t->name,symbol->elem[symbol->top+5]->name);      //id
    1054             gencode(ASSIGN,symbol->elem[symbol->top+3]->addr->name,"-",t->name);
    1055             temp = insertHeadList(&templink,&tempcount);            //final_value
    1056             gencode(ASSIGN,symbol->elem[symbol->top+1]->addr->name,"-",temp->name);
    1057             m = fmlap;
    1058             sprintf(id100,"%d",m+2);
    1059             gencode(GOTO,"-","-",id100);
    1060             t->i = m+1;
    1061 
    1062             if(symbol->elem[symbol->top+2]->type == 0)        //to
    1063             {
    1064                 gencode(PLUS,t->name,"1",t->name);
    1065                 gencode(GT,t->name,temp->name,"-");
    1066             }
    1067             else if(symbol->elem[symbol->top+2]->type == 1)     //downto
    1068             {
    1069                 gencode(SUB,t->name,"1",t->name);
    1070                 gencode(LT,t->name,temp->name,"-");
    1071             }
    1072             t->nextlist = makelist(fmlap-1);
    1073             break;
    1074         }
    1075     }
    1076 
    1077 
    1078     for(i = 0;i < len;i++)
    1079     {
    1080         pop(state);
    1081     }
    1082     for(i = 0;i < len;i++)
    1083     {
    1084         array[i] = popsym(symbol);
    1085     }
    1086     t->symbolnum = yyr1[k];
    1087     pushsym(symbol,t);
    1088 
    1089     //printf("&&");
    1090     /*
    1091     printf("%s",yytname[yyr1[k]]);      //begin打印产生式
    1092     printf("%s","->");
    1093     for(i = len - 1 ;i >= 0;i--)
    1094     {
    1095         printf("%s ",yytname[array[i]]);
    1096     }
    1097     printf("
    ");                       ///end
    1098     */
    1099 
    1100     //printf("
    ");
    1101     //PrintStack(state);
    1102     //printf("%c",'&');
    1103     //PrintSymStack(symbol);
    1104 
    1105     symbolnum = symbol->elem[symbol->top]->symbolnum - TN;    /*执行goto动作*/
    1106     statenum = state->elem[state->top];
    1107 
    1108     if(yypgoto[symbolnum] == YYPACT_NINF)
    1109     {
    1110         push(state,yydefgoto[symbolnum]);
    1111     }
    1112     else
    1113     {
    1114         index = yypgoto[symbolnum] + statenum;
    1115         if((index >= LCHECK) || (yycheck[index] != statenum))
    1116         {
    1117             push(state,yydefgoto[symbolnum]);
    1118         }
    1119         else
    1120         {
    1121             push(state,yytable[index]);
    1122         }
    1123     }
    1124 }
    1125 
    1126 Token ReadToken()
    1127 {
    1128     char strLine[1024];
    1129     char n1[10];
    1130     char n2[1027];
    1131     int i=0,j=0;
    1132     int t1;
    1133     Token rt = (Token)malloc(sizeof(To));
    1134     rt->addr = NULL;
    1135     rt->offset = NULL;
    1136     rt->truelist = NULL;
    1137     rt->falselist = NULL;
    1138     rt->nextlist = NULL;
    1139 
    1140     if(feof(fp)||(NULL == fgets(strLine,1024,fp)))
    1141     {
    1142         rt->symbolnum = 0;
    1143         return rt;
    1144     }
    1145 
    1146     for(i=1;;i++)
    1147     {
    1148         if(strLine[i] == ',')
    1149         {
    1150             n1[i-1] = '';
    1151             t1 = atoi(n1);
    1152             break;
    1153         }
    1154         n1[i-1] = strLine[i];
    1155     }
    1156     rt->symbolnum = yytranslate[t1];
    1157     i++;
    1158 
    1159     switch(t1)
    1160     {
    1161     case 36:        //id
    1162         {
    1163             while(strLine[i] != ')')
    1164             {
    1165                 n2[j] = strLine[i];
    1166                 j++;
    1167                 i++;
    1168             }
    1169             n2[j] = '';
    1170             strcpy(rt->name,n2);
    1171             break;
    1172         }
    1173     case 37:        //int
    1174         {
    1175             while(strLine[i] != ')')
    1176             {
    1177                 n2[j] = strLine[i];
    1178                 j++;
    1179                 i++;
    1180             }
    1181             n2[j] = '';
    1182             rt->i = atoi(n2);
    1183             break;
    1184         }
    1185     case 38:        //float
    1186         {
    1187             while(strLine[i] != ')')
    1188             {
    1189                 n2[j] = strLine[i];
    1190                 j++;
    1191                 i++;
    1192             }
    1193             n2[j] = '';
    1194             rt->f = atof(n2);
    1195             break;
    1196         }
    1197     case 39:        //string
    1198         {
    1199             while(strLine[i] != ')')
    1200             {
    1201                 n2[j] = strLine[i];
    1202                 j++;
    1203                 i++;
    1204             }
    1205             n2[j] = '';
    1206             strcpy(rt->s,n2);
    1207             break;
    1208         }
    1209     }
    1210     return rt;
    1211 }
    1212 
    1213 
    1214 void gencode(int op,char *arg1,char *arg2,char* ret)
    1215 {
    1216     fmlay[fmlap] = (pFour)malloc(sizeof(FourElemFormula));
    1217     fmlay[fmlap]->op = op;
    1218     strcpy(fmlay[fmlap]->arg1,arg1);
    1219     strcpy(fmlay[fmlap]->arg2,arg2);
    1220     strcpy(fmlay[fmlap]->ret,ret);
    1221     fmlap++;
    1222 }
    1223 
    1224 void backpatch(LabelNode* lis,int labelnum)
    1225 {
    1226     LabelNode* t = lis;
    1227     char numstr[60];
    1228     sprintf(numstr,"%d",labelnum);
    1229 
    1230     while(t != NULL)
    1231     {
    1232         strcpy(fmlay[t->label]->ret,numstr);
    1233         t = t->next;
    1234     }
    1235 }
    analysis&generate

    一、声明语句

    声明变量类型可以为:整型integer(type=0)、实型real(type=1)、整型数组array[] of integer

    (type=2)、实型数组array[] of real(type=3)

    支持嵌套过程,支持多维数组

    基本思想为:需要三种数据结构:符号表(其结构见《符号表管理器》一节)、offset栈(整型)、tblptr栈(符号表指针型)。当遇到过程声明语句时,首先创建一张新的符号表,并在该符号表中为过程的名字创建相应的表项。新表中还有一个指针指向外围过程的符号表。同时初始化栈tblptr,将0压入offset栈中;当遇到一个过程声明语句时,执行的动作基本相同,还需要在外围过程的符号表中为过程创建一个新表项。当规约过程/进程语句结束后,将offset栈中的和填入tblptr中,弹出offset和tblptr中的一个元素;当遇到一条声明语句时,把对应的变量名和一些属性填入符号表中,增加offset栈顶的值。

    例如如下的声明语句产生的符号表为

    program TowersofHanoi;

    var

       numdiscs : integer;

       num : real;

    procedure DoTowers (NumDiscs, OrigPeg, NewPeg, TempPeg : integer);

    var

       a,b : real;

       A : array[1..10,2..6,3..5] of real;

       c : integer;

       B : array[-3..6,5..9,7..16] of integer;

       d : real;

    begin

       ……

    end;

    begin 

      ……

    end.

     

    此输出结果是为了方便观察符号表,实际的总体程序中这部分输出是不必要的

    对于普通变量来说,打印它的名字、偏移、类型;对于数组变量来说,打印它的名字、维数ndim、每一维的最小下标值和维长。

    二、赋值语句

    支持数组元素的赋值

    一维数组:addr(A[i])=(base-low1*w)+i*w=c+i*w,其中c是存放在符号表中数组元素的对应的表项中的

    二维数组:addr(A[i1,i2])= base-(low1* n2 -low2)*w +(i1 * n2 + i2)*w=c+(i1*n2+i2)*w

    其中c是存放在符号表中数组元素的对应的表项中的

    多维数组:情形与二维数组类似

    生成的中间代码形式为 语句标号:语句

    基本思想:赋值语句的翻译结果是产生对应的中间代码。语句的左部可以使普通变量,也可以是数组元素,语句的右部可以是表达式,也可以是普通变量或数组元素。对于普通变量的翻译来说相对比较简单;对于数组元素的翻译需要根据其基地址和offset产生相应的中间代码。

    例如对如下程序中的赋值语句产生的中间代码为

    program Fibonacci;

    var

       Fibonacci1, Fibonacci2 : integer;

       temp : integer;

       count : integer;

    procedure DoTowers;

    var

         M:integer;

         A : array[1..5, 1..10] of integer;

         B : real;

        

    begin

         M := 9;

        A[1,10] := M;

        B := M + A[1,10];

    end;

    begin

       count := 0;

       Fibonacci1 := 0;

          Fibonacci2 := 1;

           repeat

          write (Fibonacci2:7);

          temp := Fibonacci2;

          Fibonacci2 := Fibonacci1 + Fibonacci2;

          Fibonacci1 := temp;

          count := count + 1

       until count = 10;

       if not (temp = 10) or (temp * 2 > 70) then

       begin

       writeln('a is not less than 20' );

       writeln (',');

       end

    else

         begin

         writeln('a is not less than 20' );

         writeln('value of a is : ', count);

         end;

       writeln;

    end.

    中间代码imcode.txt:

     

    三、布尔表达式(采用回填式翻译)

    支持的运算符有:and/or/not/</>/<=/>=/!=/=

    例如以下的布尔表达式生成的中间代码为

       repeat

         …

       until count = 10;

       if (temp = 10) and not (temp * 2 > 70) then

         begin

            writeln (' a is not less than 20');

         end;

       writeln;

    中间代码

     

    四、 if/while/for/repeat(采用回填式翻译)

    ①if-then语句                                          if-then-else语句

    生成的代码结构为                                     生成的代码结构为

             

    ②while和for语句

    ④repeat语句

     

    中间代码生成具体情况详见code.txt生成的中间代码imcode.txt

    五、过程调用语句call id(E1, E2, …, En)

    生成的中间代码形式为

    param E1.addr

    param E2.addr

    ……

    param En.addr

    call id.addr, n

    六、输入输出语句

    是特殊的过程调用语句,与普通过程调用语句的区别在于需要调用系统的输入输出函数SYSIN和SYSOUT

    read/readln(En)生成的中间代码形式为

    param En

    call SYSIN,1

    write(E1, E2)生成的中间代码形式为

    param E1.addr

    param E2.addr

    call SYSOUT,2,1

    writeln (E1, E2)生成的中间代码形式为

    param E1.addr

    param E2.addr

    call SYSOUT,2,2

  • 相关阅读:
    CSS3阴影 box-shadow的使用和技巧总结
    css实现一行文字居中,多行文字左对齐
    让一个div里面的其它div或者标签内容居中
    巧用css内容生成
    Emmet-前端开发神器
    新手向:Vue 2.0 的建议学习顺序
    require() 源码解读
    Vue-webpack项目配置详解
    webpack---webpack构建vue多页面框架(一、工程布局)
    STS创建spring boot项目,pom.xml文件第一行报错
  • 原文地址:https://www.cnblogs.com/zhouliyan/p/5941756.html
Copyright © 2011-2022 走看看