根據狀態轉換圖手工構造詞法分析程序


編制一個讀單詞過程,源程序為一個文件,讀取該文件,識別出各個具有獨立意義的單詞,即基本保留字、標識符、常數、運算符、界符五大類。並依次輸出各個單詞的內部編碼及單詞符號自身值

單詞的內部編碼如下:

1、保留字:if、int、for、while、do、return、break、continue;單詞種別碼為1;

2、標識符:除保留字外的以字母開頭,后跟字母、數字的字符序列;單詞種別碼為2;

3、常數為無符號整形數;單詞種別碼為3;

4、運算符包括:+、-、*、/、=;單詞種別碼為4;

5、分隔符包括:,、;、{、}、(、); 單詞種別碼為5。

 

 

1、詞法分析器的功能和輸出格式

詞法分析器的功能是輸入源程序,輸出單詞符號。詞法分析器的單詞符號常常表示成以下的二元式(單詞種別碼,單詞符號的屬性值)。本實驗中,采用的是一類符號一種種別碼的方式。

2、各類單詞的文法

<標識符>→<字母><字母數字串>

<字母數字串>→<字母><字母數字串>|<數字><字母數字串>|ε

<無符號整數>→<數字>|<數字><無符號整數>

<運算符>→ + | - | * | / | =

<界符>→ , | ; | ( | ) | { | }

 

#include <iostream>

#include <fstream>

#include <string>

using namespace std;

/* 各種變量的定義 */

string keywords[36] = { "char", "short", "int", "unsigned", "long", "float", "double",

"struct", "union", "void", "enum", "const", "typedef", "auto",

"static", "break", "case", "continue", "default", "do", "else",

"for", "if", "return", "switch", "while", "sizeof", "printf",

"FILE", "fopen", "NULL", "fclose", "exit", "read", "close",

"fprintf" };

char delimiters[] = { '[', ']', '(', ')', '{', '}', '\'', '\"', ',', ';', ':' };

char operators[5] = { '+', '-', '*', '/', '=' };

ifstream infile; /* 輸入文件 */

ofstream outfile; /* 輸出文件 */

char buffer1[64]; /* 緩沖數組 1*/

char buffer2[64]; /* 緩沖數組 2*/

char *pointer; /* 掃描指針 */

/* 各種函數的聲明 */

bool isChar(char c);/* 是否是字母 */

bool isDigit(char c);/* 是否是 0-9*/

bool isUnderline(char c);/* 是否是下划線 */

bool isEnter(char c);/* 是否是換行 */

bool isDelimiter(char c);/* 是否是界符 */

bool isOperator(char c);/* 是否是運算符 */

int getLength(char *s);/* 求一個字符串的長度 */

bool isIdentifier(char *s);/* 是否是標識符 */

bool isNumber(char *s);/* 是否為數字 */

bool isKeyword(string s);/* 是否是關鍵字 */

char getChar();/* 實現雙緩沖掃描文件 */

void write(string str1, string str2);/* 寫入文件,並且在屏幕上打印 */

/* 程序入口: main 函數 */

int main()

{

    char cc = '\0';

    string str = "";

    pointer = buffer1;

    buffer1[63] = buffer2[63] = -1; // 數組尾數值為 -1

    infile.open("in.txt", ios::binary);// 二進制文件 outfile.open ("out.txt",ios::trunc);// 再次寫入覆蓋文件已有內容

    for (int i = 0; i <= 62; i++)

        buffer1[i] = infile.get();// 將文件中字符放入第一緩沖區

    for (;;)

    {

        str = "";

        cc = getChar();

        str += cc;

    AAA: if (isDelimiter(cc))/* 是否是界符 */

    {

             write(" 分隔符 ", str);

    }

         else if (isOperator(cc))/* 是否是操作符 */

         {

                 write(" 運算符 ", str);

         }

         else if (isEnter(cc))/* 是否是換行符 */

         {

             write(" 換行 ", "\\n");

         }

         else if (isUnderline(cc) || isChar(cc))/* 是否是標識符 */

         {

             for (;;)

             {

                 cc = getChar();

                 if (!(isChar(cc) || isDigit(cc) || isUnderline(cc)))

                 {

                     if (isKeyword(str))

                     {

                         write(" 保留字 ", str);

                     }

                     else{

                         write(" 標識符 ", str);

                     }

                     str = cc;

                     goto AAA;

                 }

                 str += cc;

             }

         }

         else if (isDigit(cc))/* 是否是數字 */

         {

             for (;;)

             {

                 cc = getChar();

                 if (!(isDigit(cc)) && cc != '.')

                 {

                     write(" 常數 ", str);

                     str = cc;

                     goto AAA;

                 }

                 str += cc;

             }

         }

    }

    return 0;

}

/**********************************************************************/

/* 雙緩沖掃描文件 */

char getChar()

{

    if (*pointer == -1) /* 當前指針在緩沖區(不知是那個緩沖區)末尾 */

    {

        if (pointer == buffer1 + 63)/* 在第一 buffer 尾,向第二 buffer 讀入數據 */

        {

            for (int i = 0; i <= 62; i++)

            {

                buffer2[i] = infile.get();

            }

            pointer = buffer2;

            return getChar();

        }

        else if (pointer == buffer2 + 63)/* 在第二 buffer 尾,向第一 buffer 讀入數據 */

        {

            for (int i = 0; i <= 62; i++)

            {

                buffer1[i] = infile.get();

            }

            pointer = buffer1;

            return getChar();

        }

        else/* 在不是 buffer 尾的位置讀到了 EOF, 說明完成了分析 */

        {

            infile.close();

            outfile.close();

            ofstream out;

            cout << "\n\n\t 詞法分析完畢! " << endl;

            system("pause");

            exit(-1);

        }

    }

    return *pointer++;

}

/* 是否是字母 */

bool isChar(char c)

{

    if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))

    {

        return true;

    }

    else

    {

        return false;

    }

}

/* 是否是 0-9*/

bool isDigit(char c)

{

    if (c >= '0' && c <= '9')

    {

        return true;

    }

    else

    {

        return false;

    }

}

/* 是否是下划線 */

bool isUnderline(char c)

{

    if (c == '_')

    {

        return true;

    }

    else

    {

        return false;

    }

}

/* 是否是換行 */

bool isEnter(char c)

{

    if (c == '\n')

    {

        return true;

    }

    else

    {

        return false;

    }

}

/* 是否是界符 */

bool isDelimiter(char c)

{

    for (int i = 0; i<10; i++)

    {

        if (c == delimiters[i])

        {

            return true;

        }

    }

    return false;

}

/* 是否是運算符 */

bool isOperator(char c)

{

    for (int i = 0; i<5; i++)

    {

        if (c == operators[i])

        {

            return true;

        }

    }

    return false;

}

/* 求一個字符串的長度 */

int getLength(char *s)

{

    int len = 0;

    for (int i = 0;; i++)

    {

        if (s[i] != '\0')

        {

            len++;

        }

        else

        {

            return len;

        }

    }

}

/* 是否是標識符 */

bool isIdentifier(char *s)

{

    int len = getLength(s);

    if (isChar(s[0]) || isUnderline(s[0]))

    {

        for (int i = 1; i<len; i++)

        {

            if (!(isDigit(s[i]) || isDigit(s[i]) || isUnderline(s[i])))

            {

                return false;

            }

        }

        return true;

    }

    else

    {

        return false;

    }

}

/* 是否為數字 */

bool isNumber(char *s)

{

    int len = getLength(s);

    if (s[0] >= 1 && s[0] <= 9)

    {

        for (int i = 0; i<len; i++)

        {

            if (!isDigit(s[i]) && s[i] != '.')

            {

                return false;

            }

        }

        return true;

    }

    else

    {

        return false;

    }

}

/* 是否是關鍵字 */

bool isKeyword(string s)

{

    for (int i = 0; i<keywords->length(); i++)

    {

        if (s == keywords[i])

        {

            return true;

        }

    }

    return false;

}

/* 寫入文件,並且在屏幕上打印 */

void write(string str1, string str2)

{

    cout << str1 << " " << str2 << endl;

    outfile << "[ <" << str1 << "> : \"" << str2 << "\" ]" << endl;

}

  1. 實驗結果

  1. 個人體會

    這個實驗讓我認識到了詞法掃描器的構建過程,以及如何用C++實現。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM