標籤:

怎樣在bison里構造一組語法產生式,使得C語言的結構體聲明變數時不用加上struct關鍵字?

就像在C++語言中那樣,當我們聲明了一個類class MyClass {…}之後,在使用這個類定義對象x時可以直接寫成MyClass x;


瀉藥。在回答你這個問題的時候,我一直在想把這個問題複雜化回答,還是簡單化回答。其實你看到下面知友說的typedef,你就知道這肯定不止與產生式有關了,也是與類型系統有關了。所以,你要做到C中不使用struct,不僅是產生式的問題,更是類型系統的問題。其實在C++的世界上,struct真的與C很不同,如果你以C++的想法來看,你會覺得很正常,因為在C++的類型系統中,struct與class是同等地位,都是聚合體。在編譯器的產生式中,這兩者其實都被一個統一AggrDeclaration代替(你也可以取其它名字),然後讀到這兩個中的任何一個關鍵字都是統一處理,然後至於為什麼C++可以不需要加struct/class,你讀過C++之父Bjarne的《C++語言設計與演化》你就應該知道C++之父說過要把class做成一等公民,與int等類型地位一樣(int類型變數,我相信你不會使用int i ii,當然這也是不對的)。而在編譯器中,也是這樣設計的。所有的類型其實都保存在了TypeDescriptorPool裡面,然後通過TypeDescriptor掃描變數名字,然後進行解析類型,而編譯器其實也是通過isClassDeclaration()來判定是否是class/struct(方法具體實現我就不說了)。而這樣其實也會造成一些問題,如下面的例子:

#include &
using namespace std;
int a;
class a
{
public:
int c;
};

int main()
{
a = 47;
cout &<&< a &<&< endl; return 0; } // Output: 47 #include &
using namespace std;
int a;
class a
{
public:
int c;
};

int main()
{
a x;
x.c = 47;
cout &<&< x.c &<&< endl; return 0; } // Compile Error

你也會發現第一個例子是沒有錯誤的,是int類型的(當然你也可以說,class看來並沒有達到真正意義上的一等公民地位),而如果我們要修改第二個例子,那就是需要加上struct/class關鍵字。是的,你沒有看錯,我用的是斜杠,就是說可以任意一個。在我看到C++編譯器源代碼之前,我也表示很不解為什麼是這樣,當然我看完後覺得是這麼的自然。

#include &
using namespace std;
int a;
class a
{
public:
int c;
};

int main()
{
struct a x; // No Problem
x.c = 47;
cout &<&< x.c &<&< endl; return 0; } // Output: 47 #include &
using namespace std;
int a;
struct a
{
public:
int c;
};

int main()
{
class a x; // No Problem. It is class keyword!
x.c = 47;
cout &<&< x.c &<&< endl; return 0; } // Output: 47

別驚訝,他們就是這麼的等價地位(當然你往a結構體裡面加個方法,你就不能這麼替代了,當然你自己可以嘗試加入了方法以後是怎麼樣的)。所以,如果你要做成C++的這樣不需要struct關鍵字的,類型系統更是關鍵,不僅產生式這麼簡單了。我說的比較散亂,你要的答案基本上也蘊含在我的回答里了。


難道不是一直都用

typedef struct _Fuck

{

} Fuck;

這樣的方法來不加上struct關鍵字嗎


這事和上下文無關文法沒關係,文法解決不了這種和「使用前先聲明」類似的問題,因為這已經是上下文相關了。

這個表達式的語義處理要留在語法制導分析階段完成。具體到您問的這個問題,結構作為一個類型變數是需要綁定在一個類型上的,這依靠一個「類型環境」來完成,「類型環境」是一個記錄了類型變數與類型對應關係的數據結構。

在一般的c編譯器中,變數環境和類型環境都對應著符號表

您可以在文法上分別做兩個產生式,一個用於聲明結構,當遇到這個產生式的時候,擴充類型環境。另外一個用於創建結構,當遇到這個產生式的時候,擴充變數環境


說句題外話, 個人覺得多寫一個struct不費事, 而且代碼更加清晰.


推薦閱讀:

如何自學《C++ Primer》和《Thinking in C++》?
為什麼Delphi的編譯速度如此之快?
對於以中序表達式為主的編程語言,不實現運算符優先順序,統一求值順序(例如從左往右)會是個好主意嗎?

TAG:編程語言 | CC |