1. 程式人生 > >編譯原理及實踐-----詞法分析

編譯原理及實踐-----詞法分析

詞法分析

【實驗目的】

通過設計編制除錯一個具體的詞法分析程式,加深對詞法分析原理的理解。並掌握在對程式設計語言源程式進行掃描過程中將其分解為各類單詞的詞法分析方法。掌握對字元進行靈活處理的方法。 程式開始變得複雜起來,可能是大家目前編過的程式中最複雜的,但相對於以後的程式來說還是簡單的。因此要認真把握這個過渡期的練習。

【實驗內容】

編制一個讀單詞過程,從輸入的源程式中,識別出各個具有獨立意義的單詞,即基本保留字、識別符號、常數、運算子、分隔符五大類。並依次輸出各個單詞的內部編碼及單詞符號自身值。(遇到錯誤時可顯示“Error”,然後跳過錯誤部分繼續顯示) 程式要求: 程式輸入/輸出示例: 如源程式為C語言。輸入如下一段:

main()
{
int  a,b;
a = 10;
  	b = a + 20;
}

要求輸出如下圖。 (2,”main”) (5,”(“) (5,”)“) (5,”{“) (1,”int”) (2,”a”) (5,”,”) (2,”b”) (5,”;”) (2,”a”) (4,”=”) (3,”10”) (5,”;”) (2,”b”) (4,”=”) (2,”a”) (4,”+”) (3,”20”) (5,”;”) (5,”)“) 要求:

  • 識別保留字:if、int、for、while、do、return、break、continue;
  • 單詞種別碼為1。
  • 其他的都識別為識別符號;單詞種別碼為2。
  • 常數為無符號整形數;單詞種別碼為3。
  • 運算子包括:+、-、*、/、=、>、<、>=、<=、!= ;單詞種別碼為4。
  • 分隔符包括:,、;、{、}、(、); 單詞種別碼為5。

程式碼C語言版

#include <stdio.h>
#include <ctype.h> 
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#define NULL 0

FILE *fp;
char cbuffer;
char *key[8]={"if","int","for","while","do","return","break","continue"};
char *border[6]={",",";","{","}","(",")"};
char *arithmetic[4]={"+","-","*","/"};
char *relation[6]={"<","<=","=",">",">=","!="};
char *consts[20];
char *label[20];
char *digitproc[20]={"10","20"};   
int constnum=0,labelnum=0;

int search(char searchchar[],int wordtype)
{
     int i=0;
     switch (wordtype) {
     	// 判斷是否為保留字 
       case 1:for (i=0;i<=7;i++)
		  {
		   if (strcmp(key[i],searchchar)==0)    // 比較兩個字串  相等就 回0    
		     return(i+1);            // 返回對應的關鍵字的陣列下標 
	     
		  }
		  
		  // 判斷是否是  2 類識別符號 
       case 2:{for (i=0;i<=5;i++)
		  {
		   if (strcmp(border[i],searchchar)==0)
		      return(i+1);
		  }	       return(0);
	      }
         // 判斷是否是 3 類表示符 
       case 3:{for (i=0;i<=3;i++)
		  {
		   if (strcmp(arithmetic[i],searchchar)==0)
		      {
		      	
		       return(i+1);
		      }
		  }
	      return(0);
	      }
         // 判斷是否是 4類識別符號 
       case 4:{for (i=0;i<=5;i++)
		  {
		   if (strcmp(relation[i],searchchar)==0)
		      {
		       return(i+1);
		      }
		  }
	       return(0);
	      }
   
	      //  判斷無符號無符號整形數 
	    case 5:for (i=0;i<=7;i++)
		  {
		   if (strcmp(digitproc[i],searchchar)==0)
		     return(i+1);
		  }
	      }
      


}


char alphaprocess(char buffer)
{
      int atype=0;
      int i=-1;
      char alphatp[20];
      while ((isalpha(buffer))||(isdigit(buffer)))    // 判斷   如果是英文字母或數字 
	    {
	    alphatp[++i]=buffer;           // 將其讀入字元數組裡面 
	    buffer=fgetc(fp);             //  繼續讀取下一個 
	    }
       alphatp[i+1]='\0';                 //  在後面新增\0     
       if (atype=search(alphatp,1)>0)    // 判斷是否有返回   其  他的都識別為識別符號;單詞種別碼為2
      { 
         printf("(1, “%s”)\n",alphatp);  
      		 } 
      	else
      	{ 
      	 printf("(2, “%s ”)\n",alphatp); 
      	 
      }  
      return(buffer);
}

char digitprocess(char buffer)
{
      int i=-1;
      char digittp[20];
      int dtype;
      while ((isdigit(buffer)))   // 判斷是否是數字 
	    {
	    digittp[++i]=buffer;      // 讀入到 字元數組裡 
	    buffer=fgetc(fp);       // 繼續讀入下一個 
	    }
      digittp[i+1]='\0';                 //  在後面新增\0 
      printf("(3, “%s ”)\n",digittp);      //第三種查詢無符號型整型 
      return(buffer);
}

char otherprocess(char buffer)
{
      int i=-1;
      char othertp[20];
      int otype,otypetp;
      othertp[0]=buffer;           // 存入0位 ( 
      othertp[1]='\0';                  // ( \0 
      if (otype=search(othertp,3))
	 {
	 printf("(4, “%s ”)\n",othertp);
	 buffer=fgetc(fp);
	 goto out;
	 }

      if (otype=search(othertp,4))
	      {
	      buffer=fgetc(fp);
	      othertp[1]=buffer;
	      othertp[2]='\0';
	      if (otypetp=search(othertp,4))      //關係運算 
		 {
		 printf("(4, “%s ”)\n\n",othertp);
		 goto out;
		 }
	      else
		 othertp[1]='\0';
		 printf("(4, “%s ”)\n",othertp);            
		 goto out;
	      }

  
	      if (otype=search(othertp,2))
		 {
		 printf("(5, “%s ”)\n",othertp);
		 buffer=fgetc(fp);
		 goto out;
		 }
	   

	  if ((buffer!='\n')&&(buffer!=' '))
		  printf("",buffer);
	  buffer=fgetc(fp);
out:  
    return(buffer);
}

int main()
{
      if ((fp=fopen("example.c","r"))==NULL)
	 printf("error");
      else
	{
	cbuffer = fgetc(fp);
	while (cbuffer!=EOF)
	 {
	  if (isalpha(cbuffer))
	     cbuffer=alphaprocess(cbuffer);
	  else if (isdigit(cbuffer))
	     cbuffer=digitprocess(cbuffer);
	  else cbuffer=otherprocess(cbuffer);
	  }
	 printf("over\n");
	 getchar();
	 }
}
/*
識別保留字:if、int、for、while、do、return、break、continue;  1
其他的都識別為識別符號;單詞種別碼為   2。
常數為無符號整形數;單詞種別碼為    3。
運算子包括:+、-、*、/、=、>、<、>=、<=、!= ;單詞種別碼為    4。
分隔符包括:,、;、{、}、(、); 單詞種別碼為     5。*/

程式碼JAVA版

import java.io.File;
import java.io.FileReader;

/**

 * 此程式是通過將檔案的字元讀取到字元陣列中去,然後遍歷陣列,將讀取的字元進行
 * 分類並輸出
 *
 *
識別保留字:if、int、for、while、do、return、break、continue;  1
其他的都識別為識別符號;單詞種別碼為   2。
常數為無符號整形數;單詞種別碼為    3。
運算子包括:+、-、*、/、=、>、<、>=、<=、!= ;單詞種別碼為    4。
分隔符包括:,、;、{、}、(、); 單詞種別碼為     5。
 * @author 麗麗超可愛
 *
 */

public class WordAnalyze {
    private String keyWord[] = {"if","int","for","while","do","return","break","continue"};
    private char ch;
    //判斷是否是保留字
    boolean isKey(String str)
    {
        for(int i = 0;i < keyWord.length;i++)
        {
            if(keyWord[i].equals(str))
                return true;
        }
        return false;
    }
    //判斷是否是字母
    boolean isLetter(char letter)
    {
        if((letter >= 'a' && letter <= 'z')||(letter >= 'A' && letter <= 'Z'))
            return true;
        else
            return false;
    }
    //判斷是否是數字
    boolean isDigit(char digit)
    {
        if(digit >= '0' && digit <= '9')
            return true;
        else
            return false;
    }
    
    //詞法分析
    void analyze(char[] chars)
    {
        String arr = "";
        for(int i = 0;i< chars.length;i++) {
            ch = chars[i];
            arr = "";
            if(ch == ' '||ch == '\t'||ch == '\n'||ch == '\r'){}
            else if(isLetter(ch)){
                while(isLetter(ch)||isDigit(ch)){    
                    arr += ch;
                    ch = chars[++i];
                }
                //回退一個字元
                i--;
                if(isKey(arr)){
                    //保留字
                    System.out.println("(1,"+arr+")");
                }
                else{
                    //識別符號
                    System.out.println("(2,"+arr+")");
                }
            }
            else if(isDigit(ch))
            {
                while(isDigit(ch))
                {
                   
                    arr = arr + ch;
                    ch = chars[++i];
                }
                //屬於無符號常數
                System.out.println("(3,"+arr+")");
            }
            else switch(ch){
                //運算子
                case '+':System.out.println("(4,"+ch+")");break;
                case '-':System.out.println("(4,"+ch+")");break;
                case '*':System.out.println("(4,"+ch+")");break;
                case '/':System.out.println("(4,"+ch+")");break;
                //分界符
                case '(':System.out.println("(5,"+ch+")");break;
                case ')':System.out.println("(5,"+ch+")");break;
                case '[':System.out.println("(5,"+ch+")");break;
                case ']':System.out.println("(5,"+ch+")");break;
                case ';':System.out.println("(5,"+ch+")");break;
                case '{':System.out.println("(5,"+ch+")");break;
                case '}':System.out.println("(5,"+ch+")");break;
                //運算子
                case '=':{
                            ch = chars[++i];
                            if(ch == '=')System.out.println("(4,==)");
                            else {
                                System.out.println("(4,=)");
                                i--;
                            }
                         }break;
              
                case '>':{
                            ch = chars[++i];
                            if(ch == '=')System.out.println("(4,>=)");
                            else {
                                System.out.println("(4,>)");
                                i--;
                            }
                         }break;
                case '<':{
                            ch = chars[++i];
                            if(ch == '=')System.out.println("(4,<=)");
                            else {
                                System.out.println("(4,<)");
                                i--;
                            }
                         }break;
                case '!':{
                    ch = chars[++i];
                    if(ch == '=')System.out.println("(4,!=)");
                    else {
                       
                        i--;
                    }
                 }break;
            
            }
        }
    }
    
public static void main(String[] args) throws Exception {
    File file = new File("C:\\Users\\麗麗超可愛\\Desktop\\example.c"); 
    FileReader reader = new FileReader(file); 
    int length = (int) file.length();
    char buf[] = new char[length+1];
    reader.read(buf);
    System.out.println(buf);  //測試
    reader.close();
    new WordAnalyze().analyze(buf);
    
    
}
}