LCC編譯器的源程式分析 39 goto語句

2021-08-22 09:22:21 字數 1732 閱讀 2366

在現代設計的程式裡,很少再用到

goto

語句了。雖然使用

goto

語句是比較高效,但它使程式也會得非常難懂,非常難維護,比較容易出錯,所以很少使用

goto

語句的。

goto

語句為無條件跳轉語句,它的一般形式為:

goto 標號;

在lcc裡的是用下面的**來處理:

#001case goto:

#002 walk(null, 0, 0);

#003 definept(null);

#004 t = gettok();

#005 if (t == id)

#006

#016 use(p, src);

#017 branch(p->u.l.label);

#018 t = gettok();

#019 }

#020 else

#021 error("missing label in goto/n"); expect(';');

#022 break; 第

2行復位所有分配的記憶體。 第

3行定義執行點。 第

4行獲取下乙個記號。 第

5行判斷

goto

語句後面是否標號變數。如果是標號變數,就跳到第

6行到第

19行裡處理。否則就在第

21行裡提示出錯。 第

7行裡查詢標號是否已經定義。 第

9行是當標號還沒有定義時,就把這個標號安裝到符號表裡。這是在第

9行到第

15行裡處理。 第

17行是生成跳轉到標號的**。

下面再來分析標號語句是怎麼樣定義的,如下:

#001case id:

#002 if (getchr() == ':')

#003 第

2行就判斷乙個

id識別符號是否標號變數,如果在乙個

id後面緊跟著乙個冒號,就是表示宣告了乙個標號變數,所以在第

4行裡呼叫函式

stmtlabel

來處理標號。 第

5行是處理標號後面的語句。

下面來分析函式

stmtlabel:

#001static void stmtlabel(void)

#002

#012

#013if (p->defined)

#014 error("redefinition of label `%s' previously defined at %w/n", p->name, &p->src);

#015

#016p->defined = 1;

#017definelab(p->u.l.label);

#018t = gettok();

#019expect(':');

#020} 第

3行是查詢這個標號是否定義。 第

5行判斷這個標號是否定義,如果沒有定義就新增到符號表。 第

7行是儲存到符號表。 第

8行到第

10行都是設定標號的屬性。 第

13行當重複定義標號時,提示出錯。 第

16行設定這個標號已經定義。 第

17行定義乙個標號。 第

18行獲取下乙個記號。 第

19行檢查標號後是否冒號。

這樣就可以處理

goto

語句和標號語句了,到這裡就把所有基本的語句分析完成了。

LCC編譯器的源程式分析 12 13

語法分析是比較複雜的處理,下面再來分析乙個例子,它的 如下 typedef unsigned short wchar t typedef wchar t wint t 第一句語句在lcc裡的處理,前面已經解釋清楚,主要生成wchar t儲存符號表裡,並且記錄這個id的型別屬性。那麼第二句是怎麼樣通過...

LCC編譯器的源程式分析 18 19

lcc編譯器的源程式分析 19 全域性函式的定義 函式定義funcdefn處理裡,已經準備好呼叫引數和引數返回,接著就是呼叫全域性函式宣告來處理。如下面的 132 宣告函式。133 cfunc dclglobal sclass,id,ty,pt 134 上面的 是處理函式全域性定義。現在就去就分析d...

LCC編譯器的源程式分析 20 復合語句

在 c語言裡,有一種語句叫做復合語句。它是由 把一些語句括起來的,如下面的例子 在lcc 裡處理這樣的復合語句的函式是 compound 它在上面函式定義函式 funcdefn 是這樣呼叫的 150labels table null,labels 151stmtlabs table null,lab...