導航:首頁 > 源碼編譯 > csdn編譯原理輸入一段文法

csdn編譯原理輸入一段文法

發布時間:2022-12-23 06:47:54

編譯原理, 寫一個簡單文法的詞法/語法分析器有簡單的方法嗎

那就用 lex 和 yacc 寫

不過實驗課程就是讓你手算一次

如果你用工具直接生成了意義不大

② 編譯原理中怎樣寫文法和語言

寫文法:首先要清楚語言集的特徵,即找出其特殊值及通式,然後再按此考慮去寫出文法
寫語言:要先理解推導、句型、句子的概念,語言就是句子的全體。

③ 編譯原理文法

編譯原理文法的概念為:每一種自然語言或者是編程語言都需要文法來描述,文法相當於語言學的語義分析,即分析每一句話所表示的含義,編譯器需要利用文法來完成其語法分析和語義分析。

字母表是元素的非空有窮集合,字母表中的元素稱之為符號,因此,字母表也稱之為符號集。例如C語言中的字母表由字母、數字、關鍵字等組成。

符號串,就是由符號集中的元素組成的序列。例如,給定符號集a、b、c,那麼abc、abb、ac就是由該符號集組成的符號串。一個文法中,含有一個,或多個產生式,產生式,描述了將終結符集合和非終結符集合組合成串的方法。

④ 編譯原理文法分析

改完了,能文法分析出來了!!
大概 跟你說下 你的錯誤吧:
出錯地點:
1.聲明的stack[50]沒有初始化;
2.stack的入棧是錯誤的,按照你的方式,如果原來有TM,再加入T->FN,則M就被擠出來了.(這里很關鍵,你對照我給你改的再看看)
3.s指針在你入棧操作以後並沒有指向棧頂,而是保持了不變,這肯定是有問題的.(傳入push函數的時候直接傳參數s就好了.)
4.if(*s==*p){***}else{}的else的右括弧管轄的范圍 有錯誤

不嫌棄的話,可以去http://blog.csdn.net/fangguanya,我的BLOG,不怎麼充實,呵呵,有這個程序的運行結果的. 謝謝 呵呵.
總之你對照我給你改的再看看吧. 我把我的測試輸出 也給保留了.你好對照點.
(PS.我用的vs2005,用的時候你改下頭申明,其他一樣)

// grammar.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include<iostream>
using namespace std;

char * spush(char *stack,char *pt);
bool analyse(char *p);

void main()
{
//將分析串存放在二維數組中
char input[5][10]={"i+i#",
"i*(i+i)#",
"i*i+i#",
"i+*#",
"+i*i#"};
bool flag; //定義一個布爾型的標記量
for(int h=0;h<5;++h)
{
flag=analyse(input[h]);
if(flag) cout<<"恭喜你!"<<input[h]<<"語法分析成功,合法!"<<endl;
else cout<<"對不起!"<<input[h]<<"語法分析失敗,非法!"<<endl;
}
int aaa;
cin>>aaa;
}
//定義各一將串逆序入棧的函數
char * spush(char *stack,char *pt)
{
int l=0;
//while循環的作用是將指針指向字元串的末尾,然後再由後向前入棧,從而實現逆序
while(*pt!='\0')
{
pt++;
l++;
}

if (*stack == '#')
{
stack++;
}
while(l)
{
pt--;
char cTempIntoStack = (*pt);
*stack=cTempIntoStack;
stack++;
l--;
}
stack--; //由於前面向前加了一位,要返回
////////////////
return stack;
///////////////////////////////////

}

/*LL(1)分析表
i + * ( ) #
E TM +TM
F i (E)
M TM e e
N e *FN e e
T FN FN
*/

//分析函數
bool analyse(char *p){
char analyseTable[5][6][4]={
"TM", "", "", "TM", "", "",
"i", "", "", "(E)", "", "",
"", "+TM", "", "", "e", "e",
"", "e", "*FN", "", "e", "e",
"FN", "", "", "TN", "", ""
};
char *stack = new char[50]; //定義一個棧空間
for (int iStack = 0;iStack<50 ;iStack++)
{
stack[iStack] = 0;
}
char *s=stack; //用指針*s指向棧的起始地址
*s='#'; //將「#」入棧
s++; //指針加1
*s='E'; //將「E」入棧
//下面的while循環實現字元串的詞法分析操作

int count = 0;

while(*s!='#' || *p!='#'){
count++;
char * temp = s;
cout<<"NO."<<count<<endl;
cout<<"STACK"<<endl;
while (*temp != '#')
{
cout<<*temp<<" ";
temp--;
}
cout<<endl;

int x,y;
//若果棧頂數據和分析串的字元匹配,則將符號棧的棧頂數據出棧(即將棧頂指針減1)
if(*s==*p){
cout<<"Before :"<<*s<<endl;
s--;
p++;
cout<<"After :"<<*s<<endl;
}
//當符號棧和分析串的字元不匹配時,查分析表
else {
switch(*s){
case 'E':x=0;break;
case 'F':x=1;break;
case 'M':x=2;break;
case 'N':x=3;break;
case 'T':x=4;break;
default:return false;
}
switch(*p){
case 'i':y=0;break;
case '+':y=1;break;
case '*':y=2;break;
case '(':y=3;break;
case ')':y=4;break;
case '#':y=5;break;
default:return false;
}
//若果對應的為空,則分析串非法,退出
if(analyseTable[x][y][0]=='\0') return false;
//若查表所對應的為'e',則將符號棧的棧頂數據出棧
else if(analyseTable[x][y][0]=='e') s--;
//其它,這時將查表所得的項逆序入符號棧
else {
s=spush(s,analyseTable[x][y]);
}
}
}
return true; //分析成功,返回
}

⑤ 編譯原理 語法

編譯原理不同教材用的表示不太一樣,翻譯也五花八門,我不是很確定你這個活前綴是什麼意思。我按我知道的告訴你,我用「。」表示狀態的位置,你的書上可能通常是一個黑點表示,先要建立文法的狀態集合:
S1:S->。a
S2:S->a。
S3:S->。^
S4:S->^。
S5:S->。(T)
S6:S->(。T)
S7:S->(T。)
S8:S->(T)。
S9:T->。T,S
S10:T->T。,S
S11:T->T,。S
S12:T->T,S。
S13:T->。S
S14:T->S。
歸集狀態,和狀態轉換關系(這應該是要畫成圖的,這里沒法畫。。。)用I表示
I0:S1 S3 S5 S9 S13
輸入a,I0->I1
I1:S2
輸入^,I0->I2
I2:S4
輸入(,I0->I3
I3:S6 S9 S13 S1 S3 S5
歸約S,I0->I4
I4:S14
歸約T,I0->I5
I5:S10
歸約T,I3->I6
I6:S7
輸入),I6->I7
I7:S8
輸入,,I5->I8
I8:S11 S1 S3 S5
歸約S,I8->I9
I9:S12
輸入a,I8->I1
輸入^,I8->I2
輸入(,I8->I3
輸入a,I3->I1
輸入^,I3->I2
輸入(,I3->I3
然後你要建立狀態轉換表,網路不能畫表格。。。,你將就看看( $是結束符啊.還有你的文法沒有開始,即S')
先把題目中的規則編個號:
(1) S->a
(2) S->^
(3) S->(T)
(4) T->T,S
(5) T->S
action goto
狀態集 a ^ ( ) , $ S T
0 s1 s2 s3 14 10
1 acc
2 acc
3 s1
因為沒有S'不知道最終怎麼規約

⑥ 求解編譯原理的一道題:設有文法如下

首先要做這題你要知道判別文法類型
包括四個層次:

0-型文法(無限制文法或短語結構文法)包括所有的文法。該類型的文法能夠產生所有可被圖靈機識別的語言。可被圖靈機識別的語言是指能夠使圖靈機停機的字串,這類語言又被稱為遞歸可枚舉語言。注意遞歸可枚舉語言與遞歸語言的區別,後者是前者的一個真子集,是能夠被一個總停機的圖靈機判定的語言。
1-型文法(上下文相關文法)生成上下文相關語言。這種文法的產生式規則取如 αAβ -> αγβ 一樣的形式。這里的A 是非終結符號,而 α, β 和 γ 是包含非終結符號與終結符號的字串;α, β 可以是空串,但 γ 必須不能是空串;這種文法也可以包含規則 S->ε ,但此時文法的任何產生式規則都不能在右側包含 S 。這種文法規定的語言可以被線性有界非確定圖靈機接受。
2-型文法生成上下文無關語言。這種文法的產生式規則取如 A -> γ 一樣的形式。這里的A 是非終結符號,γ 是包含非終結符號與終結符號的字串。這種文法規定的語言可以被非確定下推自動機接受。上下文無關語言為大多數程序設計語言的語法提供了理論基礎。
3-型文法(正規文法)生成正規語言。這種文法要求產生式的左側只能包含一個非終結符號,產生式的右側只能是空串、一個終結符號或者一個非終結符號後隨一個終結符號;如果所有產生式的右側都不含初始符號 S ,規則 S -> ε 也允許出現。這種文法規定的語言可以被有限狀態自動機接受,也可以通過正則表達式來獲得。正規語言通常用來定義檢索模式或者程序設計語言中的詞法結構。
正規語言類包含於上下文無關語言類,上下文無關語言類包含於上下文相關語言類,上下文相關語言類包含於遞歸可枚舉語言類。這里的包含都是集合的真包含關系,也就是說:存在遞歸可枚舉語言不屬於上下文相關語言類,存在上下文相關語言不屬於上下文無關語言類,存在上下文無關語言不屬於正規語言類。

1)本題應該是--上下文無關文法

句子是產生式在推導時「僅僅有終結符」的任何一步
2)%mm%nn 是一個句子

由於下面一題的圖我等級不夠 不能貼圖 發你郵箱

⑦ 編譯原理

編譯原理):利用編譯程序從源語言編寫的源程序產生目標程序的過程; 用編譯程序產生目標程序的動作。 編譯就是把高級語言變成計算機可以識別的2進制語言,計算機只認識1和0,編譯程序把人們熟悉的語言換成2進制的。

編譯程序把一個源程序翻譯成目標程序的工作過程分為五個階段:詞法分析;語法分析;語義檢查和中間代碼生成

(7)csdn編譯原理輸入一段文法擴展閱讀:

編譯程序的語法分析器以單詞符號作為輸入,分析單詞符號串是否形成符合語法規則的語法單位,如表達式、賦值、循環等,最後看是否構成一個符合要求的程序,按該語言使用的語法規則分析檢查每條語句是否有正確的邏輯結構,程序是最終的一個語法單位。

編譯程序的語法規則可用上下文無關文法來刻畫。語法分析的方法分為兩種:自上而下分析法和自下而上分析法。自上而下就是從文法的開始符號出發,向下推導,推出句子。

而自下而上分析法採用的是移進歸約法,基本思想是:用一個寄存符號的先進後出棧,把輸入符號一個一個地移進棧里,當棧頂形成某個產生式的一個候選式時,即把棧頂的這一部分歸約成該產生式的左鄰符號。

⑧ 編譯原理的文法是什麼

文法是描述語言規則的形式規則。實際上就是用一個四元組G=(VT,VN,S,P)定義的一個推理方式。其中VT是終結符,VN是非終結符,S是開始符號,P是一組產生規則。

⑨ 編譯原理-LL1文法詳細講解

我們知道2型文法( CFG ),它的每個產生式類型都是 α→β ,其中 α ∈ VN , β ∈ (VN∪VT)*。

例如, 一個表達式的文法:

最終推導出 id + (id + id) 的句子,那麼它的推導過程就會構成一顆樹,即 CFG 分析樹:

從分析樹可以看出,我們從文法開始符號起,不斷地利用產生式的右部替換產生式左部的非終結符,最終推導出我們想要的句子。這種方式我們稱為自頂向下分析法。

從文法開始符號起,不斷用非終結符的候選式(即產生式)替換當前句型中的非終結符,最終得到相應的句子。
在每一步推導過程中,我們需要做兩個選擇:

因為一個句型中,可能存在多個非終結符,我們就不確定選擇那一個非終結符進行替換。
對於這種情況,我們就需要做強制規定,每次都選擇句型中第一個非終結符進行替換(或者每次都選擇句型中最後一個非終結符進行替換)。

自頂向下的語法分析採用最左推導方式,即總是選擇每個句型的最左非終結符進行替換。

最終的結果是要推導出一個特定句子(例如 id + (id + id) )。
我們將特定句子看成一個輸入字元串,而每一個非終結符對應一個處理方法,這個處理方法用來匹配輸入字元串的部分,演算法如下:

方法解析:

這種方式稱為遞歸下降分析( Recursive-Descent Parsing ):

當選擇的候選式不正確,就需要回溯( backtracking ),重新選擇候選式,進行下一次嘗試匹配。因為要不斷的回溯,導致分析效率比較低。

這種方式叫做預測分析( Predictive Parsing ):

要實現預測分析,我們必須保證從文法開始符號起,每一個推導過程中,當前句型最左非終結符 A 對於當前輸入字元 a ,只能得到唯一的 A 候選式。

根據上面的解決方法,我們首先想到,如果非終結符 A 的候選式只有一個以終結符 a 開頭候選式不就行了么。
進而我們可以得出,如果一個非終結符 A ,它的候選式都是以終結符開頭,並且這些終結符都各不相同,那麼本身就符合預測分析了。

這就是S_文法,滿足下面兩個條件:

例子:

這就是一個典型的S_文法,它的每一個非終結符遇到任一終結符得到候選式是確定的。如 S -> aA | bAB , 只有遇到終結符 a 和 b 的時候,才能返回 S 的候選式,遇到其他終結符時,直接報錯,匹配不成功。

雖然S_文法可以實現預測分析,但是從它的定義上看,S_文法不支持空產生式(ε產生式),極大地限制了它的應用。

什麼是空產生式(ε產生式)?

例子

這里 A 有了空產生式,那麼 S 的產生式組 S -> aA | bAB ,就可以是 a | bB ,這樣 a , bb , bc 就變成這個文法 G 的新句子了。

根據預測分析的定義,非終結符對於任一終結符得到的產生式是確定的,要麼能獲取唯一的產生式,要麼不匹配直接報錯。

那麼空產生式何時被選擇呢?

由此可以引入非終結符 A 的後繼符號集的概念:
定義: 由文法 G 推導出來的所有句型,可以出現在非終結符 A 後邊的終結符 a 的集合,就是這個非終結符 A 的後繼符號集,記為 FOLLOW(A) 。

因此對於 A -> ε 空產生式,只要遇到非終結符 A 的後繼符號集中的字元,可以選擇這個空產生式。
那麼對於 A -> a 這樣的產生式,只要遇到終結符 a 就可以選擇了。

由此我們引入的產生式可選集概念:
定義: 在進行推導時,選用非終結符 A 一個產生式 A→β 對應的輸入符號的集合,記為 SELECT(A→β)

因為預測分析要求非終結符 A 對於輸入字元 a ,只能得到唯一的 A 候選式。
那麼對於一個文法 G 的所有產生式組,要求有相同左部的產生式,它們的可選集不相交。

在 S_文法基礎上,我們允許有空產生式,但是要做限制:

將上面例子中的文法改造:

但是q_文法的產生式不能是非終結符打頭,這就限制了其應用,因此引入LL(1)文法。

LL(1)文法允許產生式的右部首字元是非終結符,那麼怎麼得到這個產生式可選集。
我們知道對於產生式:

定義: 給定一個文法符號串 α , α 的 串首終結符集 FIRST(α) 被定義為可以從 α 推導出的所有串首終結符構成的集合。

定義已經了解清楚了,那麼該如何求呢?
例如一個文法符號串 BCDe , 其中 B C D 都是非終結符, e 是終結符。

因此對於一個文法符號串 X1X2 … Xn ,求解 串首終結符集 FIRST(X1X2 … Xn) 演算法:

但是這里有一個關鍵點,如何求非終結符的串首終結符集?

因此對於一個非終結符 A , 求解 串首終結符集 FIRST(A) 演算法:

這里大家可能有個疑惑,怎麼能將 FIRST(Bβ) 添加到 FIRST(A) 中,如果問文法符號串 Bβ 中包含非終結符 A ,就產生了循環調用的情況,該怎麼辦?

對於 串首終結符集 ,我想大家疑惑的點就是,串首終結符集到底是針對 文法符號串 的,還是針對 非終結符 的,這個容易弄混。
其實我們應該知道, 非終結符 本身就屬於一個特殊的 文法符號串
而求解 文法符號串 的串首終結符集,其實就是要知道文法符號串中每個字元的串首終結符集:

上面章節我們知道了,對於非終結符 A 的 後繼符號集 :
就是由文法 G 推導出來的所有句型,可以出現在非終結符 A 後邊的終結符的集合,記為 FOLLOW(A) 。

仔細想一下,什麼樣的終結符可以出現在非終結符 A 後面,應該是在產生式中就位於 A 後面的終結符。例如 S -> Aa ,那麼終結符 a 肯定屬於 FOLLOW(A) 。

因此求非終結符 A 的 後繼符號集 演算法:

如果非終結符 A 是產生式結尾,那麼說明這個產生式左部非終結符後面能出現的終結符,也都可以出現在非終結符 A 後面。

我們可以求出 LL(1) 文法中每個產生式可選集:

根據產生式可選集,我們可以構建一個預測分析表,表中的每一行都是一個非終結符,表中的每一列都是一個終結符,包括結束符號 $ ,而表中的值就是產生式。
這樣進行語法推導的時候,非終結符遇到當前輸入字元,就可以從預測分析表中獲取對應的產生式了。

有了預測分析表,我們就可以進行預測分析了,具體流程:

可以這么理解:

我們知道要實現預測分析,要求相同左部的產生式,它們的可選集是不相交。
但是有的文法結構不符合這個要求,要進行改造。

如果相同左部的多個產生式有共同前綴,那麼它們的可選集必然相交。
例如:

那麼如何進行改造呢?
其實很簡單,進行如下轉換:

如此文法的相同左部的產生式,它們的可選集是不相交,符合現預測分析。

這種改造方法稱為 提取公因子演算法

當我們自頂向下的語法分析時,就需要採用最左推導方式。
而這個時候,如果產生式左部和產生式右部首字元一樣(即A→Aα),那麼推導就可能陷入無限循環。
例如:

因此對於:

文法中不能包含這兩種形式,不然最左推導就沒辦法進行。

例如:

它能夠推導出如下:

你會驚奇的發現,它能推導出 b 和 (a)* (即由 0 個 a 或者無數個 a 生成的文法符號串)。其實就可以改造成:

因此消除 直接左遞歸 演算法的一般形式:

例如:

消除間接左遞歸的方法就是直接帶入消除,即

消除間接左遞歸演算法:

這個演算法看起來描述很多,其實理解起來很簡單:

思考 : 我們通過 Ai -> Ajβ 來判斷是不是間接左遞歸,那如果有產生式 Ai -> BAjβ 且 B -> ε ,那麼它是不是間接左遞歸呢?
間接地我們可以推出如果一個產生式 Ai -> αAjβ 且 FIRST(α) 包括空串ε,那麼這個產生式是不是間接左遞歸。

⑩ 編譯原理 文法

構造LR(1)語法分析表,沒有沖突就是了。

閱讀全文

與csdn編譯原理輸入一段文法相關的資料

熱點內容
gz壓縮文件夾 瀏覽:177
字母h從右往左跑的c語言編程 瀏覽:127
安卓手機如何擁有蘋果手機橫條 瀏覽:765
業余編程語言哪個好學 瀏覽:137
按照文件夾分個壓縮 瀏覽:104
航空工業出版社單片機原理及應用 瀏覽:758
如何在電信app上綁定親情號 瀏覽:376
安卓的怎麼用原相機拍月亮 瀏覽:805
配音秀為什麼顯示伺服器去配音了 瀏覽:755
c盤清理壓縮舊文件 瀏覽:325
app怎麼交付 瀏覽:343
圖蟲app怎麼才能轉到金幣 瀏覽:175
如何做徵文app 瀏覽:446
用什麼app管理斐訊 瀏覽:169
安卓如何下載寶可夢劍盾 瀏覽:166
編譯器開發屬於哪個方向 瀏覽:940
megawin單片機 瀏覽:687
以色列加密貨幣監督 瀏覽:909
程序員前端現在怎麼樣 瀏覽:499
伺服器和介面地址ping不通 瀏覽:557