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

編譯原理-詞法分析

實驗內容

通過對PL/0詞法分析程式(GETSYM)的分析,並在此基礎上按照附錄A中給出的PL/0語言的語法描述,編寫一個PL/0語言的詞法分析程式。此程式應具有如下功能:
輸入為字串(待進行詞法分析的源程式),輸出為單詞串,即由(單詞、類別)所組成的二元組序列。
有一定檢查錯誤的能力,例如發現2A這類不能作為單詞的字串。

實驗程式碼如下:

# include<iostream>
#include <bits/stdc++.h>
using namespace std;

bool key_words(string s)//關鍵字
{
    static vector<string>
keyVec = { "main", "int", "float", "double", "char", "if", "then","else", "switch", "case", "break", "continue", "while", "do", "for" ,"#include","using","namespace","std","return"}; vector<string>::iterator result = find(keyVec.begin(), keyVec.end(),s); if (result != keyVec.
end()) return true; else return false; } bool ident(string s)//識別符號 { if (!key_words(s))//識別符號不能是關鍵字 { if ((s[0] >= 'a'&&s[0] <= 'z') || (s[0] >= 'A'&&s[0] <= 'Z'))//是字母 { for (int i = 1; i < s.length(); i++) { if
((s[i] >= 'a'&&s[i] <= 'z') || (s[i] >= 'A'&&s[i] <= 'Z') || (s[i] >= '0'&&s[i] <= '9')) continue; else return false; } return true; } return false; } return false; } bool digit(string s)//整數 { if (s[0] >= '0'&&s[0] <= '9') { for (int i = 1; i < s.length(); ++i) if (s[i] >= '0'&&s[i] <= '9') continue; else return false; return true; } return false; } bool points(string s)//小數 { if (s[0] >= '0'&&s[0] <= '9') { for (int i = 1; i < s.length(); ++i) if ((s[i] >= '0'&&s[i] <= '9')||s[i]=='.') continue; else return false; return true; } return false; } bool is_operator(string s)//運算子 { static vector<string> opeVec = { "=","+","-","*","/","<","<=","==","!=", ">",">=",";","(",")","?",":",",","+=","-=" }; vector<string>::iterator result = find(opeVec.begin(), opeVec.end(), s); if (result != opeVec.end()) return true; else return false; } bool is_operator(char c)//運算子 { static vector<char> opeVec = { '=','+','-','*','/','<','>',';','(',')','?',':',',' }; vector<char>::iterator result = find(opeVec.begin(), opeVec.end(), c); if (result != opeVec.end()) return true; else return false; } string result(string s)//根據傳入的引數s產生對應的輸出 { //識別符號 if (ident(s)) return "(識別符號,"+s+")"; //關鍵字 if (key_words(s)) return "(關鍵字,"+s+")"; //整型常量 if (digit(s)) return "(整數,"+s+")"; //小數 if (points(s)) return "(小數,"+s+")"; //運算子 static map<string, string> opeMap; opeMap["="] = "(等號,=)"; opeMap["<"] = "(小於號,<)"; opeMap["<="] = "(小於等於號,<=)"; opeMap["+="] = "(加等於號,+=)"; opeMap["-="] = "(減等於號,-=)"; opeMap["=="] = "(賦值運算子,==)"; opeMap["!="] = "(不等於號,!=)"; opeMap[">"] = "(大於號,>)"; opeMap[">="] = "(大於等於號,>=)"; opeMap[";"] = "(分號,;)"; opeMap["+"] = "(加號,+)"; opeMap["("] = "(左括號,( )"; opeMap["-"] = "(減號,-)"; opeMap[")"] = "(右括號,) )"; opeMap[">"] = "(大於號,>)"; opeMap["*"] = "(星號,*)"; opeMap["?"] = "(問號,?)"; opeMap["/"] = "(除號,/)"; opeMap[":"] = "(冒號,:)"; opeMap[","] = "(逗號,,)"; if (is_operator(s)) return opeMap[s]; return "Error"; } int main() { string file = ("C:\\test.txt"); ifstream input(file); ofstream output("C:\\Result.txt",ofstream::app); //先將testData.txt內容拷貝到Result.txt中 string copy; getline(input, copy, '\0'); cout<< copy << endl;//測試是否正確 //此時input已經指到了檔案尾,為了後面的讀取,需要關閉再開啟 input.close(); input.open(file); output << "原資料:\n"; output << copy; output << "處理後結果:\n"; string str; string words; cout << "處理後結果:\n"; int l=0;//計算行數 while (getline(input, str)) //讀取檔案每一次讀取一行,遇到EOF結束 { l++; //從輸入流中獲取單詞,需要用到輸入流物件,即istringstream istringstream strCin(str); string s; while (strCin >> words) { //關鍵字肯定是單獨作為一個單詞的 if (key_words(words)) { s = result(words); cout <<"Line "<<l<<":"<< s << endl; output <<"Line "<<l<<":"<< s << endl; continue; } //對單詞進行掃描,肯定是識別符號,運算子,逗號分號,數字等等混合在一起的單詞 vector<int> index = {0}; vector<string> mulWords;//將words分解為多個單詞 for (int i = 0; i < words.length(); i++) { //運算子有兩位的,比如"<=",">=","==","!=","-=","+=" if ((i < words.length() - 1) && is_operator(words[i]) && is_operator(words[i + 1])) { //但是要注意只有以上6種兩位運算子,比如+-,))就不是,但是))還是要輸出),) if (string(words.begin() + i, words.begin() + i + 2) == "<=" || string(words.begin() + i, words.begin() + i + 2) == ">=" || string(words.begin() + i, words.begin() + i + 2) == "==" || string(words.begin() + i, words.begin() + i + 2) == "-=" || string(words.begin() + i, words.begin() + i + 2) == "+=" || string(words.begin() + i, words.begin() + i + 2) == "!=") { index.push_back(i); index.push_back(i + 2); ++i; } else if (is_operator(words[i])) { if (find(index.begin(), index.end(), i) == index.end()) index.push_back(i); if (find(index.begin(), index.end(), i + 1) == index.end()) index.push_back(i + 1); } } //逗號,運算子作為分隔 else if (is_operator(words[i])) { if (find(index.begin(), index.end(), i) == index.end()) //比如遇到"a,b"這裡下標0和1將a分開,1到2將逗號分開,2到3將b分開 index.push_back(i); if (find(index.begin(), index.end(), i+1) == index.end()) index.push_back(i + 1); } } for (int i = 0; i < index.size()-1; i++) { string rel; //比如遇到"<=",需要提取”<=“ rel=result(string(words.begin() + index[i], words.begin() + index[i + 1])); output <<"Line "<<l<<":"<< rel << endl; cout <<"Line "<<l<<":"<< rel<<endl; } } } output << endl; output.close(); input.close(); system("pause"); return 0; }

實驗結果:

在這裡插入圖片描述