1. 程式人生 > >編譯原理實驗(一)之詞法分析

編譯原理實驗(一)之詞法分析

詞法分析

(1)參考附錄1設計一個簡單語言的詞法分析程式,要求能夠處理註釋、換行回車、部分複合運算子(如>=)。

(2)設計並實現含多條簡單賦值語句的語法分析程式,要求有一定的出錯提示與錯誤恢復功能。    (參考附錄2)

附錄1:

例C源程式段:
main() 
{
    int  A,B,C,D;  /*型別說明*/ 
   A=2; B=4; C=10; D=100;
   while (A<C  and B<D)
   {  
       if (A==1) C=C-1;
      else    while (A<D)
             {A=A+2;}   
   }
}

 

附錄2:

a=2; b=4; 
c=c-1;
area=3.14*a*a;
s= 2*3.1416*r*(h+r);

實驗程式碼

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace WordPicker {
    /// <summary>
    /// 詞
    /// </summary>
    struct Word {
        public int typeNum;
        public string word;
        public override string ToString() {
            return "(" + typeNum + "," + word + ")";
        }
        public string ToShow() {
            return typeNum + "," + word;
        }
    }

    class WordPicker {
      
        string input = "";
        int input_index = 0;
        char character;
        /// <summary>
        /// 關鍵字表
        /// </summary>
        string[] keyWordTable = {
            "auto","break","case", "char","const",
            "continue","default","do","double",
            "else","enum","extern","float","for",
            "goto","if", "int","long", "register",
            "return","short","signed","sizeof","static",
            "struct","switch","typedef","union","unsigned",
            "void","volatile","while"};
        /// <summary>
        /// 操作符表
        /// </summary>
        string[] operatorTable = {
            "{","}","(",")","[","]","->",".",
            "++","--",
            "&&","||","!",
            "~","&","|","^",
            "+","-","*","%","/",
            "<<",">>",
            "<",">",">=","<=",
            "==","!=","?",":",",",";",
            "=","+=","-=","*=","/=","%=",
            "&=","^=","|=",">>=","<<="
        };

        string[] operatorSort = null;
        int wordTypeNumber;    //變數名型別
        int numberTypeNumber;  //數值型別
        int charTypeNumber;    //字元型別
        int stringTypeNumber;    //字串型別
        int endTypeNumber = -1;  //結束符型別
        int errorTypeNumber = -1;  //出錯型別
        int noDefine = -3;      //未定義型別
       // char endChar = '#';
        char nullChar = '\0';

        public WordPicker() {
            wordTypeNumber = keyWordTable.Length;
            numberTypeNumber = keyWordTable.Length + 1;
            charTypeNumber = keyWordTable.Length + 2;
            stringTypeNumber = keyWordTable.Length + 3;

            operatorSort = new string[operatorTable.Length];
            Array.Copy(operatorTable, operatorSort, operatorTable.Length);
            Array.Sort(operatorSort);
            Array.Reverse(operatorSort);
        }

        static void Main(string[] args) {

            WordPicker p = new WordPicker();

            int over = 1;
            string file = "text.txt";
            p.input = File.ReadAllText(file);
            StreamWriter sw =new StreamWriter("result.txt");
            while(over > p.errorTypeNumber ) {
                Word w = p.scanner();
                if(w.typeNum < p.errorTypeNumber) {
                    Console.WriteLine(w);
                    sw.WriteLine(w.ToShow());
                }
                over = w.typeNum;
            }
            sw.Flush();
            sw.Close();
            Console.ReadKey();
        }

        /// <summary>
        /// 讀詞
        /// </summary>
        /// <returns></returns>
        Word scanner() {
            Word myWord;
            myWord.typeNum = -1;
            myWord.word = "";
            read();
            readValidChar();
            //識別符號
            if(char.IsLetter(character)) {
                readWord(ref myWord);
            }//數值
            else if(char.IsDigit(character)) {
                readDigit(ref myWord);
            }//字元常量
            else if(character == '\'') {
                readConstChar(ref myWord);
            }//字串
            else if(character == '\"') {
                readConstString(ref myWord);
            }/*//結束符
            else if(character == endChar) {
                myWord.word = "" + endChar;
                myWord.typeNum = endTypeNumber;
            }*///空值
            else if(character == nullChar) {
                myWord.word = "null";
                myWord.typeNum = errorTypeNumber;
            }//其他字元
            else {
                readOtherChar(ref myWord);
            }
            return myWord;

        }
        /// <summary>
        /// 識別符號
        /// </summary>
        /// <param name="myWord"></param>
        private void readWord(ref Word myWord) {
            while(char.IsLetter(character) || char.IsDigit(character)) {
                myWord.word += character;
                read();
            }
            retract();
            myWord.typeNum = getKeyTypeNumber(myWord.word);

        }
        /// <summary>
        /// 其他字元
        /// </summary>
        /// <param name="myWord"></param>
        private void readOtherChar(ref Word myWord) {
            string s = "" + character;
            for(int i = 0; i < 2; i++) {
                read();
                if(character == nullChar) {
                    break;
                }
                s += character;
            }
            foreach(string op in operatorSort) {
                if(s.StartsWith(op)) {
                    input_index -= s.Length - op.Length;
                    s = op;
                    break;
                }
            }
            myWord.word = s;
            myWord.typeNum = getOperatorTypeNumber(myWord.word);
        }



        /// <summary>
        /// 識別數字常量
        /// </summary>
        /// <param name="myWord"></param>
        private void readDigit(ref Word myWord) {
            while(char.IsDigit(character)) {
                myWord.word += character;
                read();
            }
            if(character == '.') {
                myWord.word += character;
                read();
                while(char.IsDigit(character)) {
                    myWord.word += character;
                    read();
                }
            }
            retract();
            myWord.typeNum = numberTypeNumber;
            // return myWord;
        }

        /// <summary>
        /// 識別字符常量
        /// </summary>
        /// <param name="myWord"></param>
        private void readConstChar(ref Word myWord) {
            // myWord.word = "" + character;
            read();
            //讀取直到'\''結束
            while(character != '\'') {
                myWord.word += character;
                read();
                //讀到空字元或結束字元
                if(character == nullChar /*|| character == endChar*/|| char.IsControl(character)) {
                   /* if(character == endChar) {
                        myWord.word +=endChar;
                    } */                                   
                    myWord.typeNum = errorTypeNumber;
                    return;
                }
            }
            // myWord.word += character;
            Match r = Regex.Match(myWord.word, "^(\\\\([0-7]{1,3}|x[0-9a-fA-F]+|[abfnrtv\\\\\'\"?])|[^\\\\])$");
            //轉義字元模式匹配
            if(!r.Success) {
                myWord.typeNum = errorTypeNumber;
                return;
            }
            myWord.typeNum = charTypeNumber;
        }
        /// <summary>
        /// 識別常量字串
        /// </summary>
        /// <param name="myWord"></param>
        private void readConstString(ref Word myWord) {
            // myWord.word = "" + character;
            read();
            while(character != '\"') {
                myWord.word += character;
                read();
                //讀到空字元或結束字元
                if(character == nullChar|| char.IsControl(character)) {
                  // myWord.word += "0";
                   myWord.typeNum = errorTypeNumber;
                    return;
                }
            }
            // myWord.word += character;

            //轉義字元模式匹配
            if(!isLegalString(myWord.word)) {
                myWord.typeNum = errorTypeNumber;
                return;
            }
            myWord.typeNum = stringTypeNumber;
        }

        /// <summary>
        /// 合法字串書寫
        /// </summary>
        /// <param name="word"></param>
        /// <returns></returns>
        private bool isLegalString(string word) {

            int i = 0;
            while(i < word.Length) {
                if(word[i] == '\\') {
                    if(++i == word.Length)
                        return false;
                    foreach(char c in translateChar) {
                        if(c == word[i]) {
                            goto aLabel;
                        }
                    }
                    return false;
                }
            aLabel:
                i++;
            }

            return true;
        }

        const string translateChar = "abfnrtv\\\'\"?";
        const string realChar = "\a\b\f\n\r\t\v\\\'\"?";
        /// <summary>
        /// 轉換為真實字串
        /// </summary>
        /// <param name="word"></param>
        /// <returns></returns>
        private string toRealString(string word) {
            string res = "";
            int index;
            for(int i = 0; i < word.Length; i++) {
                if(word[i] == '\\') {
                    if(++i == word.Length)
                       throw new Exception("字串以\\結尾異常");

                    index = translateChar.IndexOf(word[i]);
                    if(index == -1)
                        throw new Exception("\\"+ word[i] + "解析異常");
                    res += realChar[index];                   
                }
                else {
                    res += word[i];
                }
            }
            return res;
        }
        /// <summary>
        /// 讀一個字元
        /// </summary>
        void read() {
            if(input.Length <= input_index) {
                character = '\0';
            }
            else
                character = input[input_index++];
        }
        /// <summary>
        /// 去除無效字元
        /// </summary>
        void readValidChar() {

            while(char.IsWhiteSpace(character)) {
                if(input.Length <= input_index) {
                    character = '\0';
                    return;
                }
                character = input[input_index++];
            }
            //判斷註釋
            if(character == '/'&& input.Length > input_index+1) {
                ignoreNote();
            }
        }

        private void ignoreNote() {
           
            //註釋‘//’
            if(input[input_index] == '/') {
                input_index++;
                do {
                    if(input.Length <= input_index) {
                        character = '\0';
                        return;
                    }
                    character = input[input_index++];
                } while('\n' != character);
                read();
                readValidChar();
            }//註釋‘/*。。。*/’
            else if(input[input_index] == '*') {
                input_index++;
                while(true) {
                    if(input.Length <= input_index) {
                        character = '\0';
                        return;
                    }
                    character = input[input_index++];
                    if('*' == character && input.Length >= input_index + 1 && '/' == input[input_index]) {
                        input_index++;
                        read();
                        readValidChar();
                        return;
                    }

                }
            }
        }
       
        /// <summary>
        /// 獲取關鍵字編碼
        /// </summary>
        /// <returns></returns>
        int getKeyTypeNumber(string s) {
            for(int i = 0; i < keyWordTable.Length; i++) {
                if(keyWordTable[i] == s) {
                    return i;
                }
            }

            return keyWordTable.Length;
        }

        int getOperatorTypeNumber(string s) {
            int start = 100;
            for(int i = 0; i < operatorTable.Length; i++) {
                if(operatorTable[i] == s) {
                    return start + i;
                }
            }
            return noDefine;
        }
        void retract() {
            input_index--;
        }

    }
}

輸入檔案:

int main(){	
 // int x=9; //int a=c;            
 // if (x>0.123)  
 ///* foolish abc  */x=2*x+1/3;// int c=0;
//int b=10;	
 /*while(b!=0){
	b--;
}*/
 /* do{
	  int /*fdfd* / a=2.1;
  }while(!1);*/
  int ab;
  int a>>=ab;
  a=ab+-a;
  return 0;
}
 //
# 

輸出: