編譯實踐

每次由不同組員編寫 未整合故無關聯
in.txt

program test (a,b);
begin 
    x:=19;
    y:=x+5*6;
    if x<y then y:=x
    else begin
        while x+y<x do y:=y+1; 
        z:=z*7
    end
end.

詞法分析 _by GaHingZ

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<list>
#include <math.h>
#include <windows.h>
#define BOOL int
#define TRUE 1
#define FALSE 0
#define MAXSIZE 50
#define MAXNUM 16777216
#include<set>
#include<string>
#include<fstream>
using namespace std;
#define ERROR_SYN -1
//#define KEY_SYN=1~6
#define FINISH_SYN 0//#
#define IDENTIFIER_SYN 10//標識符
int lineIndex=1;
int error_index=0;
string sign_type[4]={"保留字",//for if ..
"特殊符號",//+ ( / ..
"常量",//num
"標識符"//還應該細分 以及屬性(address) 先不考慮
};
string error_info[4]={
"標識符不能帶有符號",
"整數越界",
"標識符長度大於32",
"非法識別num"
};
list<string> type0,type1,type2,type3;
list<string>::iterator finditer;
char *object;
typedef char datatype;
typedef struct                              /*定義緩衝隊列*/

{

  datatype data[MAXSIZE*2];

  int front,rear;

}Queue;

void setnull(Queue *q)                      /*隊列初始化*/

{

  q->front = MAXSIZE*2 - 1;

  q->rear = MAXSIZE*2 - 1;

}

BOOL empty(Queue *q)                   /*判隊空*/

{

  if(q->front==q->rear)

       return TRUE;

  return FALSE;

}

BOOL full(Queue *q)                         /*判隊滿*/

{

  if(q->front == (q->rear+1) % (MAXSIZE*2))

       return TRUE;

  return FALSE;

}

int quantity(Queue *q)                      /*求隊列中元素個數*/

{

  int n;

  n = q->rear - q->front;

    if(n<0)

       n += MAXSIZE*2;

  return n;

}

datatype front(Queue *q)               /*取隊頭元素*/

{

  int n;

  if(empty(q))

       return 0;

  n = (q->front+1) % (MAXSIZE*2);

  return q->data[n];

}

BOOL enqueue(Queue *q,datatype x)      /*入隊*/

{

  if(full(q))

       return FALSE;

  q->rear = ++q->rear % (MAXSIZE*2);

  q->data[q->rear]=x;

  return TRUE;

}

datatype dequeue(Queue *q)                  /*出隊*/

{

  if(empty(q))

       return 0;

  q->front = ++q->front % (MAXSIZE*2);

  return q->data[q->front];

}

int lengtharray(char *a){
   return strlen(a);
}


char token[MAXSIZE];


char* rwtab[6]={"begin","if","then","while","do","end"};//定義關鍵字


int syn;//標識符數字


Queue prog;



BOOL letter(char &ch)                   /*判斷是否字母*/

{

    if(ch>='a'&&ch<='z' ){
        return TRUE;}
    else if(ch>='A'&&ch<='Z'){
        ch=ch+32;
    return TRUE;
    }//全部轉換成小寫

  return FALSE;

}

BOOL digit(char ch,char ch2)                         /*判斷是否36進制開頭*/

{

  if(ch =='0'&& (ch2 =='X' || ch2 == 'x'))

       return TRUE;

  return FALSE;
}
BOOL digit1(char ch)                         /*判斷是否10進制*/

{

  if(ch >='0'&& ch<= '9')

       return TRUE;

  return FALSE;
}
BOOL symbol(char ch){
    if((ch>=34&&ch<=36)||ch==39||ch==64||(ch>=44&&ch<46))return TRUE;
    else return FALSE;
}
BOOL isPoint(char ch){
    if(ch==46)return true;
    else return false;
}
BOOL isBottomLine(char ch){
    if(ch==95)return true;
    else return false;
}
//判斷整數字符
BOOL digitagain(char ch){
     if ((ch >= '0' && ch <= '9')||(ch>='a'&&ch<='z' ) ||(ch>='A'&&ch<='Z'))return TRUE;
     return FALSE;

}

int translate(char c){
   int p;
   if(c>='0'&&c<='9')p=c-'0';
   if(c>='a'&&c<='z')p=c-'a'+10;
   if(c>='A'&&c<='Z')p=c-'A'+10;
   return p ;
}
BOOL explain(char ch,char ch2){

    if(ch == '-' && ch2 == '-')
        return TRUE;
    return FALSE;

}



void scanner()                                /*掃描器*/

{

  int i;
  int num,num1;
  char ch;
  char ch2;

  for(i=0;i<50;i++){

      token[i]=0;}

  i=0;

  do                                        /*去除多餘空格、換行及製表符*/

  {
       ch=dequeue(&prog);
       if(ch=='\n'){
           lineIndex++;
       }
  }while(ch==' ' || ch=='\n' || ch=='\t');//讀到不是空格、換行及製表符

  ch2 =  prog.data[prog.front+1];


  if(letter(ch))                            /*識別標識符(編號10)*/

  {
       int flag = 0;//
       while(1)
       {
           token[i++]=ch;
           ch=front(&prog);
           if(letter(ch) || digitagain(ch)||isBottomLine(ch))
                dequeue(&prog);
           else if(symbol(ch)||isPoint(ch)){
               dequeue(&prog);
                flag=1;//非法變量
           }
           else break;
       }
       if(flag!=0)
       {
           syn=ERROR_SYN;error_index=0; return;
       }
       //標識符長度大於32報錯
       if(lengtharray(token)>32){syn=ERROR_SYN;error_index=2; return;}
       //標識符的有效長度爲8
       if(lengtharray(token)>7)token[8]='\0';
       token[i]='\0';
       syn=10;
       for(i=0;i<6;i++)
           if(!strcmp(token,rwtab[i]))
                syn=i+1;                    /*識別關鍵字(編號1到6)*/
  }

  else if(explain(ch,ch2)){                /*識別註釋*/
       prog.front=prog.front+1;     //移動到--後面
       while(1){
         ch = front(&prog);
         if(ch!='\n')dequeue(&prog);
         else {syn=-2;break;}           
      }
  }

  else if(digit(ch,ch2))                   /*識別無符號整數(編號11)*/
  {
      prog.front=prog.front+1;       //移動到0X後面
      int flag=0;
       while(1)
       {
           ch=front(&prog);

           if(digitagain(ch)){

               dequeue(&prog);
           }
           else{            
               break;
           }          
           token[i++]=ch;
       }
       //轉換成36進制數
       int j,k;
       k=0;num=0;
       for(j = i-1;j>=0;j--){     
          num+=translate(token[j])*(int)pow(36,k);
//        printf("%d\n" ,translate(token[j]));
               k++;
       }
       if (num > MAXNUM){
            token[0]='\0';
            syn=ERROR_SYN;error_index=1;
//         printf("error\n");
           //break;
       }
       else{
       //將十進制數輸入到文本
       int num_1;
       num_1 = num;
       int q;
       for (q=1;;q++){
           num/=10;
           if (num==0) break;
       }
       int w,e;
       e=q-1;
       for (w=0;w<q;w++){
            token[w] = (num_1/((int)pow(10,e))) +48;
             num_1 %= ((int)pow(10,e));
              e--;
       }      
       token[e]='\0';
       syn=11;
       }

  }
  else if(digit1(ch)){
       int flag = 0;
       int k=0;
       BOOL havaPoint = FALSE;
       while(1)
       {
           token[i++]=ch;
           ch=front(&prog);    
           if(digit1(ch))
           {
               k++;
               dequeue(&prog);
                //nothing
           }
           else if(symbol(ch)||letter(ch)||isBottomLine(ch)){
               dequeue(&prog);
                flag=1;//非法變量
           }
           else if(isPoint(ch)){
                dequeue(&prog);
                havaPoint=TRUE;
                break;
           }
           else break;
       }
       if(havaPoint==TRUE){
           while(1)
          {
               token[i++]=ch;
               ch=front(&prog);    
               if(digit1(ch))
              {
                   dequeue(&prog);
                   //nothing
              }
              else if(symbol(ch)||letter(ch)||isBottomLine(ch)||isPoint(ch)){
                   dequeue(&prog);
                    flag=1;//非法變量
              }
              else break;
           }
           if(flag==0)flag=2;
       }
       if(flag==1){
        syn=ERROR_SYN;error_index=3; return;
       }
       token[i]='\0';
         //轉換成10進制數
       int j;
       num1=0;
       k--;
       for(j = 0;j<=i-1;j++){
           if(isPoint(token[j])){break;}
          num1+=translate(token[j])*(int)pow(10,k);
               k--;
        if (num1 > MAXNUM){
            token[0]='\0';
           syn=ERROR_SYN;error_index=1;
           return;
       }
       }
       if(flag==2)syn=12;
       syn=11;


  }
  else

       switch(ch)

       {

       case '#':                        /*識別結束符‘#’(編號0)*/

           syn=0;

           token[i++]='#';

           token[i]='\0';

           break;

       case '+':                        /*識別‘+’(編號13)*/

           syn=13;

           token[i++]='+';

           token[i]='\0';

           break;

       case '-':                        /*識別‘-’(編號14)*/

           syn=14;

           token[i++]='-';

           token[i]='\0';

           break;

       case '*':                        /*識別‘*’(編號15)*/

           syn=15;

           token[i++]='*';

           token[i]='\0';

           break;

       case '/':                        /*識別‘/’(編號16)*/

           syn=16;

           token[i++]='/';

           token[i]='\0';

           break;

       case ':':

           token[i++]=':';

           ch=front(&prog);

           switch(ch)

           {

           case '=':                   /*識別‘:=’(編號18)*/

                syn=18;

                token[i++]='=';

                token[i]='\0';

                dequeue(&prog);

                break;

           default:                    /*識別‘:’(編號17)*/

                syn=17;

                token[i]='\0';

                break;

           }

           break;

       case '<':

           token[i++]='<';

           ch=front(&prog);

           switch(ch)

           {

           case '>':                   /*識別‘<>’(編號21)*/

                syn=21;

                token[i++]='>';

                token[i]='\0';

                dequeue(&prog);

                break;

           case '=':                   /*識別‘<=’(編號22)*/

                syn=22;

                token[i++]='=';

                token[i]='\0';

                dequeue(&prog);

                break;

           default:                    /*識別‘<’(編號20)*/

                syn=20;

                token[i]='\0';

                break;

           }

           break;

       case '>':

           token[i++]='>';

           ch=front(&prog);

           switch(ch)

           {

           case '=':                   /*識別‘>=’(編號24)*/

                syn=24;

                token[i++]='=';

                token[i]='\0';

                dequeue(&prog);

                break;

           default:                    /*識別‘>’(編號23)*/

                syn=23;

                token[i]='\0';

                break;

           }

           break;

       case '=':                        /*識別‘=’(編號25)*/

           syn=25;

           token[i++]='=';

           token[i]='\0';

           break;

       case ';':                        /*識別‘;’(編號26)*/

           syn=26;

           token[i++]=';';

           token[i]='\0';

           break;

       case '(':                        /*識別‘(’(編號27)*/

           syn=27;

           token[i++]='(';

           token[i]='\0';

           break;

       case ')':                        /*識別‘)’(編號28)*/

           syn=28;

           token[i++]=')';

           token[i]='\0';

           break;

       default:                         /*出錯!*/

           syn=-1;

           break;

       }

}



int main()

{

  FILE *in,*out;
  ofstream outfile;
  ofstream inputfile;
  set<string> mset;
  int i;
  string ms;
  char ch;


  setnull(&prog);                           /*緩衝隊列初始化*/
  printf("在input.txt裏面輸入內容(結束符爲#),out.txt中查看輸出\n\n");
  char *argv[]={"E:/ofname.txt","input.txt","out.txt"};
//w+ 存在則清空內容,否則新建文件 
       if(!(in=fopen(argv[1],"r+")))
       {

           printf("請在input.txt中輸入內容!(結束符爲#)\n");
           in=fopen(argv[1],"w+");
           fputc('#',in);
            fclose(in);
           return 0;
       }

    out=fopen(argv[2],"w+");
    outfile.open(argv[2],ios::in);
    do
    {
        do
           {
                ch=fgetc(in);
                enqueue(&prog,ch);
           }while(ch!='#' && !full(&prog));        
           if(ch=='#')
                fclose(in);
       do
       {
           scanner();
           switch(syn)
           {
           case -2:           
                break;
           case 0:
                break;
           case -1:
               outfile <<">>>>  error:在第"<<lineIndex<<"行,原因:"<<error_info[error_index]<<endl;
                break;
           default:
                outfile <<">>>>  ";
                i=0;
                ms="";
                do
                {
                    ms+=token[i];
                    outfile<<token[i++];
                    // fputc(token[i++],out);
                }while(token[i]!='\0');
                if(syn==10){
                    outfile<<"      "<<sign_type[3];
                    finditer=find(type3.begin(),type3.end(),ms);
                    if(finditer==type3.end())
                    type3.push_back(ms);//沒找到就插入
                }
                else if(syn==11||syn==12){
                    outfile<<"      "<<sign_type[2];
                    finditer=find(type2.begin(),type2.end(),ms);
                    if(finditer==type2.end())
                    type2.push_back(ms);//沒找到就插入
                }
                else if(syn>=13&&syn<=28){
                    outfile<<"      "<<sign_type[1];
                    finditer=find(type1.begin(),type1.end(),ms);
                    if(finditer==type1.end())
                    type1.push_back(ms);//沒找到就插入
                }
                else if(syn>=1&&syn<=6){
                    outfile<<"      "<<sign_type[0];
                    finditer=find(type0.begin(),type0.end(),ms);
                    if(finditer==type0.end())
                    type0.push_back(ms);//沒找到就插入
                }
                outfile<<endl;
                //fputc(',',out);
               // i=syn/10;
                //if(i!=0)outfile<<i+48;
                //outfile<<syn%10+48<<endl;
                //fputc(syn%10+48,out);
                //fputc('\n',out);
                break;

           }

       }while(syn!=0 && (quantity(&prog) > MAXSIZE || ch=='#'));//以警號作爲程序結束標誌


  }while(ch!='#');
  outfile <<endl<<"符號表:"<<endl;
  list<string>::iterator eachit;
  outfile << sign_type[0] <<endl;
  for(eachit=type0.begin();eachit!=type0.end();++eachit){
    outfile << *eachit <<endl;
  }

   outfile << sign_type[1] <<endl;
  for(eachit=type1.begin();eachit!=type1.end();++eachit){
    outfile << *eachit <<endl;
  }
 /*
   outfile << sign_type[2] <<endl;
  for(eachit=type2.begin();eachit!=type2.end();++eachit){
    outfile << *eachit <<endl;
  }
  */
   outfile << sign_type[3] <<endl;
  for(eachit=type3.begin();eachit!=type3.end();++eachit){
    outfile << *eachit <<endl;
  }
  outfile.close();
  return 0;
}

語法分析 slr(1) _by MichaelZ

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<list>
using namespace std;
char KeyWords[10][10] = { "do", "else",  "if", "return", "void", "while","program","begin","end","then"};

int slr1[102][26];// 分析表 賦值(s9=900,r1=1;acc=30)


char creat[23][15]={"0","A->pi(H);C.","H->i","H->H,i","C->bOe","O->S","O->","S->T",
"S->S;T","T->i:E","T->C","T->fBtT","T->fBtTlT","T->wBdT","B->E<E","E->E+M","E->M","M->M*F","M->F","F->i","F->n"};//文法單元;


char temp[10],p,in[100],table[100][10];//存放識別字符串;


int t,j,val,b,flag;
char flag1,put[100],*arr;
int begin=0,forward=0,pos;// 開始符號和向前看指針;
FILE *out=fopen("out.txt","w");//用文件進行輸出
int main()
{
//SLR(1)分析表
int slr1[45][32]={

    {0, 200,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0,   0,0,0,0,0,  100,0,0,0,0,  0,0,0,0,0 },
    {0, 0,0,0,0,0,    0,0,0,0,0,  0,0,0,0,0,   0,0,0,0,30,  0,0,0,0,0,  0,0,0,0,0 },
    {0, 0,300,0,0,0,  0,0,0,0,0,  0,0,0,0,0,   0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0 },
    {0, 0,0,400,0,0,  0,0,0,0,0,  0,0,0,0,0,   0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0 },
    {0, 0,600,0,0,0,  0,0,0,0,0,  0,0,0,0,0,   0,0,0,0,0,  0,500,0,0,0,  0,0,0,0,0 },

    {0, 0,0,0,700,0,  0,800,0,0,0,  0,0,0,0,0,   0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0 },
    {0, 0,0,0,2,0,    0,2,0,0,0,  0,0,0,0,0,   0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0 },
    {0, 0,0,0,0,900,  0,0,0,0,0,  0,0,0,0,0,   0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0 },
    {0, 0,1000,0,0,0, 0,0,0,0,0,  0,0,0,0,0,   0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0 },
    {0, 0,0,0,0,0,    0,0,1200,0,0,  0,0,0,0,0,   0,0,0,0,0,  0,0,1100,0,0,  0,0,0,0,0 },

    {0, 0,0,0,3,0,  0,3,0,0,0,  0,0,0,0,0,   0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0 },
    {0, 0,0,0,0,0,  1300,0,0,  0,0,0,0,0,   0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0 },
    {0, 0,1700,0,0,0,  0,0,1200,0,0,  1900,0,0,2000,0,   0,0,0,0,0,  0,0,1800,1400,1500,  1600,0,0,0,0 },
    {0, 0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0,   0,0,0,0,1,  0,0,0,0,0,  0,0,0,0,0 },
    {0, 0,0,0,0,0,  0,0,0,2100,0,  0,0,0,0,0,   0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0 },

    {0, 0,0,0,0,2200,  0,0,0,5,0,  0,0,0,0,0,   0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0 },
    {0, 0,0,0,0,7,     0,0,0,7,0,  0,0,0,0,0,   0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0 },
    {0, 0,0,0,0,0,     0,0,0,0,2300,  0,0,0,0,0,   0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0 },
    {0, 0,0,0,0,10,    0,0,0,10,0,  0,0,10,0,0,   0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0 },
    {0, 0,2800,0,0,0,  0,0,0,2900,0,  0,0,0,0,0,   0,0,0,0,0,  0,0,0,0,0,  0,2400,2500,2600,2700 },

    {0, 0,2800,0,0,0,  0,0,0,2900,0,  0,0,0,0,0,   0,0,0,0,0,  0,0,0,0,0,  0,3000,2500,2600,2700 },
    {0, 0,0,0,0,4,  4,0,0,4,0,  0,0,4,0,0,   0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0 },
    {0, 0,1700,0,0,0,  0,0,1200,0,0,  1900,0,0,2000,0,   0,0,0,0,0,  0,0,1800,0,0,  3100,0,0,0,0 },
    {0, 0,2800,0,0,0,  0,0,0,0,0,  0,0,0,0,0,   0,0,0,2900,0,  0,0,0,0,0,  0,0,3200,2600,2700 },
    {0, 0,0,0,0,0,  0,0,0,0,0,  0,3300,0,0,0,   0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0 },

    {0, 0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0,   3400,3500,0,0,0,  0,0,0,0,0,  0,0,0,0,0 },
    {0, 0,0,0,0,16,  0,0,0,16,0,  0,16,16,0,16,   16,16,3600,0,0,  0,0,0,0,0,  0,0,0,0,0 },
    {0, 0,0,0,0,18,  0,0,0,18,0,  0,18,18,0,18,   18,18,18,0,0,  0,0,0,0,0,  0,0,0,0,0 },
    {0, 0,0,0,0,19,  0,0,0,19,0,  0,19,19,0,19,   19,19,19,0,0,  0,0,0,0,0,  0,0,0,0,0 },
    {0, 0,0,0,0,20,  0,0,0,20,0,  0,20,20,0,20,   20,20,20,0,0,  0,0,0,0,0,  0,0,0,0,0 },

    {0, 0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,3700,   0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0 },
    {0, 0,0,0,0,8,  0,0,0,8,0,  0,0,0,0,0,   0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0 },
    {0, 0,0,0,0,9,  0,0,0,9,0,  0,0,9,0,0,   0,3500,0,0,0,  0,0,0,0,0,  0,0,0,0,0 },
    {0, 0,1700,0,0,0,  0,0,1200,0,0,  1900,0,0,2000,0,   0,0,0,0,0,  0,0,1800,0,0,  3800,0,0,0,0 },
    {0, 0,2800,0,0,0,  0,0,0,0,0,  0,0,0,0,0,   0,0,0,2900,0,  0,0,0,0,0,  0,0,3900,2600,2700 },

    {0, 0,2800,0,0,0,  0,0,0,0,0,  0,0,0,0,0,   0,0,0,2900,0,  0,0,0,0,0,  0,0,0,4000,2700 },
    {0, 0,2800,0,0,0,  0,0,0,0,0,  0,0,0,0,0,   0,0,0,2900,0,  0,0,0,0,0,  0,0,0,0,4000,2700 },
    {0, 0,1700,0,0,0,  0,0,1200,0,0,  1900,0,0,2000,0,   0,0,0,0,0,  0,0,1800,0,0,  4200,0,0,0,0 },
    {0, 0,0,0,0,11,  0,0,0,11,0,  0,0,4300,0,0,   0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0 },
    {0, 0,0,0,0,0,  0,0,0,0,0,  0,14,0,0,14,   0,3500,0,0,0,  0,0,0,0,0,  0,0,0,0,0 },

    {0, 0,0,0,0,15,  0,0,0,15,0,  0,15,15,0,15,   15,15,3600,0,0,  0,0,0,0,0,  0,0,0,0,0 },
    {0, 0,0,0,0,17,  0,0,0,17,0,  0,17,17,0,17,   17,17,0,0,0,  0,0,0,0,0,  0,0,0,0,0 },
    {0, 0,0,0,0,13,  0,0,0,13,0,  0,0,13,0,0,   0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0 },
    {0, 0,1700,0,0,0,  0,0,1200,0,0,  1900,0,0,2000,0,   0,0,0,0,0,  0,0,1800,0,0,  4400,0,0,0,0 },
    {0, 0,0,0,0,12,  0,0,0,12,0,  0,0,12,0,0,   0,0,0,0,0,  0,0,0,0,0,  0,0,0,0,0 }
    };

    list<int> list1;//鏈表定義
    list<char> list2;
    list<int>::iterator it1;//itrator做指針
    list<char>::iterator it2;

    //讀取文件以達到輸入的目的

    void print(int flag);//print函數用於輸入字符的類別判斷與輸出,並且將得到的類型存入in[]中
    //in[]作爲簡化後的輸入串
    int group(char flag1 );//group函數用於確定項在分析表中的列號數
    int size,i=0,l=1;
    char ch; 
    FILE *fp=fopen("file.txt","r");//用文件進行輸入

    if (out==NULL){ return 0;}
    if (fp==NULL){ return 0;}
    fseek(fp,0,2);//找到文件尾
    size=ftell(fp); //ftell存入的是偏移地址
    arr=new char[size];
    if ((fp=fopen("file.txt","r"))==NULL) exit(1);
    if ((out=fopen("out.txt","w"))==NULL) exit(1);
    while (!feof(fp))
    {
        ch=fgetc(fp);
        arr[i++]=ch;//array用於存儲文件中的字符
    }
    fclose(fp);  
    size=i-1;
    int state;//狀態;
    i=0; 


    //詞法分析器

    while(i<=size)
    {
                for(t=0;t<8;t++)
                temp[t]=0;
        if(begin==forward)
        {
            ch=arr[forward];
            if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z') state=9;
            else if(ch>='0'&&ch<='9')state=12;
            else if(ch=='+'||ch=='-'||ch=='*'||ch=='/')state=25;
            else if(ch=='<'||ch=='>'||ch==':')state=0;
            else if(ch=='.'||ch==','||ch==';'||ch=='('||ch==')')state=30;
            else if (ch=='\n'||ch=='\t'||ch==' ') state=22;
            else state=31;

        }       



switch(state)
        {
        case 0: {ch=arr[i++];forward++;}    
            if(ch=='<')state=1;
            else if(ch=='='){state=5;}
            else if(ch=='>')state=6;
            break;
        case 1:{ch=arr[i++];forward++;} 
            if(ch=='=')state=2;
            else if(ch=='>')state=3;
            else state=4;
            break;
        case 2:print(5);    break;      
        case 3:print(5);    break;      
        case 4:{i=i-1;forward=forward-1;print(5);}
            break;
        case 5:print(5);break;
        case 6:{ch=arr[i++];forward++;} 
            if(ch=='=')state=7;
            else state=8;
            break;
        case 7:print(5);break;          
        case 8:{i=i-1;forward=forward-1;print(5);}
            break;


        case 9:{ch=arr[i++];forward++;} 
            if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))state=10;
            break;


        case 10:{ch=arr[i++];forward++;}    
            if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))state=10;
            else if(ch>='0'&&ch<='9')state=10;
            else state=11;
            break;
        case 11:
            i=i-1;forward=forward-1;print(1);
            break;

        case 12:{ch=arr[i++];forward++;}    
            if(ch>='0'&&ch<='9')state=13;
            break;
        case 13:{ch=arr[i++];forward++;}    
            if(ch>='0'&&ch<='9')state=13;
            else if (ch=='E')state=16;
            else if(ch=='.')state=14;
            else state=20;
            break;
        case 14:{ch=arr[i++];forward++;}    
            if(ch>='0'&&ch<='9')state=15;
            else state=32;
            break;
        case 15:{ch=arr[i++];forward++;}    
            if(ch>='0'&&ch<='9')state=15;
            else if(ch=='E')state=16;
            else state=21;
            break;
        case 16:{ch=arr[i++];forward++;}    
            if(ch>='0'&&ch<='9')state=18;
            else if(ch=='+'||ch=='-')state=17;
            else state=32;
            break;
        case 17:{ch=arr[i++];forward++;}    
            if(ch>='0'&&ch<='9')state=18;
            else state=32;
            break;
        case 18:{ch=arr[i++];forward++;}    
            if(ch>='0'&&ch<='9')state=18;
            else   state=19;
            break;
        case 19:{i=i-1;forward=forward-1;print(2);}break;
        case 20:{i=i-1;forward=forward-1;print(2);}break;
        case 21:{i=i-1;forward=forward-1;print(2);}break;
        case 22:{ch=arr[i++];forward++;}    
            if(ch=='\n'||ch=='\t'||ch==' ')
                state=23;
            break;
        case 23:{ch=arr[i++];forward++;}    
            if(ch=='\n'||ch=='\t'||ch==' ') state=23;
            else   state=24;
            break;
        case 24:{i=i-1; forward=forward-1;begin+=1; forward=begin;}
            break;


        case 25:{ch=arr[i++];forward++;}    
            if(ch=='+')state=26;
            else if(ch=='-')state=27;
            else if(ch=='*')state=28;
            else if(ch=='/')state=29;   
            break;

        case 26:print(4);break;
        case 27:print(4);break;
        case 28:print(4);break;
        case 29:print(4);break;
        case 30:{ch=arr[i++];forward++;}print(3);break;
        case 31:{ch=arr[i++];forward++;}print(6);break; 
        case 32:{i=i-1;forward=forward-1;}print(6);break;   
        }


}

    //語法分析;字符串輸入以$結束
    printf("輸入的字符串以結束$\n");

    fputs("輸入的字符串以結束$\n",out);

    in[val]='$';
    printf("%s",in);
    printf("\n");
    fputs(in,out);
    fputs("\n",out);
    i=0;j=0;
    list1.push_back(0);//push_back() //增加一元素到鏈表尾
    char n,c;
    int m,st,len;
    printf("棧              符號                      輸入                     動作 \n"); 
    fputs("棧                                   符號                                    輸入                                                     動作 \n",out);
    while(1) 
    { 
        char s[10];
        char b[1000]={0};
        //begin() 返回第一個元素的指針(iterator)
        //返回最後一個元素的下一位置的指針(list爲空時end()=begin())
        for(it1=list1.begin();it1!=list1.end();it1++){  
        //printf("%d",*it1);
        //整形字符串拼接
        sprintf(s, "%d",*it1);
        sprintf(b,"%s%s",b,s); 
        }
        //printf("%s",b);
        fputs(b,out);
    //  printf("                  ");
        fputs("                                   ",out);
        for(it2=list2.begin();it2!=list2.end();it2++){
    //      printf("%c",*it2); 
            fputc(*it2,out);
        }
    //  printf("                              ");   
        fputs("                  ",out);
        for(i=j;i<=val;i++){
            printf("%c",in[i]);
            fputc(in[i],out);
        }
        //printf("                              ");
        fputs("                                 ",out);
        st=list1.back();

        n=in[j];
        flag=group(n);//得到當前狀態行數 

        if(slr1[st][flag]>100)
        {
            m=slr1[st][flag]/100;

            printf("移入\n");
            fputs("移入\n",out);
            list1.push_back(m);

            list2.push_back(in[j]);
            j++;
        }
        else if(slr1[st][flag]<100&&slr1[st][flag]!=30&&slr1[st][flag]!=0)
        {
            m=slr1[st][flag];
            printf("根據%s規約\n",creat[m]);
            fputs("根據",out);
            fputs(creat[m],out);
            fputs("規約\n",out);
            c=creat[m][0];            
            flag=group(c);        
            len=strlen(creat[m])-3;
            for(i=0;i<len;i++)

            {    list1.pop_back();
            list2.pop_back();
            }

            st=list1.back();
            //printf("\n%d\n",st);
            //printf("\n%d\n",flag);
            list2.push_back(c);
            m=slr1[st][flag]/100;

            list1.push_back(m);
        }
        else if(slr1[st][flag]==30)
        { 
            printf("接受\n");
            fputs("接受\n",out);
            break;
        }
        else if(slr1[st][flag]==0)
        {
            printf("\n");
            fputs("\n",out);
            printf("%s",table[j-1]);
            fputs(table[j-1],out);
            printf("%s ",table[j]);
            fputs(table[j],out);
            printf("ERROR\n");
            fputs("ERROR\n",out);
            break;
        }
    }
    fclose(out);
    return 0;
    }   
    void print(int b) //輸出 
    {   
        pos=begin;
        for(t=0;t<forward-begin;t++)
        {
            p=arr[pos++];temp[t]=p;         
        }
        begin=forward;

        switch(b)
        {
        case 1:        
            {
                for(j=0; j<55; j++)

                    if(strcmp(temp,KeyWords[j])==0)
                    {
                        printf("<%s keyword>\n",temp);
                         fputs("<",out);
                         fputs(temp,out);
                         fputs(" keyword>\n",out);
                        if(strcmp(temp,"if")==0)
                        {   
                            strcpy(table[val],temp);
                            in[val++]='f';  break;}
                        else if(strcmp(temp,"program")==0)
                        {
                            strcpy(table[val],temp);
                            in[val++]='p';  break;}
                        else if(strcmp(temp,"end")==0)
                        {
                            strcpy(table[val],temp);
                            in[val++]='e';  break;}
                        else if(strcmp(temp,"else")==0)
                        {
                            strcpy(table[val],temp);
                            in[val++]='l';  break;}
                        else if(strcmp(temp,"while")==0)
                        {
                            strcpy(table[val],temp);    
                            in[val++]='w';  break;}
                        else if(strcmp(temp,"do")==0)
                        {
                            strcpy(table[val],temp);
                            in[val++]='d';  break;}
                        else if(strcmp(temp,"then")==0)
                        {
                                strcpy(table[val],temp);
                            in[val++]='t';  break;}
                        else 
                        { 
                            strcpy(table[val],temp);
                            in[val++]='b';  break;  }                                          
                    }
                    if(j==55) 
                    {   printf("<%s id>\n",temp);
                     fputs("<",out);
                         fputs(temp,out);
                         fputs(" id>\n",out);
                    strcpy(table[val],temp);
                    in[val++]='i';}
            }break;
        case 2:
            printf("<%s num>\n",temp);
            fputs("<",out);
            fputs(temp,out);
            fputs(" num>\n",out);
            strcpy(table[val],temp);
            in[val++]='n';           
            break;
        case 3:
            printf("<%s division>\n",temp);
            fputs("<",out);
            fputs(temp,out);
            fputs(" division>\n",out);
             strcpy(table[val],temp);
            in[val++]=temp[0];          
            break;
        case 4:
            printf("<%s relation>\n",temp);
            fputs("<",out);
            fputs(temp,out);
            fputs(" relation>\n",out);
            strcpy(table[val],temp);
            in[val++]=temp[0];
            break;
        case 5: 

            printf("<%s operator>\n",temp);
            fputs("<",out);
            fputs(temp,out);
            fputs(" operator>\n",out);
            strcpy(table[val],temp);
            in[val++]=temp[0];  

            break;
        case 6:
                printf("<%s ERROR>\n",temp);
                fputs("<",out);
                fputs(temp,out);
                fputs(" ERROR>\n",out);
            break;
        }       
    }


    int group(char flag1 )
    {
        if(flag1=='p')
            flag=1;
        else if(flag1=='i')
            flag=2;
        else if(flag1=='(')
            flag=3;     
        else if(flag1==')')
            flag=4;
        else if(flag1==';')
            flag=5;
        else if(flag1=='.')
            flag=6;
        else if(flag1==',')
            flag=7;
        else if(flag1=='b')
            flag=8;
        else if(flag1=='e')
            flag=9;
        else if(flag1==':')
            flag=10;
        else if(flag1=='f')
            flag=11;
        else if(flag1=='t')
            flag=12;
        else if(flag1=='l')
            flag=13;
        else if(flag1=='w')
            flag=14;
        else if(flag1=='d')
            flag=15;
        else if(flag1=='<')
            flag=16;
        else if(flag1=='+')
            flag=17;
        else if(flag1=='*')
            flag=18;
        else if(flag1=='n')
            flag=19;
        else if(flag1=='$')
            flag=20;
        else if(flag1=='A')
            flag=21;
        else if(flag1=='H')
            flag=22;
        else if(flag1=='C')
            flag=23;
        else if(flag1=='O')
            flag=24;
        else if(flag1=='S')
            flag=25;
        else if(flag1=='T')
            flag=26;
        else if(flag1=='B')
            flag=27;
        else if(flag1=='E')
            flag=28;
        else if(flag1=='M')
            flag=29;
        else if(flag1=='F')
            flag=30;
        return(flag);
    } 

語義分析 by france&lola

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cstring>
using namespace std;
//詞法分析雙向鏈表(存已識別的詞單元(endSign))
typedef struct WordAnalysisList
{
    struct WordAnalysisList *last;
    char index;//以字母作爲標號 其index爲在endSign中對應的元素
    char value[128];//對應值字符串
    struct WordAnalysisList *next;
}WordAnalysisList;
//headWAL 對應語法分析時的輸入
WordAnalysisList *headWAL, *currendWAL;
//headSignStack:符號棧 從null到最後被規約成S tail4:反着顯示要用到
WordAnalysisList *headSignStack, *tail4;
typedef struct Tree
{
    int number;
    char bb[128];
    struct Tree *haveF;
    struct Tree *child[4];
}Tree;
Tree *root;
//語法分析棧
typedef struct stack
{
    struct stack *last;
    //當前棧的值(規約規則的序號)
    int number;
    //非終結符的個數
    int flag;
    char bb[128];
    struct Tree *haveF;
    struct stack *next;
}Stack;
Stack *stackHead, *tail2;
//存規約順序
Stack *guiYueOrderheadTemp;
//在guiYueOrderheadTemp初始化的時候賦值給guiYueOrderhead 存的是第一個規約
Stack *guiYueOrderhead;
//對語法樹進行前序遍歷
Stack * grammarTreePreorderHead;
//用來存儲 id或者number 
typedef struct Str2
{
    char sstr[128];
    struct Str2 *next;
}Str2;
//head*:規約時將識別到的id或num放入list
Str2 *headid, *headnum, *headid2, *headnum2;
int id = 0, num = 0, ok = 1;
char str[128], Bool[128];

//初始化詞法分析
void initMorphology(){
    headWAL = NULL;
    currendWAL = NULL;
}
//行號
int line = 1;

//act[i][j]=a:第i個狀態在第j個終結符執行的操作:a>0表示sa,a<0表示ra a=0表示acc
int act[45][20];
//gt[i][j]=b:規約pop stack後第i個狀態在第j個終結符時跳轉到第b個狀態
int gt[45][10];
//haveF[i][j] = c第i個字母在第j個產生式中存在c次
int haveF[10][21];
//全局的Lx Tx;
int L = 0, T = 0;
//具體的產生式規則
char gg[21][128] = { "s'->A", "S -> program id ( id_lists );  compound_stmt .", "id_lists -> id ", "id_lists -> id_lists , id ", "compound_stmt -> begin optional_stmts end", "optional_stmts -> stmts ", "optional_stmts -> ε", "stmts -> stmt ", "stmts -> stmts; stmt ", "stmt -> id := expr ", "stmt -> compound_stmt", "stmt -> if bool then stmt ", "stmt -> if bool then stmt else stmt ", "stmt -> while bool  do stmt", "bool ->  expr < expr ", "expr -> expr + term  ", "expr -> term", "term -> term * factor ", "term -> factor", "factor -> id ", "factor -> num" };
//簡化的產生式規則
char g[21][12] = { "s'->A", "A->bcdBefCg", "B->c", "B->Bhc", "C->iDj", "D->E", "D->ε", "E->F", "E->EfF", "F->ckH", "F->C", "F->lGmF", "F->lGmFnF", "F->oGpF", "G->HqH", "H->HrI", "H->I", "I->IsJ", "I->J", "J->c", "J->t" };
//規約時棧pop的個數
int Number[21] = { 1, 8, 1, 3, 3, 1, 0, 1, 3, 3, 1, 4, 6, 4, 3, 3, 1, 3, 1, 1, 1 };
//非終結符
char noend[10][15] = { "S", "id_lists", "compound_stmt", "optional_stmts", "stmts", "stmt", "bool", "expr", "term", "factor" };
//終結符
char endSign[21][8] = { "ε", "program", "id", "(", ")", ";", ".", ",", "begin", "end", ":=", "if", "then", "else", "while", "do", "<", "+", "*", "num", "$" };
/*
初始化語法分析表(手動)
act[i][j]=a:第i個狀態在第j個終結符執行的操作:a>0表示sa,a<0表示ra a=0表示acc
gt[i][j]=b:規約pop stack後第i個狀態在第j個終結符時跳轉到第b個狀態
haveF[i][j] = c第i個字母在第j個產生式中存在c次
*/
void initGrammar()
{
    act[0][0] = 2;
    act[1][19] = 0;
    act[2][1] = 3;
    act[3][2] = 4;
    act[4][1] = 6;
    act[5][3] = 7; act[5][6] = 8;
    act[6][3] = -2; act[6][6] = -2;
    act[7][4] = 9;
    act[8][1] = 10;
    act[9][7] = 12;
    act[10][3] = -3; act[10][6] = -3;
    act[11][5] = 13;
    act[12][1] = 17; act[12][7] = 12; act[12][8] = -6; act[12][10] = 19; act[12][13] = 20;
    act[13][19] = -1;
    act[14][8] = 21;
    act[15][4] = 22; act[15][8] = -5;
    act[16][4] = -7; act[16][8] = -7;
    act[17][9] = 23;
    act[18][4] = -10; act[18][8] = -10; act[18][12] = -10;
    act[19][1] = 28; act[19][18] = 29;
    act[20][1] = 28; act[20][18] = 29;
    act[21][4] = -4; act[21][5] = -4; act[21][8] = -4; act[21][12] = -4;
    act[22][1] = 17; act[22][7] = 12; act[22][10] = 19; act[22][13] = 20;
    act[23][1] = 28; act[23][18] = 29;
    act[24][11] = 33;
    act[25][15] = 34; act[25][16] = 35;
    act[26][4] = -16; act[26][8] = -16; act[26][11] = -16; act[26][12] = -16; act[26][14] = -16; act[26][15] = -16; act[26][16] = -16; act[26][17] = 36;
    act[27][4] = -18; act[27][8] = -18; act[27][11] = -18; act[27][12] = -18; act[27][14] = -18; act[27][15] = -18; act[27][16] = -18; act[27][17] = -18;
    act[28][4] = -19; act[28][8] = -19; act[28][11] = -19; act[28][12] = -19; act[28][14] = -19; act[28][15] = -19; act[28][16] = -19; act[28][17] = -19;
    act[29][4] = -20; act[29][8] = -20; act[29][11] = -20; act[29][12] = -20; act[29][14] = -20; act[29][15] = -20; act[29][16] = -20; act[29][17] = -20;
    act[30][14] = 37;
    act[31][4] = -8; act[31][8] = -8;
    act[32][4] = -9; act[32][8] = -9; act[32][12] = -9; act[32][16] = 35;
    act[33][1] = 17; act[33][7] = 12; act[33][10] = 19; act[33][13] = 20;
    act[34][1] = 28; act[34][18] = 29;
    act[35][1] = 28; act[35][18] = 29;
    act[36][1] = 28; act[36][18] = 29;
    act[37][1] = 17; act[37][7] = 12; act[37][10] = 19; act[37][13] = 20;
    act[38][4] = -11; act[38][8] = -11; act[38][12] = 43;
    act[39][11] = -14; act[39][14] = -14; act[39][16] = 35;
    act[40][4] = -15; act[40][8] = -15; act[40][11] = -15; act[40][12] = -15; act[40][14] = -15; act[40][15] = -15; act[40][16] = -15; act[40][17] = 36;
    act[41][4] = -17; act[41][8] = -17; act[41][11] = -17; act[41][12] = -17; act[41][14] = -17; act[41][15] = -17; act[41][16] = -17; act[41][17] = -17;
    act[42][4] = -13; act[42][8] = -13; act[42][12] = -13;
    act[43][1] = 17; act[43][7] = 12; act[43][10] = 19; act[43][13] = 20;
    act[44][4] = -12; act[44][8] = -12; act[44][12] = -12;

    gt[0][0] = 1;
    gt[4][1] = 5;
    gt[9][2] = 11;
    gt[12][2] = 18; gt[12][3] = 14; gt[12][4] = 15; gt[12][5] = 16;
    gt[19][6] = 24; gt[19][7] = 25; gt[19][8] = 26; gt[19][9] = 27;
    gt[20][6] = 30; gt[20][7] = 25; gt[20][8] = 26; gt[20][9] = 27;
    gt[22][2] = 18; gt[22][5] = 31;
    gt[23][7] = 32; gt[23][8] = 26; gt[23][9] = 27;
    gt[33][2] = 18; gt[33][5] = 38;
    gt[34][7] = 39; gt[34][8] = 26; gt[34][9] = 27;
    gt[35][8] = 40; gt[35][9] = 27;
    gt[36][9] = 41;
    gt[37][2] = 18; gt[37][5] = 42;
    gt[43][2] = 18; gt[43][5] = 44;

    haveF[1][1] = 1; haveF[1][3] = 1;
    haveF[2][1] = 1; haveF[2][10] = 1;
    haveF[3][4] = 1;
    haveF[4][5] = 1; haveF[4][8] = 1;
    haveF[5][7] = 1; haveF[5][8] = 1; haveF[5][11] = 1; haveF[5][12] = 2; haveF[5][13] = 1;
    haveF[6][11] = 1; haveF[6][12] = 1; haveF[6][13] = 1;
    haveF[7][9] = 1; haveF[7][14] = 2; haveF[7][15] = 1;
    haveF[8][15] = 1; haveF[8][16] = 1; haveF[8][17] = 1;
    haveF[9][17] = 1; haveF[9][18] = 1;
}
/*
增加詞法節點
以標號c和值s[]建一個節點,並加到詞法分析鏈表的最後面
*/
void addWordNode(char c, char s[])
{
    WordAnalysisList *temp;
    //創建WAL_Node
    temp = (WordAnalysisList*)malloc(sizeof(WordAnalysisList));
    temp->index = c;
    if (s)
        strcpy(temp->value, s);

    if (headWAL == NULL)
    {
        headWAL = temp;
        currendWAL = headWAL;
    }
    else
    {
        printf("currend value:%s\n", currendWAL->value);
        if (headWAL->next == NULL){
            headWAL->next = temp;
            currendWAL = headWAL->next;
        }
        else{
            currendWAL->next = temp;
            currendWAL = currendWAL->next;
        }
        currendWAL->next = NULL;
    }
}
/*
識別關鍵字
傳入文件開始識別指針
返回關鍵字所在endSign數組中的位置 或 報error返回
*/
void keyword(FILE *fp)
{
    char ch, instring[128];
    int n = 0;
    do{
        ch = fgetc(fp);
        instring[n++] = ch;
    } while ((ch >= 'a'&&ch <= 'z') || (ch >= 'A'&&ch <= 'Z'));
    fseek(fp, -1L, 1);
    instring[--n] = 0;
    _strlwr(instring);//將字符串中的字符轉換爲小寫
    int i;
    for (i = 1; i<20; i++)
    {
        if (i != 2 && i != 19)
        {
            if (strcmp(instring, endSign[i]) == 0)
                break;
        }
    }
    if (i<20)
    {
        //加入關鍵字
        addWordNode(97 + i, instring);
    }
    else
    {
        if (n>32)
            printf("-->>error標識符過長!  line:%d\n", line);
        //加入id
        addWordNode(97 + 2, instring);
    }
}
void number(FILE *fp, int flag)
{
    char ch, instring[128];//,instring2[128];
    int n = 0; int number = 0; int m;
    do{
        ch = fgetc(fp);
        instring[n++] = ch;
    } while (ch >= '0'&&ch <= '9');
    fseek(fp, -1L, 1);
    instring[--n] = '\0';
    for (int i = 0; i<n; i++)
    {
        m = 1;
        for (int j = 0; j<(n - i - 1); j++)
            m *= 10;
        number += (instring[i] - 48)*m;
    }
    //加入number
    addWordNode(97 + 19, instring);
}
void number36(FILE *fp)
{
    char ch, instring[128];
    int n = 0;
    int number = 0, m;
    do{
        ch = fgetc(fp);
        if (ch == '\n')
            line++;
        instring[n++] = ch;
    } while ((ch >= '0'&&ch <= '9') || (ch >= 'a'&&ch <= 'z') || (ch >= 'A'&&ch <= 'Z'));
    fseek(fp, -1L, 1);
    instring[--n] = '\0';
    for (int i = 0; i<n; i++)
    {
        m = 1;
        for (int j = 0; j<(n - i - 1); j++)
            m *= 36;
        if (instring[i] >= '0'&&instring[i] <= '9')
            number += (instring[i] - 48)*m;
        else if (instring[i] >= 'a'&&instring[i] <= 'z')
            number += (instring[i] - 87)*m;
        else
            number += (instring[i] - 55)*m;
    }
    if (number >= 16777216)
        printf("-->> 7、error越界錯誤! line:%d\n", line);
    //加入number
    addWordNode(97 + 19, instring);
}
void other(FILE *fp)
{
    int endIndex = 0;
    char ch = fgetc(fp);
    if (ch == ' ' || ch == '\n' || ch == '\t')
        endIndex = -2;
    char s[3];
    s[0] = ch;
    if (ch == ':')
    {
        ch = fgetc(fp);
        if (ch == '=')
        {
            s[1] = ch; s[2] = '\0';
        }
        else
        {
            endIndex = -1;
        }
    }
    else
    {
        s[1] = '\0';
    }
    int i;
    for (i = 1; i<20; i++)
    {
        if (i != 2 && i != 19)
        {
            if (strcmp(endSign[i], s) == 0)
            {
                break;
            }
        }
    }
    if (i<20)
    {
        endIndex = i;
    }
    else
    {
        endIndex = -1;
    }
    if (endIndex>-1)
    {
        addWordNode(97 + endIndex, endSign[endIndex]);
    }
}
//在詞法最後增加一個表示識別結束的$符號
void addWordNodeEnd()
{
    WordAnalysisList *endNode;
    endNode = (WordAnalysisList*)malloc(sizeof(WordAnalysisList));
    endNode->index = '$';
    endNode->next = NULL;
    currendWAL->next = endNode;
}
//添加當前要移入的詞法單元到符號棧
void addCurrentInputWord(char c, char s[])
{
    WordAnalysisList *p1;
    p1 = (WordAnalysisList*)malloc(sizeof(WordAnalysisList));
    p1->index = c;
    if (s)
        strcpy(p1->value, s);
    p1->next = headSignStack;
    p1->last = NULL;
    headSignStack->last = p1;
    headSignStack = p1;
}
//傳入的s爲類型number或者id的值 c=1 表示傳入的是id 0 number
void addheadstr(int c, char s[])
{
    printf("\n addheadstr s:%s\n", s);
    Str2 *p1, *p2, *p3 = NULL;
    p1 = (Str2*)malloc(sizeof(Str2));
    strcpy(p1->sstr, s);
    p1->next = NULL;
    if (c == 1)
    {
        p2 = headid;
        if (p2 == NULL)
        {
            headid = p1;
        }
        else
        {
            while (p2)
            {
                p3 = p2;
                p2 = p2->next;
            }
            p3->next = p1;
        }
    }
    else
    {
        p2 = headnum;
        if (p2 == NULL)
        {
            headnum = p1;
        }
        else
        {
            while (p2)
            {
                p3 = p2;
                p2 = p2->next;
            }
            p3->next = p1;
        }
    }
}
//移入或規約時產生的push
void addstack(int t)
{
    Stack *p1;
    p1 = (Stack*)malloc(sizeof(Stack));
    p1->number = t;
    p1->next = stackHead;
    p1->last = NULL;
    stackHead->last = p1;
    stackHead = p1;
}
//存語法分析的規約順序(t爲第幾條規約規則)
void addGuiyueOrder(int t)
{
    Stack *p1;
    p1 = (Stack*)malloc(sizeof(Stack));
    p1->number = t;
    p1->flag = 0;
    p1->next = guiYueOrderheadTemp;
    p1->last = NULL;
    if (guiYueOrderheadTemp == NULL)
        guiYueOrderheadTemp = guiYueOrderhead = p1;
    else guiYueOrderheadTemp->last = p1;
    guiYueOrderheadTemp = p1;
}
//規約時狀態棧產生的pop
void popstack(int i)
{

    int j = Number[i];
    while (j--)
    {
        stackHead = stackHead->next;
    }
    stackHead->last = NULL;
}
//規約時符號棧產生的pop
void popSignStack(int i)
{
    WordAnalysisList *p1;
    p1 = headSignStack;
    int j = Number[i];
    while (j--)
    {
        p1 = p1->next;
    }
    if (p1)
    {
        p1->last = NULL;

    }
    headSignStack = p1;
}
//將原來縮略的產生字母轉爲對應的詞法單元
void Printf(char aa)
{
    if (aa>'a' && aa <= 'z')
    {
        printf("%s ", endSign[aa - 97]);
    }
    else if (aa >= 'A' && aa <= 'Z')
    {
        printf("%s ", noend[aa - 65]);
    }
    else if (aa == '$')
    {
        printf("$");
    }
}
void output(int t, int j)
{
    Stack *p1;
    WordAnalysisList *p2, *p3, *p4;
    p2 = headWAL;
    p1 = tail2;
    p3 = headSignStack;
    p4 = tail4;
    if (t != 3)
    {
        if (t == 1)
            printf("移入\n");
        else if (t == 2) printf("歸約%s\n", gg[j]);
        while (p1)
        {
            printf("%d ", p1->number);
            p1 = p1->last;
        }
        printf("                          ");
        while (p4)
        {
            Printf(p4->index);
            p4 = p4->last;
        }
        printf("                          ");
        while (p2)
        {
            Printf(p2->index);
            p2 = p2->next;
        }
        printf("                          ");
    }
    else printf("接受\n");
}
//由詞法單元去執行語法分析,得到一個規約順序(實驗二爲直接輸出)
void grammarAnalysis()
{
    WordAnalysisList *temp;
    int i, j, k;
    Stack *p1;
    p1 = (Stack*)malloc(sizeof(Stack));
    //初始化棧
    p1->number = 0;
    p1->next = NULL;
    p1->last = NULL;
    stackHead = tail2 = p1;
    WordAnalysisList *p2;
    //headWAL 對應語法分析時的輸入
    while (1)
    {
        if (headWAL->index == '$')
        {
            j = headWAL->index - 17;
        }
        else
            j = headWAL->index - 98;
        //移入 入棧
        if (act[stackHead->number][j]>0)
        {
            addstack(act[stackHead->number][j]);
            if (tail4 == NULL)
            {
                //p2:當前輸入的詞法單元
                p2 = (WordAnalysisList*)malloc(sizeof(WordAnalysisList));
                p2->index = headWAL->index;
                strcpy(p2->value, headWAL->value);
                p2->next = NULL;
                p2->last = NULL;
                //加到符號棧
                headSignStack = tail4 = p2;
            }
            else addCurrentInputWord(headWAL->index, headWAL->value);

            headWAL = headWAL->next;
            output(1, 0);
        }
        //規約 改棧
        else if (act[stackHead->number][j]<0)
        {
            i = -act[stackHead->number][j];
            //存第i條規約順序
            addGuiyueOrder(i);
            //存入id或者number到2個list中

            //stmt->id := expr 以前是一直移入 直到 id := expr head4爲expr要找到前面的id 執行下面的操作
            if (i == 9)
            {
                k = 2;
                temp = headSignStack;
                while (k--)
                {
                    //printf("?%s\n", temp->value);
                    temp = temp->next;
                }
                addheadstr(1, temp->value);
            }
            //factor->id 規則
            else if (i == 19)
            {
                addheadstr(1, headSignStack->value);
            }
            //factor->num
            else if (i == 20)
            {
                addheadstr(0, headSignStack->value);
            }

            popstack(i);
            popSignStack(i);
            if (headSignStack == NULL)
            {
                p2 = (WordAnalysisList*)malloc(sizeof(WordAnalysisList));
                p2->index = g[i][0];
                p2->next = NULL;
                p2->last = NULL;
                headSignStack = tail4 = p2;
            }
            else addCurrentInputWord(g[i][0], 0);

            //第i條規則 左部符號在非終結符中排的位置(如B排66-65=1) 即gt中的j 
            addstack(gt[stackHead->number][g[i][0] - 65]);
            output(2, i);
        }
        else if (act[stackHead->number][j] == 0)
        {

            if (headWAL->index != '$' || (tail4->index != 'A' || tail4->last != NULL))
            {
                printf("\nerror!\n");
                ok = 0;
            }
            else
                output(3, 0);
            break;
        }
    }
}
//規約的產生式有幾個非終結符存入flag中
void noendNumToflag()
{
    int t;
    Stack *pp;
    pp = guiYueOrderhead;
    while (pp)
    {
        pp->haveF = NULL;
        //printf("%d ",pp->number);
        t = pp->number;
        if (t == 2 || t == 19 || t == 20 || t == 6)
        {
            pp->flag = -1;//只有這句用到
        }
        else if (t == 3 || t == 5 || t == 7 || t == 8 || t == 9 || t == 10 || t == 16 || t == 18)
        {
            pp->flag = 1;
        }
        else if (t == 1 || t == 11 || t == 13 || t == 14 || t == 15 || t == 17)
        {
            pp->flag = 2;
        }
        else if (t == 12)
        {
            pp->flag = 3;
        }
        pp = pp->last;
    }
}
//創建leaf節點(傳入一條規約規則)
Tree *creatleaf(Stack *rule)
{
    Tree *p1;
    p1 = (Tree*)malloc(sizeof(Tree));
    p1->number = rule->number;
    //rule19:factor->id rule9: stmt->id := expr
    if (rule->number == 19 || rule->number == 9)
    {
        strcpy(p1->bb, headid->sstr);
        headid = headid->next;
    }
    //rule20:factor->num
    else if (rule->number == 20)
    {
        strcpy(p1->bb, headnum->sstr);
        headnum = headnum->next;
    }
    p1->haveF = NULL;
    p1->child[0] = NULL;
    p1->child[1] = NULL;
    p1->child[2] = NULL;
    p1->child[3] = NULL;
    return p1;
}
Tree *creathaveF(Stack *pp, Tree *child)
{
    Tree *p1;
    p1 = (Tree*)malloc(sizeof(Tree));
    p1->number = pp->number;
    ///*
    if (pp->number == 19 || pp->number == 9)
    {
        strcpy(p1->bb, headid->sstr);
        headid = headid->next;
    }
    else if (pp->number == 20)
    {

        strcpy(p1->bb, headnum->sstr);
        headnum = headnum->next;
    }
    //*/
    p1->child[0] = child;
    p1->child[1] = NULL;
    p1->child[2] = NULL;
    p1->child[3] = NULL;
    p1->haveF = NULL;
    return p1;
}
//爲child的添加一個產生式爲p的haveF
void addhaveF(Tree *child, Stack *p)
{
    int i = 0;
    Tree *node;
    //產生式的haveF存在 說明之前有另外一天產生式以其作爲haveF了 
    //如A->B p:A->D C->A+A 在p找haveF時就是p->haveF =C->A+A存在 
    //
    if (p->haveF)
    {
        node = p->haveF;
        while (node->child[i] && i <= 3)
        {
            i++;
        }
        //尋找一個空 to添加節點
        node->child[i] = child;
    }
    //p:A->B 的haveF沒有找到 child:B->id
    else
    {
        node = creathaveF(p, child);
        p->haveF = node;
    }
}
//從當前的規約順序guiYueOrderhead開始尋找child的haveF
Stack *findhaveF(Stack *start, Tree *child)
{
    Stack *p1;
    p1 = start->last;
    int i = 1;
    int j, k;
    int flag = 0;
    while (p1&&flag == 0)
    {
        //得到當前規約規則產生式左邊的標號在後面產生式右邊佔有j個
        //實際按語法規則 出現 A->B A->B C->A+A 的順序是對的 不會出現 A->B  C->A+A A->B 的順序
        //A->B A->B A->B C->A+A D->A E->DC 那麼第一條A->B的haveF爲D->A (有待研究)
        j = haveF[g[start->number][0] - 65][p1->number];
        if (j>0)
        {
            for (k = 0; k<j&&flag == 0; k++)
            {
                i--;
                if (i == 0)
                {
                    flag = 1;
                    //如 找到p1:A->B child:帶有id的leaf
                    addhaveF(child, p1);
                    guiYueOrderhead = guiYueOrderhead->last;
                    guiYueOrderhead->next = NULL;
                }
            }

        }

        if (flag == 0)
        {
            //中途遇到產生式左邊與當前產生式左邊一樣的
            if (g[p1->number][0] == g[start->number][0])
            {
                i++;
            }
            p1 = p1->last;
        }

    }
    return guiYueOrderhead;
}
//構建語法分析樹:語法樹規約結束 從下往上建
void newGrammarTree()
{
    Stack *ppp;
    Tree *child;
    //guiYueOrderhead一開始處於最底端 要不斷的找他的last
    while (guiYueOrderhead)
    {
        //第一條規約規則 當前guiYueOrderhead_haveF爲root
        if (guiYueOrderhead->number == 1)
        {
            root = guiYueOrderhead->haveF;
            guiYueOrderhead = guiYueOrderhead->last;
        }
        else{
            ppp = guiYueOrderhead;
            //只有終結符的 創建leaf節點
            if (guiYueOrderhead->flag == -1)
            {
                // B->id 創建一個leaf節點 裏面存的是規約index和id的具體值
                child = creatleaf(guiYueOrderhead);
                //B->id 建完leaf節點要讓leaf找到他的haveF,從當前的規約順序guiYueOrderhead開始
                guiYueOrderhead = findhaveF(guiYueOrderhead, child);
            }
            else
            {
                //如果是非終結符 A->B 
                child = guiYueOrderhead->haveF;
                guiYueOrderhead = findhaveF(guiYueOrderhead, child);
            }
        }
        //guiYueOrderhead = guiYueOrderhead->last;
        //guiYueOrderhead->next = NULL;
    }
}
//前序遍歷得到的序列 p1:語法樹root h:節點
Stack *creatGrammarTreePreOrder(Tree *p1, Stack *h)
{
    Stack *pp, *p2;
    pp = (Stack*)malloc(sizeof(Stack));
    pp->number = p1->number;
    if (p1->bb)
        strcpy(pp->bb, p1->bb);
    pp->next = NULL;
    if (h == NULL)
    {
        h = pp;
    }
    else h->next = pp;
    if (p1->child[0])
    {
        p2 = creatGrammarTreePreOrder(p1->child[0], pp);
        if (p1->child[1])
        {
            while (p2)
            {
                pp = p2;
                p2 = p2->next;
            }
            p2 = creatGrammarTreePreOrder(p1->child[1], pp);
            if (p1->child[2])
            {
                while (p2)
                {
                    pp = p2;
                    p2 = p2->next;
                }
                p2 = creatGrammarTreePreOrder(p1->child[2], pp);
                if (p1->child[3])
                {
                    while (p2)
                    {
                        pp = p2;
                        p2 = p2->next;
                    }
                    p2 = creatGrammarTreePreOrder(p1->child[3], pp);
                }
            }
        }
    }

    return h;
}
//具體的語義分析操作
Stack *semanticsAnalysisDetail(Stack *h)
{
    int l1, l2, l3, t1, t, i;
    char str1[128], str2[128];
    Stack *p;
    p = h;
    h = h->next;
    if (p->number == 9)
    {
        h = semanticsAnalysisDetail(h);
        printf("%s=%s\n", p->bb, str);
    }
    //if then
    else if (p->number == 11)
    {
        L++;
        l1 = L;
        L++;
        l2 = L;
        h = semanticsAnalysisDetail(h);//繼續往下
        printf("if (%s) gt L%d\ngt L%d\n", Bool, l2, l1);
        printf("L%d:", l2);
        grammarTreePreorderHead = semanticsAnalysisDetail(h);
        printf("L%d:\n", l1);
    }
    else if (p->number == 12)
    {
        L++;
        l1 = L;
        L++;
        l2 = L;
        L++;
        l3 = L;
        h = semanticsAnalysisDetail(h);
        printf("if (%s) gt L%d\ngt L%d\n", Bool, l2, l3);
        printf("L%d:", l2);
        h = semanticsAnalysisDetail(h);
        printf("gt L%d\n", l1);
        printf("L%d:", l3);
        h = semanticsAnalysisDetail(h);
        printf("L%d:\n", l1);
    }
    else if (p->number == 13)
    {
        L++;
        l1 = L;
        L++;
        l2 = L;
        L++;
        l3 = L;
        printf("\nL%d:", l1);
        h = semanticsAnalysisDetail(h);
        printf("if (%s) gt L%d\ngt L%d\n", Bool, l2, l3);
        printf("L%d:", l2);
        h = semanticsAnalysisDetail(h);
        printf("gt L%d\n", l1);
        printf("L%d:\n", l3);
    }
    else if (p->number == 14)
    {
        h = semanticsAnalysisDetail(h);
        strcpy(Bool, str);
        str[0] = '<';
        str[1] = '\0';
        strcat(Bool, str);
        h = semanticsAnalysisDetail(h);
        strcat(Bool, str);
    }
    //str(全局)存的是addr 
    else if (p->number == 15 || p->number == 17)
    {

        h = semanticsAnalysisDetail(h);
        strcpy(str1, str);
        h = semanticsAnalysisDetail(h);
        strcpy(str2, str);
        T++;
        t1 = T;
        str[0] = 't';
        i = 1;
        while (t1)
        {
            t = t1 % 10;
            t1 = (t1 - t) / 10;
            str[i] = t + 48;
            i++;
        }
        str[i] = '\0';
        if (p->number == 15)
            printf("%s=%s+%s\n", str, str1, str2);
        else printf("%s=%s*%s\n", str, str1, str2);
    }
    //賦值
    else if (p->number == 16 || p->number == 18)
    {
        h = semanticsAnalysisDetail(h);
    }
    else if (p->number == 19 || p->number == 20)
    {
        strcpy(str, p->bb);
    }
    else if (p->number == 1 || p->number == 8)
    {
        h = semanticsAnalysisDetail(h); h = semanticsAnalysisDetail(h);
    }
    else if (p->number == 3 || p->number == 4 || p->number == 5 || p->number == 7 || p->number == 10)
    {
        h = semanticsAnalysisDetail(h);
    }

    return h;

}
//語義分析
void semanticsAnalysis(){
    grammarTreePreorderHead = creatGrammarTreePreOrder(root, grammarTreePreorderHead);
    //該序列遍歷: 相當於自頂向下分析
    while (grammarTreePreorderHead)
    {
        grammarTreePreorderHead = semanticsAnalysisDetail(grammarTreePreorderHead);
    }
}
int main(){
    /*
    讀輸入文件
    */
    FILE *fp;
    if ((fp = fopen("in.txt", "r")) == NULL)
    {
        printf("cannot open the file!\n");
        exit(0);
    }
    /*
    初始化詞法分析
    */
    initMorphology();
    /*
    初始化語法分析表
    */
    initGrammar();
    /*
    將輸出寫文件
    */
    freopen("out.txt", "w", stdout);
    /*
    詞法分析
    */
    char ch;
    printf("詞法分析:\n");
    while (!feof(fp))
    {
        ch = fgetc(fp);
        if (ch == '\n')
            line++;//行號
        if (feof(fp))
            break;
        fseek(fp, -1L, 1);//讀指針退一位 所以傳入的是fp
        if ((ch >= 'a'&&ch <= 'z') || (ch >= 'A'&&ch <= 'Z'))
        {
            keyword(fp);
        }
        else
        {
            if (ch>'0'&&ch <= '9')
            {
                number(fp, 1);
            }
            else if (ch == '0')
            {
                ch = fgetc(fp);
                ch = fgetc(fp);
                if (ch == 'x' || ch == 'X')
                {
                    number36(fp);
                }
                else
                {
                    fseek(fp, -1L, 1);
                    number(fp, 1);
                }
            }
            else
            {
                other(fp);
            }
        }
    }
    addWordNodeEnd();
    printf("\n語法分析:\n");
    grammarAnalysis();
    if (ok){//用於判斷是否有文法錯誤
        printf("\n語義分析:\n");
        noendNumToflag();
        newGrammarTree();
        semanticsAnalysis();
    }
    fclose(stdout);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章