編譯原理實驗(一)之詞法分析
阿新 • • 發佈:2019-01-13
詞法分析
(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;
}
//
#
輸出: