詞法與語法分析 (VC實現)

這兩個星期按下面語法圖封裝了一個詞法與語法的類,因爲水平有限現在傳上來,希望各位高手指正^_^

以下是語法圖:

 頭文件:

struct CIFA            //存儲分析出的詞
{
 CString work;  //分析出的單詞
 int type;  //1 關鍵字,2 標識符,3 數字,4或7 錯誤,5 操作符,6 statement number
 int loca;  //該詞在緩衝的位置
// int value;  //該詞的值
 CIFA * next;    //連接下一單詞
};

class CFenXi 
{
public:
 BOOL GetErrFlag();
 void PrintYuFaMsg(CString &str);
 void YuFaFenXi();
 void PrintCiFaErrMsg(CString& str);
 void CifaFenxi();
 CFenXi();
 virtual ~CFenXi();

 CIFA *m_head;  //詞法分析結果
 CString m_code;  //源程序緩衝

protected:
 BOOL IsRepeat();
 BOOL Expression();
 BOOL KW_VARIABLE();
 BOOL NextWord();
 void NextYuJu();
 int WhichKW(CString str);
 BOOL Condition();
 BOOL Statement();
 BOOL Program();
 BOOL IsRem(CString str);
 BOOL IsKeyWord(CString str);
 BOOL IsString(CString str);
 BOOL KW_FOR();
 BOOL KW_END();
 BOOL KW_NEXT();
 BOOL KW_UNLOOP();
 BOOL KW_IF();
 BOOL KW_REM();
 BOOL KW_GOTO();
 BOOL KW_GOSUB();
 BOOL KW_RETURN();
 BOOL KW_INPUT(int num);
 BOOL KW_PRINT(int num);

 CIFA* cur; //指向當前分析的詞
 char m_keyWord[15][10]; //關鍵字表
 int m_keyWordNum;  //分析的單詞個數
 char m_operor[15][5];  //操作符表
 char m_errMes[35][100];  //錯誤信息表
 int m_errors[50]; //記錄語法錯誤
 int m_errNum;  //記錄語法錯誤個數
 int m_errFlag;  //詞法錯誤標誌(詞法有錯爲非零)
 int m_staNum[50];  //記錄statement number
 int m_stanum; //statement Number  個數
};

 

CPP文件:

CFenXi::CFenXi()
{
 m_errFlag = 0;
 m_head = NULL;

 strcpy(m_keyWord[0],"FOR");
 strcpy(m_keyWord[1],"END");
 strcpy(m_keyWord[2],"NEXT");
 strcpy(m_keyWord[3],"UNLOOP");
 strcpy(m_keyWord[4],"IF");
 strcpy(m_keyWord[5],"REM");
 strcpy(m_keyWord[6],"GOTO");
 strcpy(m_keyWord[7], "GOSUB");
 strcpy(m_keyWord[8],"RETURN");
 strcpy(m_keyWord[9],"INPUT");
 strcpy(m_keyWord[10],"PRINT");
 strcpy(m_keyWord[11],"TO");
 strcpy(m_keyWord[12],"THEN");
 strcpy(m_keyWord[13],"program");
// strcpy(m_keyWord[13],"CR");
 m_keyWordNum = 14;

 strcpy(m_operor[0],"=");
 strcpy(m_operor[1],"-");
 strcpy(m_operor[2],"+");
 strcpy(m_operor[3],"*");
 strcpy(m_operor[4],"/");
 strcpy(m_operor[5],"(");
 strcpy(m_operor[6],")");
 strcpy(m_operor[7],"<");
 strcpy(m_operor[8],">");
 strcpy(m_operor[9],",");
 char temp[2];
 temp[0] = (char)13;
 strcpy(m_operor[10],temp); //m_operor[10]存儲回車

 strcpy(m_errMes[0],"標識符定義錯誤或存在非法字符;標識符定義只能有一個字母打頭,後面跟數字串");
 strcpy(m_errMes[1],"漏了一邊括號");
 strcpy(m_errMes[2],"缺少CR或該語句後存在多餘語句");
 strcpy(m_errMes[3],"缺少statement number");
 strcpy(m_errMes[4],"註釋行有錯");
 strcpy(m_errMes[5],"缺少關鍵字“ program ”");
 strcpy(m_errMes[6],"program與statement間有多餘信息");
 strcpy(m_errMes[7],"缺少statement number");
 strcpy(m_errMes[8],"FOR的結構應爲FOR 標識符 = 標識符或常量 TO 標識符或常量");
 strcpy(m_errMes[9],"END後除了‘CR’外沒有其它字符");
 strcpy(m_errMes[10],"NEXT後只跟一個標識符");
 strcpy(m_errMes[11],"UNLOOP後只跟一個標識符");
 strcpy(m_errMes[12],"IF結構錯誤 正確爲(標識符或常數 <或=或〉標識符或常數)");
 strcpy(m_errMes[13],"REM語句出錯");
 strcpy(m_errMes[14],"GOTO後應跟statement number");
 strcpy(m_errMes[15],"GOSUB後應跟statement number");
 strcpy(m_errMes[16],"statement Number 與另一重複");
 strcpy(m_errMes[17],"INPUT後跟標識符,若有多個(不超過三個)標識符用逗號分開");
 strcpy(m_errMes[18],"PRINT後跟標識符,若有多個(不超過三個)標識符用逗號分開");
 strcpy(m_errMes[19],"variable後應爲 = 表達式 CR");
 strcpy(m_errMes[20],"statement後不能直接換行");
 strcpy(m_errMes[21],"一次語句只能輸入三個數");
 strcpy(m_errMes[22],"PRINT後跟標識符,若有多個(不超過三個)標識符用逗號分開");
 strcpy(m_errMes[23],"statement後只能跟關鍵字或變量");

}

CFenXi::~CFenXi()
{

}
void CFenXi::CifaFenxi()
{//詞法分析
 m_stanum = 0;
 m_errFlag = 0; //出錯標誌初始爲0
 if(m_head)
 {
  CIFA* p;
  CIFA* q;
  p = m_head->next;
  while(p) //當再次運行函數,將上次所佔資源釋放
  {
   q = p;
   p = p->next;
   delete q;
  }
  m_head = NULL;  //表頭清空
 }

 m_head = new CIFA; //帶頭節點的鏈表存儲詞法分析結果
 CString room; //當前分析的詞
 room.Empty();
 CIFA* last = m_head; //記錄表尾
 BOOL m_isKG = TRUE; //判斷是否讀到一個詞
 int m_n;  //記錄詞在緩衝的位置
 int flag = 1;  //0表示字符串,1表示操作符或空格
 for(int i = 0;i<=m_code.GetLength();i++)//分析源代碼
 {
  if(m_isKG) //遇到空格或操作符時的處理
  {
   m_n = i;
   room.Empty();
   m_isKG = FALSE;
  }

  if(i < m_code.GetLength())//當前字符不是m_code的最後一位,則操作
  {
   int tt = m_code.GetAt(i);
   if(tt != ' ' && !(tt>=40&&tt<=45) && tt!=47 && !(tt>=60&&tt<=62) && tt!=13 && tt!=10) 
    //如果不是空格或不是操作符,繼續讀字符
   {
    room += m_code.GetAt(i);
    flag = 0;//將標誌轉成字符串
    continue;
   }
  }
//  CIFA* cur; //存放當前分析的詞
  if(flag == 0)
  {//一個詞讀完,進行處理
   cur = new CIFA;
   cur->work = room;

   int n = 0; //room標識符的類型,1爲非法,2爲數字與字符混合
      //3爲數字,4爲字符,0爲沒定義
   int m; //循環控制標誌
   for(m = 0;m<room.GetLength();m++)//分析當前詞
   {
    if(!((room.GetAt(m)>=65 && room.GetAt(m)<=90) ||
     (room.GetAt(m)>=97 && room.GetAt(m)<=122) ||
     (room.GetAt(m)>=48 && room.GetAt(m)<58)))
    {//遇到非法字符,出錯
     m_errFlag = 1;
     cur->type = 4;
     cur->loca = m_n;
     cur->next = NULL;
     last->next = cur;
     last = cur;
     n=1;
     break; //檢測到非法字符,確定單詞爲非法串,退出循環
    }

    if(room.GetAt(m)>=48 && room.GetAt(m)<58)
    {//判斷是否純數字
     if(n!=1 && (n==0||n==3))
      n = 3;
     if(n!=1 && (n==4||n==2))
      n = 2;//確定該詞爲數字與字符混合
    }
    if((room.GetAt(m)>=65 && room.GetAt(m)<=90) ||
     (room.GetAt(m)>=97 && room.GetAt(m)<=122))
    {///判斷是否純字符
     if(n!=1 && (n==0||n==4))
      n=4;    
     if(n!=1 && (n==3||n==2))
      n = 2;//確定該詞爲數字與字符混合
    }
   }
   if(n == 3)
   {//該詞類型爲數字
    if(last->work == "CR")
    {
     if(IsRepeat())
      cur->type = 7;
     else
      cur->type = 6;
    }
    else
     cur->type = 3;
    cur->loca = m_n;
    cur->next = NULL;
    last->next = cur;
    last = cur;
   }
   if(n == 4)
   {
    if(m==1)//當只有一個字母時爲標識符
    {
     cur->type = 2;
     cur->loca = m_n;
     cur->next = NULL;
     last->next = cur;
     last = cur;
    }
    else//當大於一個字母時爲標識符
    {
     if(IsKeyWord(room))//是否爲關鍵字
     {
      if(IsRem(room))//如果爲 註釋
      {
       BOOL m_yinHao = FALSE;
       CString strRem;
       for(int h = i;;h++)//過濾註釋
       {
        if(m_code[h] == 13)
         break;
        if(m_code[h] == ' ')
         continue;
        else
         strRem += m_code.GetAt(h);
 //       if((m_code[h] == 34&&m_yinHao==FALSE)
 //        m_yinHao = TRUE;
       }
       if(IsString(strRem)) //分析註釋
        cur->type = 1;
       else
       {
        cur->type = 4;
        m_errFlag = 1;
       }
       i = h;
      }
      else
       cur->type = 1;
      cur->loca = m_n;
      cur->next = NULL;
      last->next = cur;
      last = cur;
     }
     else
     {//大於兩個字符的純字母組成的串爲非法串
      cur->type = 4;
      m_errFlag = 1;
      cur->loca = m_n;
      cur->next = NULL;
      last->next = cur;
      last = cur;
     }
    }
   }
   if(n == 2)
   {
    if(room.GetAt(0)>=48 && room.GetAt(0)<58)
    {//不符合標識符定義規則
     m_errFlag = 1;
     cur->type = 4;
     cur->loca = m_n;
     cur->next = NULL;
     last->next = cur;
     last = cur;
    }

    if((room.GetAt(0)>=65 && room.GetAt(0)<=90) ||
     (room.GetAt(0)>=97 && room.GetAt(0)<=122))
    {
     for(m = 1;m<room.GetLength();m++)
     {//標識符定義爲一字符打頭,後面跟數字.不能跟數字以外的符號
      if(room.GetAt(m)<48 || room.GetAt(m)>=58)
       break;  
     }
     if(m<room.GetLength())
     {//不符合標識符定義規則
      m_errFlag = 1;
      cur->type = 4;
      cur->loca = m_n;
      cur->next = NULL;
      last->next = cur;
      last = cur;
     }
     else
     {//標識符
      cur->type = 2;
      cur->loca = m_n;
      cur->next = NULL;
      last->next = cur;
      last = cur;
     }//if
    }//if
   }//for
  }//if

  if(i < m_code.GetLength())//當前字符不是m_code的最後一位,則操作
  {
   flag = 1;  //將標誌轉成操作符
   int t = m_code.GetAt(i);
   if((t>=40&&t<=45) || t==47 || (t>=60&&t<=62) || t==13) 
   {//噹噹前字符爲操作符時
    cur = new CIFA;
    if(t == 13) //如果當前是回車,且上個單詞不是回車,則
     if(last->work != "CR")
     {
      cur->work = "CR";
      cur->type = 1;  //回車爲關鍵字
      i++;
     }
     else
     {//如果連續兩個回車,則過濾
      m_isKG = TRUE;
      continue;
     }

    else
    {
     cur->work = m_code.GetAt(i);
     cur->type = 5; //其他爲操作符
    }
    cur->loca = i;
    cur->next = NULL;
    last->next = cur;
    last = cur;
   }
  }
  m_isKG = TRUE;
 }
}

BOOL CFenXi::IsKeyWord(CString str)
{//判斷是否爲關鍵字
 char *temp; 
// for(int i = 0;i<str.GetLength();i++)
//  temp[i] = str.GetAt(i);
 temp = str.GetBuffer(str.GetLength());
 for(int m = 0;m<m_keyWordNum;m++)
  if(strcmp(temp,m_keyWord[m]) == 0)//兩字符串相等
   return TRUE;
 return FALSE;
}

void CFenXi::PrintCiFaErrMsg(CString &str)
{//打印詞法分析的錯誤信息

 CIFA * p;
 p = m_head->next;
 int num = 0; //錯誤單詞個數
 CString temp;
 str.Empty();
 str.Format("詞法分析");
 str += 13; //回車
 str += 10; //換行
 str += "屬性中1 關鍵字,2 標識符,3 數字,4或7 錯誤,5 操作符,6 statement number";
 str += 13; //回車
 str += 10; //換行
 str += 13; //回車
 str += 10; //換行
 str += "屬性        單詞        ";
 str += 13; //回車
 str += 10; //換行
 while(p)
 {
  temp.Empty();
  switch(p->type)
  {
  case 1:
   temp += '1';//關鍵字
   break;
  case 2:
   temp += '2';//標識符
   break;
  case 3:
   temp += '3';//數字
   break;
  case 4:
   temp += '4';//出錯
   break;
  case 5:
   temp += '5';//操作符
   break;
  case 6:
   temp += '6';//statement number
   break;
  case 7:
   temp += '7';//statement number出現重複
   break;
  }
  temp += "           ";
  temp += p->work;
  if(p->type == 4)
  {
   temp += "     ";
   if(p->work == "REM")
    temp += m_errMes[4];//顯示出錯信息
   else
    temp += m_errMes[0];//顯示出錯信息
   num++;
  }
  if(p->type == 7)
  {
   temp += "     ";
   temp += m_errMes[16];//顯示出錯信息
   num++;
  }
  temp += 13;
  temp += 10;
  str += temp;
  p = p->next;
 }
 str += 13; //回車
 str += 10; //換行
 char a[5];
 itoa(num,a,10); //錯誤個數
 str += "錯誤個數    ";
 str += a;
}

BOOL CFenXi::IsRem(CString str)
{//判斷是否爲註釋行
 if(str.GetLength()>3)
  return FALSE;//不與關鍵字REM匹配放回FALSE
 for(int i = 0;i<str.GetLength();i++)
 {
  if(str.GetAt(i) != m_keyWord[5][i])
   break;
 }
 if(i<str.GetLength())
  return FALSE;//不與關鍵字REM匹配放回FALSE
 return TRUE;//與關鍵字REM匹配放回TRUE
}

BOOL CFenXi::IsString(CString str)
{//分析string
 if(str.GetAt(0) != 34) //判斷第一個字符是否爲 "
  return FALSE;
 else
  if(str.GetAt(str.GetLength()-1) != 34)
   return  FALSE;
 //註釋在兩雙引號內則返回TRUE
 return TRUE;
}

void CFenXi::YuFaFenXi()
{
 Program();
}

BOOL CFenXi::Program()
{//程序分析開始
 cur = m_head->next; //cur獲得的一個分析的單詞
 m_errNum = 0;  //錯誤信息初始爲0
 if(cur->work != "program")
  m_errors[m_errNum++] = 5; //缺少關鍵字“ program ”

 NextWord(); //分析下一單詞

 while(1)
 {
  if(cur->work != "CR")
  {
   NextWord();
   if(m_errNum == 1)
    m_errors[m_errNum++] = 6; //program與statement間有多餘信息
  }
  else
   break;  //遇到statement number時退出
 }

 NextWord();

 while(1)
 {
  if(cur)
  {
   if(Statement()) //分析statement
    return TRUE;  //遇到END返回TRUE
  }
  else
   break;
 }

 return FALSE;
}

BOOL CFenXi::Statement()
{//分析statement
 if(cur->type != 6)
 {
  NextYuJu();
  m_errors[m_errNum++] = 7; //缺少statement number
  NextWord();
  NextWord();
  return FALSE;
 }

 NextWord();

 int flag = 1;
 switch(WhichKW(cur->work))//各個語句分析
 {
 case 0: //"FOR"
  if(!KW_FOR())
  {
   if(cur->work == "CR")
   {
    NextWord();
    m_errors[m_errNum++] = 8; //FOR的結構應爲FOR 標識符 = 標識符或常量 TO 標識符或常量
    return FALSE;
   }
   else
    NextYuJu();
   m_errors[m_errNum++] = 8; //FOR的結構應爲FOR 標識符 = 標識符或常量 TO 標識符或常量
  }
  break;
 case 1: //"END"
  if(!KW_END())
  {
   m_errors[m_errNum++] = 9; //END後除了‘CR’外沒有其它字符
  }
  return TRUE; //END後沒有字符返回真

  break;
 case 2: //"NEXT"
  if(!KW_NEXT())
  {
   if(cur->work == "CR")
   {
    NextWord();
    m_errors[m_errNum++] = 10; //NEXT後只跟一個標識符
    return FALSE;
   }
   else
    NextYuJu();
    m_errors[m_errNum++] = 10; //NEXT後只跟一個標識符
  }
  break;
 case 3: //"UNLOOP"
  if(!KW_UNLOOP())
  {
   if(cur->work == "CR")
   {
    NextWord();
    m_errors[m_errNum++] = 11; //UNLOOP後只跟一個標識符
    return FALSE;
   }
   else
    NextYuJu();
    m_errors[m_errNum++] = 11; //UNLOOP後只跟一個標識符
  }
  break;
 case 4: //"IF"
  if(!KW_IF())
  {
   if(cur->work == "CR")
   {
    NextWord();
    m_errors[m_errNum++] = 12; //IF結構錯誤
    return FALSE;
   }
   else
    NextYuJu();
    m_errors[m_errNum++] = 12; //IF結構錯誤
  }
  break;
 case 5: //"REM"
  if(!KW_REM())
  {
   NextYuJu();
   m_errors[m_errNum++] = 13; //REM出錯
  }
  break;
 case 6: //"GOTO"
  if(!KW_GOTO())
  {
   if(cur->work == "CR")
   {
    NextWord();
    m_errors[m_errNum++] = 14; //GOTO後跟statement number
    return FALSE;
   }
   else
    NextYuJu();
   m_errors[m_errNum++] = 14; //GOTO後跟statement number
  }
  break;
 case 7: //"GOSUB"
  if(!KW_GOSUB())
  {
   if(cur->work == "CR")
   {
    NextWord();
    m_errors[m_errNum++] = 15; //GOSUB後跟statement number
    return FALSE;
   }
   else
    NextYuJu();
   m_errors[m_errNum++] = 15; //GOSUB後跟statement number
  }
  break;
 case 8: //"RETURN"
  if(!KW_RETURN())
   m_errors[m_errNum++] = 16;
  break;
 case 9: //"INPUT"
  if(!KW_INPUT(0))
  {
   if(cur->work == "CR")
   {
    NextWord();
    m_errors[m_errNum++] = 17; //INPUT後跟標識符,若有多個(不超過三個)標識符用逗號分開
    return FALSE;
   }
   else
    NextYuJu();
   m_errors[m_errNum++] = 17; //INPUT後跟標識符,若有多個(不超過三個)標識符用逗號分開
  }
  break;
 case 10: //"PRINT"
  if(!KW_PRINT(0))
  {
   if(cur->work == "CR")
   {
    NextWord();
    m_errors[m_errNum++] = 18; //PRINT後跟標識符,若有多個(不超過三個)標識符用逗號分開
    return FALSE;
   }
   else
    NextYuJu();
   m_errors[m_errNum++] = 18; //PRINT後跟標識符,若有多個(不超過三個)標識符用逗號分開
  }
  break;
 default:
  if(cur->type == 2)
  {
   if(!KW_VARIABLE())
   {
    if(cur->work == "CR")
    {
     NextWord();
     m_errors[m_errNum++] = 19; //variable後應爲 = 表達式 CR
     return FALSE;
    }
    else
     NextYuJu();
    m_errors[m_errNum++] = 19; //variable後應爲 = 表達式 CR
   }
  }
  else
  {
   if(cur->work != "CR")
    NextYuJu();
   else
   {
    NextWord();
    m_errors[m_errNum++] = 20; //statement後不能直接換行
    return FALSE;
   }
   m_errors[m_errNum++] = 23; //statement後只能跟關鍵字或變量
  }
 }

 NextWord();
 if(cur->work != "CR")
 {
  NextYuJu();
  m_errors[m_errNum++] = 2; //缺少CR或該語句後存在多餘語句
  NextWord();
  NextWord();
 }
 else
  NextWord();

 return FALSE;
}

BOOL CFenXi::Condition()
{//IF的判斷條件 
 if(cur->work.GetAt(0) != '(')
  return FALSE;
 NextWord();

 if(!(cur->type == 2 || cur->type == 3))
  return FALSE;
 NextWord();

 if(!(cur->work.GetAt(0) == '<' || cur->work.GetAt(0) == '=' || cur->work.GetAt(0) == '>'))
  return FALSE;
 NextWord();

 if(!(cur->type == 2 || cur->type == 3))
  return FALSE;
 NextWord();

 if(cur->work.GetAt(0) != ')')
  return FALSE;
 return TRUE;
}

int CFenXi::WhichKW(CString str)
{//判斷關鍵字所對應的序號
 for(int i = 0;i<11;i++)
 {
  for(int j = 0;j<str.GetLength();j++)
   if(str.GetAt(j) != m_keyWord[i][j])
    break;
  if(j==str.GetLength())
   return i; //表示相應的關鍵字
 }
 return -1;  //表示是標示符
}

BOOL CFenXi::KW_FOR()//FOR的結構應爲FOR 標識符 = 標識符或常量 TO 標識符或常量 CR
{
 NextWord();
 if(cur->type != 2)//FOR後缺標識符
  return FALSE;
 NextWord();
 if(cur->work.GetAt(0) != '=')//FOR中的 =  有誤
  return FALSE;
 NextWord();
 if(!(cur->type == 2||cur->type == 3)) //標識符出錯
  return FALSE;
 NextWord();
 if(cur->work != "TO")//TO 出錯
  return FALSE;
 NextWord();
 if(!(cur->type == 2||cur->type == 3)) //標識符出錯
  return FALSE;

 return TRUE;
}

BOOL CFenXi::KW_END()//END後除了‘CR’外沒有其它字符
{
 NextWord();
 if(!cur) //爲空則結束
  return TRUE;
 if(cur->work != "CR") //不空又不與CR相符,出錯
  return FALSE;
 if(cur->next) //空又與CR相符,但後面還有字符,出錯
  return FALSE;
 return TRUE;
}

BOOL CFenXi::KW_NEXT()//NEXT後只跟一個標識符
{
 NextWord();
 if(cur->type != 2)
  return FALSE;
 return TRUE;
}

BOOL CFenXi::KW_UNLOOP()//UNLOOP後只跟一個標識符
{
 NextWord();
 if(cur->type != 2)
  return FALSE;
 return TRUE;
}

BOOL CFenXi::KW_IF()//結構 (標識符或常數 <或=或〉標識符或常數)
{
 NextWord();
 if(!Condition())
  return FALSE;
 NextWord();
 if(cur->work != "THEN")
  return FALSE;
 NextWord();
 if(cur->type != 3)
  return FALSE;
 return TRUE;
}

BOOL CFenXi::KW_REM()
{
 return TRUE;
}

BOOL CFenXi::KW_GOTO()//GOTO後跟statement number
{
 NextWord();
 if(cur->type != 3)
  return FALSE;
 return TRUE;
}

BOOL CFenXi::KW_GOSUB()//GOSUB後跟statement number
{
 NextWord();
 if(cur->type != 3)
  return FALSE;
 return TRUE;
}

BOOL CFenXi::KW_INPUT(int num)
{//INPUT後跟標識符,若有多個(不超過三個)標識符用逗號分開
 NextWord();
 if(cur->type != 2) //不是標識符返回FALSE
  return FALSE;
// NextWord();
 if(cur->next->work != "CR")
 {
  NextWord();
  if(cur->work.GetAt(0) != ',')//若有多個逗號分開
   return FALSE;
  else
  {
   if(num < 2)
   {
    if(!KW_INPUT(++num))
     return FALSE;
   }
   else
   {
    NextYuJu();
//    m_errors[m_errNum++] = 21;//一次語句只能輸入三個數 
    return FALSE;
   }
  }
 }
 return TRUE;
}

BOOL CFenXi::KW_RETURN()
{
 return TRUE;
}

BOOL CFenXi::KW_PRINT(int num)
{//PRINT後跟標識符,若有多個(不超過三個)標識符用逗號分開
 NextWord();
 if(cur->type != 2) //不是標識符返回FALSE
  return FALSE;
 if(cur->next->work != "CR")
 {
  NextWord();
  if(cur->work.GetAt(0) != ',')//若有多個逗號分開
   return FALSE;
  else
  {
   if(num < 2)
   {
    if(!KW_PRINT(++num))
     return FALSE;
   }
   else
   {
    NextYuJu();
//    m_errors[m_errNum++] = 21;//一次語句只能輸入三個數 
    return FALSE;
   }
  }
 }
 return TRUE;
}

void CFenXi::PrintYuFaMsg(CString &str)
{
 str.Empty();
 char a[5];
 if(m_errNum == 0)
 {
  str += 13; //回車
  str += 10; //換行
  str += "     源程序語法正確";
  return ;
 }
 str += "語法分析結果:";
 str += 13; //回車
 str += 10; //換行
 for(int i = 1;i<=m_errNum;i++)
 {
  itoa(i,a,10); //錯誤排列
  str += "錯誤";
  str += a;
  str += "   ";
  str += m_errMes[m_errors[i-1]];
  str += 13; //回車
  str += 10; //換行
 }
 str += 13; //回車
 str += 10; //換行
 itoa(m_errNum,a,10); //錯誤個數
 str += "錯誤個數    ";
 str += a;
 
}

void CFenXi::NextYuJu()
{//將指針移到下一語句
 while(1)
 {
  if(!cur->next)
   break;
  if(cur->next->work == "CR")
   break;
  NextWord();
 }
}

BOOL CFenXi::NextWord()
{//指向下一單詞
 if(cur)
 {
  cur = cur->next;
  return TRUE;
 }
 else //當沒有單詞時返回FALSE
  return FALSE;
}

BOOL CFenXi::KW_VARIABLE()
{
 NextWord();
 if(cur->work.GetAt(0) != '=')
  return FALSE;
 NextWord();
 if(!Expression())
  return FALSE;
 return TRUE;
}

BOOL CFenXi::Expression()
{//表達式     

 if(!(cur->type == 2 || cur->type == 3 || cur->work.GetAt(0) == '('))
  return FALSE;//不是變量或數字或因子,返回FALSE
 else
 {
  if(cur->work.GetAt(0) == '(')
  {
   NextWord();
   if(!Expression())//如果因子則判斷裏面是否表達式
    return FALSE;
   if(cur->work.GetAt(0) != ')')
    return FALSE;
   else
   {
    if(cur->next->work == "CR")//語句結束則返回TRUE
     return TRUE;
   }
  }
 }

 if(cur->next->work != "CR")
  NextWord();
 else
  return TRUE;//語句結束則返回TRUE

 if(!(cur->work.GetAt(0) == '+' || cur->work.GetAt(0) == '-'
  || cur->work.GetAt(0) == '*' || cur->work.GetAt(0) == '/'))
  if(cur->work.GetAt(0) != ')')
   return FALSE;//不是以上操作符返回FALSE
  else
   return TRUE;
 NextWord();

 if(!Expression())//遞歸
  return FALSE;

 return TRUE;
}

BOOL CFenXi::GetErrFlag()//得到此法分析時的錯誤標誌
{
 return m_errFlag;
}

BOOL CFenXi::IsRepeat()//statement Number 是否重複出現
{
 char a[10];
 for(int i = 0;i<cur->work.GetLength();i++)
  a[i] = cur->work.GetAt(i);
 a[i] = '/0';

 int t = atoi(a);
 for(int j = 0;j<m_stanum;j++)//查找有沒有重複statement number
 {
  if(t == m_staNum[j])
   break;
 }
 m_staNum[m_stanum++] = t;
 if(j<m_stanum-1)
  return TRUE;
 return FALSE;
}

類留了詞法分析,語法分析,詞法分析報告輸出和語法分析報告輸出幾個接口
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章