編譯原理的項目
㈠ 請問大家在實際項目中用到過編譯原理嗎
我跟你說,編譯原理太有用了。
我是做手機游戲的,現在做一個游戲引擎。既然是引擎,就需要提供抽象的東西給上層使用。這里,我引入了腳本系統。
這個腳本系統包括一堆我根據實際需求自行設計的指令集,包括基本的輸入輸出,四則運算,系統功能調用,函數聲明,調用等等(其實你要是用過lua或者其他游戲腳本你就知道了。)整個結構包括指令集、編譯器、虛擬機等部分。這樣,引擎提供一些基礎服務,比如繪圖,計算位置等,腳本就可以非常簡單控制游戲。甚至快速構建新游戲。你應該知道QUAKE引擎吧?
這里提供給你一個計算器的小程序,應用了EBNF理論,支持表達式,比如(2+3*6)*4+4,你自己體驗一下它的簡潔和強大。
/*
simple integer arithmetic calculator according to the EBNF
<exp> -> <term>{<addop><term>}
<addop>->+|-
<term>-><factor>{<mulop><factor>}
<mulop> -> *
<factor> -> ( <exp> )| Number
Input a line of text from stdin
Outputs "Error" or the result.
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
char token;/*global token variable*/
/*function prototypes for recursive calls*/
int exp(void);
int term(void);
int factor(void);
void error(void)
{
fprintf(stderr,"Error\n");
exit(1);
}
void match(char expectedToken)
{
if(token==expectedToken)token=getchar();
else error();
}
main()
{
int result;
token = getchar();/*load token with first character for lookahead*/
result = exp();
if(token=='\n')/*check for end of line */
printf("Result = %d\n",result);
else error();/*extraneous cahrs on line*/
return 0;
}
int exp(void)
{
int temp = term();
while((token=='+')||(token=='-'))
switch(token)
{
case '+':
match('+');
temp+=term();
break;
case '-':
match('-');
temp-=term();
break;
}
return temp;
}
int term(void)
{
int temp = factor();
while (token=='*')
{
match('*');
temp*=factor();
}
return temp;
}
int factor(void)
{
int temp;
if(token=='('){
match('(');
temp = exp();
match(')');
}
else if(isdigit(token)){
ungetc(token,stdin);
scanf("%d",&temp);
token = getchar();
}
else error();
return temp;
}
其實編程學到一定程度總是沒有方向了,總是在問學C/C++下一步怎麼學啊,覺得掌握了該語言了雲雲,實際上,你缺少的就是這些軟的東西,缺少的是理論。
編譯原理不是單一的理論,它涵蓋了一個niche,裡面可以學到很多其他知識,比如正則表達式、BNF、EBNF、分析樹、語法樹還有很多運行時環境等知識
這些給你帶來的是非常豐厚的回報。不說多了,學完運行時,你就會加深對C++語言本身的理解。
㈡ 編譯原理 A產生空和B的規約在一個項目集里是規約沖突嗎
如果我們把同心的項目集合合並為一,就可能導致沖突,但是這種沖突不會是移進-規約沖突.因為如果存在這種沖突,則意味著對當前輸入符號a,有一個項目[A→α.,a]要求以A→α進行規約,同時又有另一個項目[B→β.aγ,b]要求把a移進.這兩個項目既然同處於合並之後的項目集中,則意味著在合並前,必有某個c使得[A→α.,a]和[B→β.aγ,c]同處於合並前的某一集合中.然而,這又意味著原來的LR(1)項目集就已經存在移進-規約沖突.從而文法不是LR(1)的,這與假設不符.事實上移進-規約沖突不依賴於搜索符號而只依賴於其心,因此,同心集合的合並不會引起新的移進-規約沖突
㈢ 編譯原理中LR(1) 那個向前搜索符怎麼求的 跪求高手解答 復制粘貼或者答非所問的別來
1、首先第一步就是項目[S』-> . S,],自動生成搜索符],自動生成搜索符],自動生成搜索符,從項目[A->α.Bβ,?]生成項目[B->…,first(β)]。
㈣ 計算機科學與技術中編譯原理簡答題
時間有點久記得不太真切,用通俗語言說,希望題主盡量查閱書籍參考資料自行驗證理解。
1、什麼是移進項目,什麼是規約項目
這個是自頂向下和自下向上分析時候用到的。所謂移進就是不處理,所謂規約就是處理,合並,替換。比如當前符合某個正規式左部,就用這個正規式右部替換左部,稱為規約。兩種操作的目的都是為了分析整體是否符合語法樹。
2、請給出生成C語言語句序列的文法(假定s表示任意一個語句,它為終結符)
關於這個,我感覺你描述的不是很清楚,因為C語言文法包含的正規式還是挺多的,如果單指statement的話,
statement_listà
statement
| statement_list statement
Statementà
| compound_statement
| expression_statement
| selection_statement
| iteration_statement
| jump_statement
再配合上相應的終結符。
3、能用上下文無關文法生成正規集嗎?為什麼?
可以。不過無法保證不含沖突。
4、計算first集和follow集對於構造自頂向下的語法分析器有什麼作用?
可以用來排除沖突。例如移進-移進沖突,移進-規約沖突。
5、是否可能存在這樣一個DFA,它的所有狀態都是接受狀態,包括其實狀態,為什麼?
這個愛莫能助,據我的構想是可以的,但是這樣的DFA最終都會成為單一狀態DFA。
㈤ 編譯原理中,LR(0)文法的項目集規范族的I0,I1,I2,I3…………是怎麼求的~
先舉個例子:
}
將其命名為I1。
其他可類似推出。
㈥ 編譯原理項目集規范族問題GO(I,X)中的X是安什麼順序進行測試的
這個問題本身不太准確。
GO(I,X)是一個轉換函數,它的定義如下:
GO(I,X)中的X是一個文法符號,可以是終結符或非終結符,CLOSURE(J)是J的閉包函數,閉包函數的定義就不多說了。
問題「GO(I,X)中的X是按什麼順序進行測試」,是否可解釋成「X是按出現在產生式中的順序進行測試」
㈦ 編譯原理的發展歷程
在20世紀40年代,由於馮·諾伊曼在存儲-程序計算機方面的先鋒作用,編寫一串代碼或程序已成必要,這樣計算機就可以執行所需的計算。開始時,這些程序都是用機器語言 (machine language )編寫的。機器語言就是表示機器實際操作的數字代碼,例如:
C7 06 0000 0002 表示在IBM PC 上使用的Intel 8x86處理器將數字2移至地址0 0 0 0 (16進制)的指令。
但編寫這樣的代碼是十分費時和乏味的,這種代碼形式很快就被匯編語言(assembly language )代替了。在匯編語言中,都是以符號形式給出指令和存儲地址的。例如,匯編語言指令 MOV X,2 就與前面的機器指令等價(假設符號存儲地址X是0 0 0 0 )。匯編程序(assembler )將匯編語言的符號代碼和存儲地址翻譯成與機器語言相對應的數字代碼。
匯編語言大大提高了編程的速度和准確度,人們至今仍在使用著它,在編碼需要極快的速度和極高的簡潔程度時尤為如此。但是,匯編語言也有許多缺點:編寫起來也不容易,閱讀和理解很難;而且匯編語言的編寫嚴格依賴於特定的機器,所以為一台計算機編寫的代碼在應用於另一台計算機時必須完全重寫。
發展編程技術的下一個重要步驟就是以一個更類似於數學定義或自然語言的簡潔形式來編寫程序的操作,它應與任何機器都無關,而且也可由一個程序翻譯為可執行的代碼。例如,前面的匯編語言代碼可以寫成一個簡潔的與機器無關的形式 x = 2。
在1954年至1957年期間,IBM的John Backus帶領的一個研究小組對FORTRAN語言及其編譯器的開發,使得上面的擔憂不必要了。但是,由於當時處理中所涉及到的大多數程序設計語言的翻譯並不為人所掌握,所以這個項目的成功也伴隨著巨大的辛勞。幾乎與此同時,人們也在開發著第一個編譯器, Noam Chomsky開始了他的自然語言結構的研究。他的發現最終使得編譯器結構異常簡單,甚至還帶有了一些自動化。Chomsky的研究導致了根據語言文法(grammar ,指定其結構的規則)的難易程度以及識別它們所需的演算法來為語言分類。正如現在所稱的-與喬姆斯基分類結構(Chomsky hierarchy )一樣-包括了文法的4個層次:0型、1型、2型和3型文法,且其中的每一個都是其前者的專門化。2型(或上下文無關文法(context-free grammar ))被證明是程序設計語言中最有用的,而且今天它已代表著程序設計語言結構的標准方式。
分析問題( parsing problem ,用於限定上下文無關語言的識別的有效演算法)的研究是在20世紀60年代和70年代,它相當完善地解決了這一問題, 現在它已是編譯理論的一個標准部分。它們與喬姆斯基的3型文法相對應。對它們的研究與喬姆斯基的研究幾乎同時開始,並且引出了表示程序設計語言的單詞(或稱為記號)的符號方式。
人們接著又深化了生成有效的目標代碼的方法,這就是最初的編譯器,它們被一直使用至今。人們通常將其誤稱為優化技術(optimization technique ),但因其從未真正地得到過被優化了的目標代碼而僅僅改進了它的有效性,因此實際上應稱作代碼改進技術(code improvement technique )。
這些程序最初被稱為編譯程序-編譯器,但更確切地應稱為分析程序生成器 (parser generator ),這是因為它們僅僅能夠自動處理編譯的一部分。這些程序中最著名的是 Yacc (yet another compiler- compiler),它是由Steve Johnson在1975年為Unix系統編寫的。
類似地,有窮自動機的研究也發展了另一種稱為掃描程序生成器 (scanner generator )的工具,Lex (與Yacc同時,由Mike Lesk為Unix系統開發的)是這其中的佼佼者。在20世紀70年代後期和80年代早期,大量的項目都關注於編譯器其他部分的生成自動化,這其中就包括代碼生成。這些嘗試並未取得多少成功,這大概是因為操作太復雜而人們又對其不甚了解。
編譯器設計最近的發展包括:首先,編譯器包括了更為復雜的演算法的應用程序,它用於推斷或簡化程序中的信息;這又與更為復雜的程序設計語言(可允許此類分析)的發展結合在一起。其中典型的有用於函數語言編譯的Hindle y - Milner類型檢查的統一演算法。
其次,編譯器已越來越成為基於窗口的交互開發環境(interactive development environment,IDE )的一部 分,它包括了編輯器、鏈接程序、調試程序以及項目管理程序。這樣的IDE的標准並沒有多少, 但是已沿著這一方向對標準的窗口環境進行開發了。