賴智超
(中航工業(yè)綜合技術(shù)研究所,北京 100028)
AltaRica語言在安全性仿真分析平臺中的實現(xiàn)與應(yīng)用
賴智超
(中航工業(yè)綜合技術(shù)研究所,北京 100028)
[摘要]通過分析AltaRica語言的特性,在借鑒了編譯原理相關(guān)理論的基礎(chǔ)上,介紹如何實現(xiàn)AltaRica語言的編譯解析框架以及在安全性仿真分析平臺中的應(yīng)用。
[關(guān)鍵詞]AltaRica語言;編譯解析;仿真分析平臺
[收修訂稿日期] 2015-09-23
AltaRica語言[1]是一種形式化建模語言,被廣泛用于復(fù)雜系統(tǒng)的事件驅(qū)動建模中,它的語言特性非常適用于安全性和可靠性分析,因為安全性和可靠性分析的一個主要目標(biāo)實際上就是檢測和量化導(dǎo)致系統(tǒng)從正常狀態(tài)到失效狀態(tài)的事件集合。
AltaRica語言以事件為中心,其語義為:系統(tǒng)通過一系列的變量來描述狀態(tài),當(dāng)事件發(fā)生時,系統(tǒng)狀態(tài)會隨之發(fā)生改變。
安全性仿真分析平臺是基于模型的安全性和可靠性分析軟件。該平臺采用AltaRica語言,具有圖形化建模、故障樹分析、安全性分析、失效模式與影響分析、動態(tài)仿真等功能。平臺統(tǒng)籌考慮適航安全性評估分析、任務(wù)可靠性評估、可靠性設(shè)計權(quán)衡分析等需求,是仿真大平臺的核心組成部分。
在安全性仿真分析平臺實現(xiàn)過程中,涉及到的多項功能業(yè)務(wù)均與AltaRica腳本緊密關(guān)聯(lián),包括故障樹的生成、模塊邏輯關(guān)系的描述、故障傳遞的運算、仿真計算分析,因此,實現(xiàn)該平臺的首要任務(wù)是完成對AltaRica語言的編譯解析。
最基本的語言編譯過程通常包括詞法分析、語法分析、語義分析、生成目標(biāo)代碼,同樣的,AltaRica語言的編譯過程也是經(jīng)過了這幾個階段。首先,AltaRica語言在經(jīng)過詞法分析和語法分析后,會首先生成抽象語法樹,生成的抽象語法樹再經(jīng)過語義分析生成AltaRica語法樹,最后通過擴展、轉(zhuǎn)換生成中間代碼,整個過程如圖1所示。
圖1 編譯解析流程圖
2.1 生成抽象語法樹
開發(fā)一個AltaRica語法分析器大致分3步,第一步:寫出所需要分析的內(nèi)容的文法;第二步:完成針對該文法的語法分析器的代碼;第三步:編譯語法分析器。
所謂文法,即是一系列的語法規(guī)則,它是由若干定義語法規(guī)則的推導(dǎo)式組成的。通過簡單的以AltaRica語言規(guī)范中最基本的條件賦值(Condition)作為例子了解一下文法的表達。條件賦值是一個表達式,它的格式類似于 “STATE = WORKING;”。由于在語法分析中一般是用樹來表示語法結(jié)構(gòu),表達式的語法樹是以操作符為根節(jié)點和操作數(shù)為子節(jié)點的樹形結(jié)構(gòu)。在安全性仿真分析平臺項目中,文法定義大致如圖2所示。
圖2 文法定義
文法定義中分2大部分:語法描述和詞法描述。其中每一行都是一個規(guī)則(rule)或叫做推導(dǎo)式,每個規(guī)則的左邊是文法中的一個名字,代表文法中的一個抽象概念。中間用一個“:”表示推導(dǎo)關(guān)系,右邊是該名字推導(dǎo)出的文法形式。
語法分析是編譯過程的第二步,在詞法分析提供的詞號流的基礎(chǔ)上,對源代碼的結(jié)構(gòu)做總體的分析。無論分析的內(nèi)容有多大,語法分析總是由一個啟始規(guī)則開始的,最后總是生成一棵語法樹。一般情況語法規(guī)則是一個文法的主體部分,也是編寫文法的難點。
安全性仿真分析平臺采用自頂向下的語法分析方法。自頂向下的分析方法的思路是從起始規(guī)則開始選擇對應(yīng)的規(guī)則反復(fù)推導(dǎo),直到推導(dǎo)出待分析的語型。如果推導(dǎo)失敗則返回選擇其他規(guī)則進行推導(dǎo),即回溯,如果所有規(guī)則都失敗則說明這個句型是非法的。AltaRica語言進過語法分析之后,生成抽象語法樹,這棵抽象語法樹則是進行下一步語義分析的基礎(chǔ)。
2.2 語義分析及中間代碼
在完成語法分析階段后,接下來的目標(biāo)就是通過遍歷抽象語法樹,完成語義分析并生成中間代碼。
語義分析是編譯過程的一個邏輯階段,它的任務(wù)是對源程序進行上下文有關(guān)性質(zhì)的審查和類型審查,審查其有無語義錯誤,為代碼生成階段收集類型信息。比如審查某個運算符是否具有語言規(guī)范允許的運算對象,當(dāng)不符合語言規(guī)范時,編譯程序應(yīng)報告錯誤。
2.2.1 語義分析
通過語法分析得出的抽象語法樹,它的某個節(jié)點在整個程序上下文的意義是需要經(jīng)過分析轉(zhuǎn)換得到的,因為語法分析并未對一個源代碼內(nèi)部的邏輯含義加以分析。因此,編譯框架接下來需要執(zhí)行語義分析,即審查每個語法成分的靜態(tài)語義。靜態(tài)語義檢查涉及了以下幾個方面:
● 類型檢查,比如某個操作符的兩個操作對象必須類型一致。
● 控制流檢查,判斷控制語句的流向是否正確,比如if(…)then(…)else(…)格式語句需要有跳轉(zhuǎn)點,否則出錯。
● 一致性檢查,比如在相同的作用域里,定義了兩個同名的標(biāo)識符,這樣會造成歧義。
在語義分析階段,通過遍歷抽象語法樹進行轉(zhuǎn)換,以生成中間代碼。遍歷轉(zhuǎn)換過程針對AltaRica語言規(guī)范中的文法規(guī)則來定義不同類型的節(jié)點,這些節(jié)點將用來對語法樹節(jié)點進行轉(zhuǎn)義吸收,為后續(xù)的語義校驗提供基礎(chǔ)。遍歷過程針對不同類型節(jié)點,可分為如下幾類:
● 定義常量及變量節(jié)點
針對AltaRica語言規(guī)范定義出整形、浮點、布爾值、字符型、枚舉等常量節(jié)點,以及定義出代表系統(tǒng)變量(如系統(tǒng)端口、狀態(tài))的變量節(jié)點,這些節(jié)點均繼承自基類AltaRicaNodeBase,我們稱之為AltaRica節(jié)點。在遍歷到該類型的語法樹節(jié)點時,進行轉(zhuǎn)義吸收。如圖3所示,AltaRica節(jié)點派生出各種類型的常量和變量節(jié)點。
圖3 AltaRica節(jié)點
● 定義邏輯操作符節(jié)點
它代表的是與操作符、或操作符、非操作符等。比如,當(dāng)代表一個或門的AltaRica節(jié)點出現(xiàn)時,在語義分析階段,會把它轉(zhuǎn)義為或操作符,同時遍歷該AltaRica節(jié)點的所有孩子作為操作對象,并同時分析孩子的類型是否匹配。如圖4所示。
圖4 邏輯操作符節(jié)點
● 定義運算操作符節(jié)點
它代表的是常見的加、減、乘、除、比較等操作符。其中,比較運算符又細分為小于、小于等于、大于、大于等于、相等、不等操作符。
● 定義函數(shù)節(jié)點
它代表一些自定義的常用的函數(shù)。所有符合ANTLR函數(shù)規(guī)則文法的表達式,均會被語法分析器解析成函數(shù),但是符合規(guī)則的這些函數(shù)其語義需要在函數(shù)節(jié)點中重新定義,賦予其真正的含義。比如Max函數(shù),它在語法樹中,只能被告知這是一個函數(shù)節(jié)點,只有在語義解析階段,才給它定義功能為:這是一個二元及以上運算操作的函數(shù),必須包含兩個及兩個以上的運算對象,其計算結(jié)果是取所有運算對象中值最大的那個。函數(shù)節(jié)點的定義如圖5所示。
在遍歷抽象語法樹時,會根據(jù)不同的類型,執(zhí)行不同類型節(jié)點的轉(zhuǎn)義操作,在遍歷完抽象語法樹之后,AltaRica代碼的文法定義也就都經(jīng)過了語義分析,具備了屬于其自身的含義,這時,將生成另外一棵樹:AltaRica語法樹,這時,它的節(jié)點已經(jīng)具備了上下文關(guān)系。利用AltaRica語法樹可以在接下來的語義校驗過程中,很方便地識別某個節(jié)點的身份含義,從而判斷某些節(jié)點是否存在語法錯誤。
在校驗階段,其實就是對AltaRica語法樹的節(jié)點進行語法檢查的一個過程。還是以Max函數(shù)為例,如果有一個函數(shù)被描述為Max(A,B),在AltaRica語法樹中,它的結(jié)構(gòu)應(yīng)該是如6所示的。
圖5 函數(shù)節(jié)點的定義
圖6 語法樹結(jié)構(gòu)示例
在執(zhí)行到Max節(jié)點的語法檢查時,會同時啟動對孩子節(jié)點的檢查,如果發(fā)現(xiàn)孩子節(jié)點少于兩個時,會報“函數(shù)定義不合法”的錯誤。
在安全性仿真分析平臺中,定義了信號流(Flow)和斷言(Assert),它們的文法如圖2所示。
假設(shè)有下面這樣一段代碼:
flow
A:bool: in;
B:bool: in;
X:bool: out;
assert
X = if ((A=false) and (B=false)) then false else true;
它表示有A、B、X 3個布爾型的變量,X為輸出端口,A、B為輸入端口,這句斷言的語義是“當(dāng)輸入端口A和B的取值同時為false的時候,輸出端口X取值為false,否則為true”。上面的代碼將會被編譯成如圖7這樣的AltaRica語法樹結(jié)構(gòu)。
圖7 斷言在AltaRica語法樹中的結(jié)構(gòu)
生成中間代碼,是在AltaRica語法樹的基礎(chǔ)上,擴展出一套符合AltaRica運算法則的方法。基于前面生成的AltaRica語法樹,在它上面掛載一些系統(tǒng)的業(yè)務(wù)功能比如邏輯關(guān)系運算、仿真計算、故障傳遞等接口,使它可以在中間代碼解析執(zhí)行引擎執(zhí)行相應(yīng)的功能。
2.2.3 中間代碼解析執(zhí)行引擎
中間代碼必須在經(jīng)過加載、初始化、解析等階段才能被使用。在編譯解析框架中實現(xiàn)了一個中間代碼解析執(zhí)行引擎,就是做這部分工作。
在中間代碼解析執(zhí)行引擎的內(nèi)部維護了一個狀態(tài)機,當(dāng)中間代碼被加載時,狀態(tài)機會開辟出包括變量區(qū)、操作數(shù)棧、棧信息區(qū)等區(qū)域。
變量區(qū):是一組變量值的存儲空間,用于存放在AltaRica代碼中定義的各種變量,在安全性仿真分析平臺中,這個區(qū)域一般是存放系統(tǒng)狀態(tài)值、端口的狀態(tài)值以及其他系統(tǒng)配置參數(shù)。
操作數(shù)棧:是用來存放操作數(shù)的棧結(jié)構(gòu),當(dāng)一個方法剛開始執(zhí)行的時候,這個方法的操作數(shù)棧是空的,在方法的執(zhí)行過程中,會有指令向操作數(shù)棧中寫入和提取內(nèi)容,也就是入棧和出棧的操作。
棧信息區(qū):主要用于存儲操作數(shù)棧的一些基本信息,包括方法返回的地址、臨時變量的地址、回調(diào)方法的地址等等。
?數(shù)據(jù)來自 Schenk C.R.,“The Origins of the Eurodollar Market in London:1955 ~ 1963”,Explorations in Economic History,2004,35(2),pp.221 ~238.
在中間代碼加載完畢之后,會進行初始化工作,首先把AltaRica代碼中定義的變量初始化進變量區(qū),然后在棧信息區(qū)里存儲各種函數(shù)調(diào)用關(guān)系。
初始化工作完成后,便可以執(zhí)行各種需要的運算工作,比如項目執(zhí)行仿真計算或者故障推進演算等等,都是在這個時期進行的。
當(dāng)運算工作結(jié)束,可以主動調(diào)用狀態(tài)機去釋放內(nèi)存,或者等待系統(tǒng)在注銷狀態(tài)機時自動釋放,完成垃圾回收工作。
2.2.4 中間代碼優(yōu)化
所謂代碼優(yōu)化,是在不改變程序運行效果的前提下,對被編譯的程序進行等價變化,以生成更加高效的目標(biāo)代碼。代碼優(yōu)化的級別一般分為3種:局部優(yōu)化、循環(huán)優(yōu)化、全局優(yōu)化。由于AltaRica語言的特性,循環(huán)操作強度不大,而且代碼量不會非常龐大,做循環(huán)優(yōu)化和全局優(yōu)化的意義并不大,所以目前這套解析框架只實現(xiàn)了局部優(yōu)化。
局部優(yōu)化的第一步是劃分基本塊,一個基本塊內(nèi)的語句是沒有跳轉(zhuǎn)及分叉匯合的,比如,在安全性仿真分析平臺中常用到的影響(Effect),它的格式是Effect:= Assert1; Assert2;… .,它可以包含N個斷言(Assert),而Assert的格式則是這樣的X:= If(邏輯語句 A)then true else false;那么,在劃分基本塊時,會自頂向下進行劃分,一直到邏輯語句A時,把它劃分為一個基本塊。
這時進行第二步:基本塊處理?;緣K處理主要是進行轉(zhuǎn)移分析,凡是控制流不可到達的語句,直接忽略處理,比如,邏輯語句A的內(nèi)容恒真,則它永遠不會到達else那部分邏輯處理,可以將else部分直接忽略處理。除此之外,基本塊處理還會進行變量分析,比如,對于已定義卻從未在語句中使用過的變量,會直接剔除掉。在經(jīng)過局部優(yōu)化之后,生成的AltaRica語法樹會較未優(yōu)化之前的要小。
在安全性仿真分析平臺中,有相當(dāng)多的地方使用到了AltaRica語言,整個系統(tǒng)與AltaRica語言可謂是緊密相連,在系統(tǒng)的諸多功能中,AltaRica語言扮演了重要的角色,它既是參與模塊信息存儲的一份子,也是故障樹的前身;既是邏輯關(guān)系運算的載體,也是仿真計算的主角。下面介紹一下AltaRica語言在仿真計算中的應(yīng)用。
首先,仿真計算中關(guān)鍵的一步就是,如何計算出一個信號的流入或者系統(tǒng)自身狀態(tài)的改變,會影響系統(tǒng)自身的輸出。這個計算的依據(jù),就是存儲在模型設(shè)計時用于描述系統(tǒng)模塊狀態(tài)變化的邏輯關(guān)系,而邏輯關(guān)系則直接由AltaRica腳本編寫,所以,仿真計算的這一步,其實最終就是簡化為對AltaRica腳本的編譯計算,這樣,就可以根據(jù)邏輯關(guān)系的推演計算結(jié)果得到仿真計算的結(jié)果。
假設(shè),在模型設(shè)計時,有如圖8的模型關(guān)系。
圖8 模型示例
其中,模型b12的邏輯關(guān)系如圖9所示。
圖9 模型b12的邏輯關(guān)系
它對應(yīng)的AltaRica代碼如下:
o := if((狀態(tài)1=失效) or ((i=故障) and (i1=故障))) then 故障 else 正常;
這段代碼的語義是:“當(dāng)自身的某個狀態(tài)1是失效,或者當(dāng)兩個輸入端口信號同時均為故障時,輸出信號為故障,否則輸出信號為正?!薄?/p>
這段代碼經(jīng)過編譯解析框架的編譯之后,其AltaRica語法樹如圖10所示。
生成中間代碼后,即可用于仿真計算,比如,系統(tǒng)b10和系統(tǒng)b11的輸出均為故障信號,則系統(tǒng)b12的兩個輸入端口均接收到該故障信號,這時,針對系統(tǒng)b12的輸出計算,就是把故障信號作為參數(shù)傳遞給中間代碼,在解析執(zhí)行引擎中,會把這段邏輯關(guān)系執(zhí)行運算,得出系統(tǒng)b12的輸出端口的值,即推算出了系統(tǒng)b12的輸出結(jié)果,從而達到仿真計算的目的。
圖10 編譯后的語法樹內(nèi)容
本文從應(yīng)用需求的角度出發(fā),提出了一種解決AltaRica語言的編譯解析的方法,借鑒于一般的編譯原理方式,解決了AltaRica語言的詞法分析、語法分析、語義分析等編譯任務(wù),并建立了一套可擴展的編譯解析框架,在后期中間代碼生成階段,也充分考慮到了業(yè)務(wù)的可擴展性,能夠在未來可以實現(xiàn)插件的方式來注入自定義的一些功能。
這套編譯解析框架雖然很好地解決了AltaRica語言的編譯需求,整個設(shè)計非常的簡潔統(tǒng)一,但是在對AltaRica語言進行詞法分析、語法分析時,生成的抽象語法樹有些龐大,希望后續(xù)的研究中能對其進行改進優(yōu)化,以提升整個編譯解析框架的執(zhí)行效率。
[參考文獻]
[1] Antoine B. Rauzy. AltaRica Data-Flow Language Specification –Version 2.1[EB/OL] . http://www.lix.polytechnique.fr/~rauzy/altarica/.
[2] T. Prosvirnova & Antoine B. Rauzy. AltaRica 3.0 project : compile Guarded Transition Systems into Fault Trees[EB/OL] . http://www.lix.polytechnique.fr/~prosvirnova/.
(編輯:勞邊)
[中圖分類號]TP391
[文獻標(biāo)識碼]C
[文章編號]1003–6660(2015)06–0037–05
[DOI編碼]10.13237/j.cnki.asq.2015.06.009