標籤(空格分隔): 未分類前端
本章內容是對本書第3章至第六章中介紹的編譯技術的綜合介紹.web
2.2:給出一個普遍使用的表示方法來描述語法,叫作上下文無關法
或者BNF(Backus-Naur範式)
.api
2.3:面向文法的編譯技術:語法指導翻譯
數組
2.4:語法分析數據結構
2.5:一箇中綴轉後綴的過程app
2.6:詞法分析koa
2.8:構造語法樹ssh
介紹一種用於描述程序設計語言語法的表示方法---"上下文無關法"
或簡稱文法
.被用於組織編譯器前端.函數
Java的if-else
工具
文法
一個上下文無關法(context-free grammar)由4個元素組成:
非終結符號
表示一個終結符號串
的結合.(後面介紹)非終結符號
.根據文法推倒符號串時.首先從開始符號出發,不斷地將某個非終結符號替換爲該非終結符號的某個產生式的體.直到所有爲終結符號.
parsing
的任務是: 接受一個終結符號串做爲輸入,找出從文法的開始符號推倒出該串的方法.
若是不能推倒出,則報告語法錯誤.
主要語法分析方法,在第四章中介紹
語法分析樹
用圖形方法展示了從文法的開始符號推倒出對應語言中的符號串的過程.
parse tree
有如下性質
e
非終結符號A
它的子節點從左至右有X1,X2..XN
,那麼必然有產生式A->X1X2X3..XN
.文法:
須要推倒的語句: 9 - 5 + 2
語法樹:
一個文法的語言的另外一個定義是任何可以由某顆語法分析樹生成的符號串的集合.
爲一個給點的終結符號串構建一顆語法分析樹的過程稱爲對該符號穿進行語法分析
某些語法若是不嚴謹會產生二義性.好比將上述例子的語法改爲
那麼對以前的終結符號串的解釋能夠用兩種語法樹
前者的結果是6, 後者是2
顯然有問題.因此一個好的文法不該該有二義性.
等號的文法:
結合性規則只能做用於同一級別的運算
當具備+
,-
,*
,\
,(
,)
時的文法
factor
不可被分開.term
可能被高優先級的運算符*
和/
分開expr
能夠被任意優先級分開非終結字符
來肯定n個優先級的語法.
從如下代碼能看出如何增長一個優先級.
語法制導翻譯
是經過向一個文法的產生式附加一些規則或程序片斷而獲得的.
看不懂
語法制導定義(syntax-directed definition)
把每一個文法符號和一個屬性集合相關聯,而且把每一個產生式和一組語義規則(semantic rule
)相關聯,這些規則用於計算與該產生式相關聯的屬性值.
註釋語法分析樹
:若是一顆語法分析樹的各個結點上標記了相應的屬性值,那麼這顆語法分析樹就稱爲註釋語法分析樹,簡稱註釋分析樹.
綜合屬性
:若是某個屬性在語法分析樹結點N上的值由N的子節點和N自己的屬性值肯定,那麼這個屬性叫作綜合屬性
5.1.1節將會講述一種繼承屬性
:繼承屬性在某個語法分析樹的結點的值由其自己,兄弟,父節點屬性值決定.
##關於語法制導一個十分不錯的例子
上述例子的語法制導定義具備如下重要性質:
關於樹的遍歷就再也不贅述了
以前上述的語法翻譯的例子將字符串做爲屬性值附加在結點上,從而獲得翻譯結果.
咱們來考慮一種不須要操做字符串的方法,經過運行程序片斷
,逐步生成相同的翻譯結果.
語法分析
是決定如何使用一個文法生成一個終結符號串的過程.
遞歸降低
的語法分析方法,該方法用於語法分析和實現語法制導翻譯器.
Yacc
的工具直接根據方案生成一個翻譯器.對於任何上下文無關法,都能構造出一個O(n^3)的語法分析器,可是對於實際的語言設計,基本都是線性時間構造出來的.
自頂向上
,自底向上
.
自頂向上語法
,構造過程從根節點開始,逐步向葉子節點
進行.
自底向上語法
則相反
向前看(lookahead)
符號.
爲一個非終結符號 選擇產生式是一個嘗試並犯錯的過程,咱們首先選擇一個產生式,若是這個產生式不合適將會進行回溯,再嘗試另外一個產生式.
預測語法分析
的特殊狀況不須要回溯.
遞歸降低分析方法(recursive-descent parsing)
是一種自頂向下的語法分析方法,他使用一組遞歸過程來處理輸入.
這裏咱們考慮遞歸降低方法
的一個簡單形式,稱爲預測分析法(predictive parsing)
預測分析法
中,各個非終結符對應的過程當中的控制流能夠由向前看無二義的肯定.在分析輸入串時出現的過程調用序列隱式地定義了該輸入串的一顆語法分析樹.關於計算的方法在4.2.2中介紹
預測分析法要求時
當知足可以使用預測分析器時:
對於語法動做如何處理
左遞歸:
右遞歸:
右遞歸對於左結合運算的翻譯會變得困難
4.3.3節將考慮更通常的左遞歸形式
(1)
void S(){ swithch( lookahead ) { case +: match(+);S();S();break; case -: match(-);S();S();break; case a; match(a);break; default: report("syntax error"); } }
(2)要注意最終的結果,並消除左遞歸
void S(){ if(lookahead == "("){ match("("); S(); match(")"); S(); } }
(3)兩個產生式的FIRST都是0,須要注意
void S() { if(lookahead==0) { match(0); if(lookahead!=1) S(); match(1); } else report("syntax error"); }
使用前三節技術,咱們將使用Java語言編寫一個語法制導翻譯器.
如今咱們處於矛盾中:
另外一方面,咱們須要一個明顯不一樣的可以支持語法分析過程的文法;
因此先使用易於翻譯的文法,而後當心的轉換,使之可以語法分析.
咱們將消除2-21的左遞歸,獲得一個適用於預測遞歸降低翻譯器的文法.
設計一個翻譯器是,名爲抽象語法樹(abstract syntax tree)
的數據結構是一個很好的起點.
語法分析樹叫作具體語法樹(concrete syn-tax tree)
,相應的文法叫作該語言的具體文法(concrete syntax)
2個左遞歸產生式和一個非左遞歸產生式
通常都會預讀一些字符放在緩衝區.有兩個好處
>
仍是>=
等本節的詞法分析器會預讀一個字符,本節中的詞法分析器不變式斷言以下:
當詞法分析器返回一個詞法單元時:
- 變量
peek
要麼保存當前詞法單元詞素後的那個字符,要麼保存空白
當在輸入流出現一個數位序列時,詞法分析器將向語法分析器傳送一個詞法單元.
num
和根據數位計算出來的值 如:<num,31>
關鍵詞(keyword)
:大多數程序使用for
,do
,if
這樣的固定字符串做爲標點符號,或者用於某種構造,這些字符串加作關鍵詞.
關鍵詞一般也知足標識符的組成規則,當將關鍵詞做爲保留字時,相對容易解決.
使用一個字符串表來保存字符串.
符號表(symbol table)
是一種供編譯器用於保存有關源程序構造的各類信息的數據結構.
一顆 有前向邊的樹
支持三種操做
兩種最重要的中間表現形式
指望<=
,>=
以後的結構是boolean
咱們將說明如何經過遍歷語法樹來生成三地址代碼.
具體來講,咱們將顯示如何編寫一個抽象語法樹的函數,並同時生成必要的三地址代碼.
If
是類Stmt
的一個子類.Stmt
的子類都有一個構造函數和一個gen
gen
是一個生成三地址代碼的函數.咱們將考慮包含二目運算符op
,數組訪問,和賦值運算,幷包含常量及標識符的表達式,以此來講明對錶達式的翻譯.
lvalue
,rvalue