天天看點

從0開始的python學習:編譯原理實驗2:詞法分析器1--狀态轉換圖方法實驗二:詞法分析器1–狀态轉換圖方法

繼續先把實驗報告上的先搬上來。目前還停留在簡單粗暴地解決問題的層次,對代碼效率沒有任何的考慮。

實驗二:詞法分析器1–狀态轉換圖方法

實驗目的: 通過編寫一個隻包含部分保留字和單詞符号(見語言子集L)的C語言的掃描器(詞法分析器),掌握編譯器的方法之一—狀态轉換圖法。

實驗要求:

1、該詞法分析器的任務如下:

1)濾掉源程式中的無用成分,如空格;

2)輸出分類記号供文法分析器使用,并産生兩個表格(符号表):常數表和變量表(即辨別符表),分别記錄曾掃描到的變量和常量,表的資料結構和包含内容自行定義;

3)識别非法輸入,并将其标記為“出錯記号”。

2、該詞法分析器的功能:

以在下面段落3中定義的PASCAL語言子集的源程式作為詞法分析程式的輸入,即源程式,源程式段存放在檔案中。詞法分析器打開該檔案後,自檔案頭開始掃描源程式字元,發現符合“單詞”定義的源程式字元串時,将它翻譯成固定長度的單詞内部表示,并查填适當的資訊表(符号表),一旦發現不符合“單詞”定義的源程式字元串時,給出錯誤提示。經過詞法分析後,源程式字元串(源程式的外部表示)被翻譯成具有等長資訊的單詞串(源程式的内部表示),并産生兩個表格:常數表和變量表(即辨別符表),它們分别包含了源程式中的所有常數和所有辨別符。即該詞法分析器可将下面C語言子集L所定義的“單詞”區分開來,識别輸入的源程式代碼中每個“單詞”是關鍵字,還是常量,還是變量,對于變量還要記錄變量的個數,識别不同的變量,如程式段:real xx,y;xx=1;if(xx=1)y=5;要能識别出有2個變量,分别是xx,y,第1次掃描到xx,識别出是(6,0) 第2次、第3次掃描到xx,識别出仍是(6,0);第1次掃描到y,識别出是(6,1) ,第2次掃描到y,識别出仍是(6,1);對于常數采用同樣的識别方法。

3、C語言子集L----保留字不區分大小寫

L={ IF,THEN,ELSE,INT,CHAR,FOR,=,>=,==-,+, /,%,++,", ; }∪{常數}∪{變量,即辨別符},變量隻由字母構成,字母個數小于10。

4、實驗報告要求:

(1)詞法分析器構造原理,單詞符号(記号)的分類編碼表,狀态轉換圖設計繪制寫在實驗報告中;

(2)進行詞法分析器的測試:測試例程(一小段程式)、測試結果與測試結果分析。

5、例子:

本例中單詞符号(記号)的種類:

1、保留字(關鍵字);

2、分隔符;

3、運算符;

4、常數;

5、辨別符

(單詞符号的分類可以自己規定,請在實驗報告中給出分類編碼表)

測試用例

第一段:
for (i=1;i<=100;i++)
	{ printf("%d ", i );  }
over
           
運作詞法分析程式後,顯示結果如下:

for (for,16)

( ((,err)

i (i,51)

= (=,31)

1 (1,41)

; (;,22)

i (i ,51)

<= (<=,err)

100 (100,42)

; (;,22)

i (i ,51)

++ (++,37)

) (),err)

{ ({,err)

Printf (Printf,52)

( ((,err)

" (" ,21)

% (%,36)

d (d,53)

" (" ,21)

, (,err)

i (i,51)

) ( ),err)

; ( ;,22)

} ( },err)

over

常數表中的内容為:1,100

變量表(辨別符表)中的内容為:i,printf,d

更多測試用例

第二段:
{ int n,i,kk;
    printf(“n=?");  scanf("%d",&n);
    for (i=2; i<=kk; i++)
        if(n%i==0) break;
    if(i<n) printf("%d no\n",n);
    else printf("%d yes\n",n);
    return 0;
}
over
           
第三段:
char c;
  int letters=0,space=0,digit=0,other=0;
  printf("\n");
  while((c=getchar())!='\n')
   {
     if (( c>='a' && c<='z' )||( c>='A' && c<='Z') )  letters++;
     else if (c==' ')   space++;
     else if (c>='0' && c<='9')   digit++;
     else   other++;
    }
   printf(letters,space,digit,other);
over
           

實驗代碼:

# -*- coding: UTF-8 -*-
# list.append(obj)   增添對象
# extend 清單
# aList = [123, 'xyz', 'zara', 'abc', 123];
# bList = [2009, 'manni'];
# aList.extend(bList)
# 設定清單
list0 = ['IF', 11, 'THEN', 12, 'ELSE', 13, 'INT', 14, 'CHAR', 15, 'FOR', 16]
list2 = ['=', 21, '>=', 22, "==", 23, '+', 24,  '/', 25, '%', 26, '++', 27, '"', 28, ';', 29]    # 運算符
list4 = []    # 數字  動态添加
list5 = []    # 變量名  動态添加,檢查是否存在
# 分割語句
list_temp = []
# str = 'for (i=1;i<=100;i++)' \
#       '{     printf("%d ", i );' \
#       '}' \
# 測試代碼片,可以寫個讀檔案
str = '{ int n,i,kk;' \
      ' printf("n=?");  scanf("%d",&n); ' \
      ' for (i=2; i<=kk; i++) ' \
      ' if(n%i==0) break; ' \
      ' if(i<n) printf("%d no\n",n);' \
      ' else printf("%d yes\n",n); ' \
      ' return 0; ' \
      '}'
list_temp = str.split()
print list_temp
# 開始從第一個單詞循環
i = 0
sum_1 = 0
j = 0
k = 0
# 開始周遊
for idx in range(len(list_temp)):
    str_new = list_temp[idx]
    i = 0
    while i < len(str_new):
        if 'a' <= str_new[i] <= 'z' or 'A' <= str_new[i] <= 'Z':
            if i != len(str_new)-1:
                end = i + 1
                while end < len(str_new):
                    if 'a' <= str_new[end] <= 'z' or 'A' <= str_new[end] <= 'Z':
                        end = end + 1
                    else:
                        end = end - 1
                        break
                if i != end:
                    tmp = str_new[i:end+1]
                    if tmp.upper() in list0:
                        print tmp, "(", tmp, ",", list0[list0.index(tmp.upper()) + 1], ")"
                    else:
                        if tmp not in list5:
                            list5.append(tmp)
                            list5.append(50 + k)
                            k = k + 1
                            print tmp, "(", tmp, ",", list5[list5.index(tmp) + 1], ")"
                        else:
                            print tmp, "(", tmp, ",", list5[list5.index(tmp) + 1], ")"
                    i = end + 1
                    continue
                else:
                    tmp = str_new[i]
                    if tmp not in list5:
                        list5.append(tmp)
                        list5.append(50 + k)
                        k = k + 1
                        print tmp, "(", tmp, ",", list5[list5.index(tmp) + 1], ")"
                    else:
                        print tmp, "(", tmp, ",", list5[list5.index(tmp) + 1], ")"
                    i = end + 1
                    continue
            else:
                tmp = str_new[i]
                if tmp not in list5:
                    list5.append(tmp)
                    list5.append(50 + k)
                    k = k + 1
                    print tmp, "(", tmp, ",", list5[list5.index(tmp) + 1], ")"
                else:
                    print tmp, "(", tmp, ",", list5[list5.index(tmp) + 1], ")"
                i = i + 1
                continue
        else:
            if '0' <= str_new[i] <= '9':
                sum_1 = 0
                while i < len(str_new):
                    if '0' <= str_new[i] <= '9':
                        sum_1 = sum_1 * 10 + int(str_new[i])
                        i = i + 1;
                    else:
                        num_end = i
                        if sum_1 not in list4:
                            list4.append(sum_1)
                            list4.append(40 + j)
                            j = j + 1
                            print sum_1, "(", sum_1, ",", list4[list4.index(sum_1) + 1], ")"
                        break
                i = num_end-1
            else:
                # = 與 ==
                if str_new[i] == '=':
                    if str_new[i + 1] == '=':
                        print "==", "(", "==", ",", 23, ")"
                        i = i + 1
                    else:
                        print "=", "(", "=", ",", 21, ")"
                else:
                    # < 與 <=
                    if str_new[i] == '>':
                        if str_new[i + 1] == '=':
                            print ">=", "(", ">=", ",", 22, ")"
                            i = i + 1
                        else:
                            print ">", "(", ">", ",", "err", ")"
                    else:
                        # + 與 ++
                        if str_new[i] == '+':
                            if str_new[i + 1] == '+':
                                print "++", "(", "++", ",", 27, ")"
                                i = i + 1
                            else:
                                print "+", "(", "+", ",", 24, ")"
                        else:
                            if str_new[i] == '/':
                                print '/', "(", '/', ",", "25", ")"
                            else:
                                if str_new[i] == '%':
                                    print '%', "(", '%', ",", "26", ")"
                                else:
                                    if str_new[i] == '"':
                                        print '"', "(", '"', ",", "28", ")"
                                    else:
                                        if str_new[i] == ';':
                                            print ';', "(", ";", ",", "29", ")"
                                        else:
                                            # 錯誤判斷,一般就是符号錯誤,最多2個,看下一位'='判斷
                                            if str_new[i] not in list2:
                                                if i != len(str_new) - 1:
                                                    if str_new[i + 1] == '=':
                                                        print str_new[i: i + 2], "(", str_new[i: i + 2], ",", "err", ")"
                                                        i = i + 1
                                                    else:
                                                        print str_new[i], "(", str_new[i], ",", "err", ")"
                                                else:
                                                    print str_new[i], "(", str_new[i], ",", "err", ")"
        i = i + 1
x = 0
print("常數有:")
print list4
while x < len(list4):
    if 2 * x < len(list4):       # 防止越界
        print(list4[2 * x])
    x = x + 1
x = 0
print("變量有:")
print list5
while x < len(list5):
    if 2 * x < len(list5):
        print(list5[2 * x])
    x = x + 1
           
從0開始的python學習:編譯原理實驗2:詞法分析器1--狀态轉換圖方法實驗二:詞法分析器1–狀态轉換圖方法
從0開始的python學習:編譯原理實驗2:詞法分析器1--狀态轉換圖方法實驗二:詞法分析器1–狀态轉換圖方法
從0開始的python學習:編譯原理實驗2:詞法分析器1--狀态轉換圖方法實驗二:詞法分析器1–狀态轉換圖方法

還是照搬了實驗報告,删了些注釋掉的代碼,有空再看看能不能改進。

問題及讨論:

資料可以用詞典來儲存,可以更友善。