溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

JavaML 用于 Java 源代碼的標(biāo)記語言(轉(zhuǎn))

發(fā)布時間:2020-08-11 05:01:59 來源:ITPUB博客 閱讀:200 作者:amyz 欄目:編程語言
JavaML 用于 Java 源代碼的標(biāo)記語言(轉(zhuǎn))[@more@]

  傳統(tǒng)的源代碼簡單文本表示對于編程人員來說很方便,但需要進行語法分析來揭示程序的深層結(jié)構(gòu)。盡管某些復(fù)雜的軟件工具通過分析源代碼可以訪問程序的結(jié)構(gòu),但許多像 grep 這樣的輕量級編程輔助工具卻僅僅依賴于源代碼的詞法結(jié)構(gòu)。我說明的是一種新的 XML 應(yīng)用程序,該應(yīng)用程序提供了另一種 Java 源代碼表示法。這種基于 XML 的表示法叫做 JavaML,對工具軟件來說顯得更加自然,它利用豐富的 XML 工具和技術(shù),可以方便地對大量軟件工程分析進行規(guī)范。使用 Jikes Java 編譯器框架構(gòu)建的強健的轉(zhuǎn)換器,可將傳統(tǒng)的源代碼表示轉(zhuǎn)換為 JavaML;而使用 XSLT 樣式表,又可將 JavaML 轉(zhuǎn)回到傳統(tǒng)的文本格式。

  簡介

  從第一種計算機編程語言開始,編程人員就已經(jīng)開始將文本表示用作軟件結(jié)構(gòu)和計算過程的編碼媒介。這些年來,技術(shù)已得到充分發(fā)展,使編譯器的前端大大自動化了;編譯器的前端就是執(zhí)行詞法分析和語法分析的那部分,是揭示以簡單文本表示的編程語言的結(jié)構(gòu)所必不可少的。借助于具有牢固基礎(chǔ)的正規(guī)表達式的概念和語法,Lex/Flex 和 Yacc/Bison [42] 之類的工具使這些單調(diào)乏味的分析工作走向了自動化。正規(guī)表達式說明單個字符如何組合成表單記號,語法則描述更高級別的結(jié)構(gòu)是如何由其他結(jié)構(gòu)和原始表單記號遞歸構(gòu)成的。這些過程一起將字符系列轉(zhuǎn)換成一種叫做 抽象語法樹 (AST) 的數(shù)據(jù)結(jié)構(gòu),這種數(shù)據(jù)結(jié)構(gòu)可以更直接地反映程序的結(jié)構(gòu)。

  源代碼的文本表示有幾種良好的特性。文本表示相當(dāng)簡明,并且與自然語言相似,往往比較容易閱讀。文本還是一種通用的數(shù)據(jù)格式,因而可以方便地使用大量軟件工具轉(zhuǎn)換和處理源代碼,這些軟件工具包括文本編輯器、版本控制系統(tǒng)以及 grep, awk 和 wc 之類的命令流水線實用程序。

  然而,傳統(tǒng)的源代碼表示有許多問題。諸如 C++ 和 Perl 之類的當(dāng)前十分流行的語言的語法結(jié)構(gòu),更加重了對語法分析能力的限制。盡管有許多工具的支持,但是為這些語言構(gòu)造一個編譯器的前端仍很困難。更為困難的也許是,要發(fā)展一種語言的語法,就常常需要處理脆弱的文法。這種局限性使得對一種正在發(fā)展的語言的處理復(fù)雜化了。

  文本表示和軟件工具

  傳統(tǒng)的源代碼表示的最大局限性是,只有在語法分析后,才能搞清楚程序的結(jié)構(gòu)。這一缺陷使得,某種語言專用的分析功能,在每一個工具中都要重復(fù)配置,只要這些工具在進行程序的詞法分析之外,還要對程序進行語法推理。編譯器必然需要與抽象結(jié)構(gòu)樹(AST)一起使用,而許多其他軟件工程工具將從訪問源代碼的結(jié)構(gòu)化表示中獲益。遺憾的是,許多軟件工程工具沒有嵌入語法分析器,因而僅限于執(zhí)行一些詞法分析任務(wù)。

  有幾種原因使得開發(fā)人員常常避免在工具軟件中嵌入語法分析器。正如前面所提到的,對于語法結(jié)構(gòu)復(fù)雜的語言,構(gòu)建一個完整的編譯器前端是具有挑戰(zhàn)性的。雖然重復(fù)使用(例如重復(fù)使用語法定義)簡化了實現(xiàn)的過程,但產(chǎn)生的抽象結(jié)構(gòu)樹(AST)并不總是直觀的。抽象結(jié)構(gòu)樹(AST)通常反映的是奇特的人為技巧,而不是直接表示編程層次上的結(jié)構(gòu)。此外,如果您的目標(biāo)是使用詞法信息就能完成得“相當(dāng)好”的簡單語法分析,嵌入編譯器的前端無異于“殺雞用牛刀”。

  如果希望轉(zhuǎn)換源代碼的格式,則會出現(xiàn)其他的復(fù)雜問題:抽象結(jié)構(gòu)樹(AST)的變化最終必定反映到傳統(tǒng)的源代碼表示中,因為后者是主要的長期存儲格式。要從一個抽象結(jié)構(gòu)樹(AST)重新創(chuàng)建一種文本表示,最直接了當(dāng)?shù)姆椒ň褪遣贿M行語法分析,但這樣會產(chǎn)生不受歡迎的副作用,如縮排或空白的更改。開發(fā)人員所依賴的其他詞法工具會分不清這些更改,例如,版本控制系統(tǒng)就無法區(qū)分一個有意義的修改和一個意外產(chǎn)生的無理修改。

  最后,在某種工具中使用語法分析器必定會把該工具定位于那種特定的語言,因而會減弱它的適用性和通用性。更糟的是,由于源程序沒有標(biāo)準(zhǔn)的結(jié)構(gòu)化的外部表示法,甚至對于以同一種編程語言為目標(biāo)的不同工具來說,要對它們之間的互操作性進行支持,都是很困難的。

  這些復(fù)雜因素的最終結(jié)果是,開發(fā)人員往往不得不使用簡單的、面向詞法分析的工具,比如編輯器中的 grep 或者“搜索并替換”。這種方法犧牲了準(zhǔn)確性:試想將一個局部變量從 result 重命名為 answer。借助簡單的“搜索并替換”,每一處出現(xiàn)這個單詞的地方都會替換,即使是注釋、文本串或者毫不相干的實例字段中的字符,也不例外。

  一些開發(fā)人員采用的一種替代方法是,依靠集成開發(fā)環(huán)境 (IDE) 中提供的一套固定的工具,該開發(fā)環(huán)境能夠通過一個集成的語言專用分析器訪問其源程序的結(jié)構(gòu),但這種方法犧牲了靈活性。集成開發(fā)環(huán)境(IDE)一般只提供一套有限的功能,而且這些功能難于擴展。此外,使用現(xiàn)有的交互式環(huán)境,難以自動或批量分析和轉(zhuǎn)換源代碼。一些更高級的集成開發(fā)環(huán)境 (IDE) 如 IBM VisualAge for C++ [ 48],將應(yīng)用程序編程接口提供給程序的表示法,雖然這也算是一種改進,但這項技術(shù)仍然有弊端,因為它不能將簡單工具從一種復(fù)雜的環(huán)境中分離出來,此外還產(chǎn)生了對專有技術(shù)的依賴,這是我們所不希望看到的。

  解決方案

  隱藏在上述問題背后的一個基本問題是,源代碼缺乏規(guī)范的結(jié)構(gòu)化表示方法。我們需要有一種通用的格式來直接表示程序結(jié)構(gòu),以便于軟件工具分析和處理。我們觀察到的一個關(guān)鍵之處是,XML 這種可擴展標(biāo)記語言(eXtensible Markup Language) [ 9],正好提供了這種功能,而且它是一種功能無比強大的源代碼補充表示。

  在本文中,我要介紹 Java 標(biāo)記語言,也即 JavaML ? 一種用于描述 Java 源程序的 XML 應(yīng)用程序。JavaML 文檔類型定義 (DTD) 規(guī)定了有效的 JavaML 文檔的元素,以及這些元素組合的方式。在這些元素、元素的屬性以及用這些元素編寫的編程語言結(jié)構(gòu)之間,有一種自然的對應(yīng)關(guān)系。在 JavaML 文檔中,源程序的結(jié)構(gòu)反映在元素的嵌套中。借助這種表示,我們就可以利用處理和查詢 XML 和 SGML 文檔的大量工具,提供一種功能豐富的、開放式的基本結(jié)構(gòu),進行 Java 源代碼的軟件工程轉(zhuǎn)換和分析。

  JavaML 很適合用作工具軟件的規(guī)范的 Java 源代碼表示。它保留了傳統(tǒng)表示的大部分優(yōu)點,而且克服了這些表示法的許多弱點。下一節(jié)講述 Java 語言和 XML 的有關(guān)特性, “Java 標(biāo)記語言 (JavaML)” 一節(jié)則詳細描述標(biāo)記語言,以及傳統(tǒng)表示與 JavaML 之間的轉(zhuǎn)換器的實現(xiàn)。 “使用 XML” 一節(jié)舉了許多例子來說明,如何利用現(xiàn)有的 XML 和 SGML 工具,在 JavaML 提供的功能更為豐富的表示法的基礎(chǔ)上,分析源代碼和進行格式轉(zhuǎn)換。 “相關(guān)工作”和 “下一步工作” 講述相關(guān)的工作,并推薦完成更令人興奮的下一步工作的途徑。 附錄 A 中有 JavaML 的完整的文檔類型定義 (DTD),而已轉(zhuǎn)換的源代碼的更多實例可從作者 的 JavaML Web 頁 [ 4 ] 上獲得。

  背景

  Java 標(biāo)記語言在 Java 和 XML 這兩種技術(shù)之間架起了一座橋梁,它受到這兩種技術(shù)的大量特性的影響,獲益匪淺。

  Java 技術(shù)

  雖然基于 XML 的編程語言結(jié)構(gòu)的表示法與語言無關(guān),但是 Java 語言是試驗這些理念和技術(shù)的最佳選擇。

  Java 語言是一種流行的面向?qū)ο蟮木幊陶Z言,由 Sun Microsystems 在 90 年代中期開發(fā) [ 3][ 25 ]。它是一個基于 Java 虛擬機 (JVM) 的、與操作平臺無關(guān)的執(zhí)行模型,由于用作萬維網(wǎng)應(yīng)用程序的編程語言而很快被廣泛的接受。Java 語言將一種令人聯(lián)想到 Smalltalk [ 26 ] 的簡單對象模型,與 Algol 語言塊結(jié)構(gòu)、一種類似 C++ [ 49] 的語法,一種靜態(tài)類型系統(tǒng)和一種由 Modula-2 [ 10] 產(chǎn)生的軟件包系統(tǒng)結(jié)合在一起。

  在 Java 語言中,與在大多數(shù)其他面向?qū)ο?(OO) 的語言中一樣,對程序語言進行解析所得到的基本單元是 類(class),類規(guī)定了一組對象的行為。每一個類可定義幾種 方法,或者稱之為行為,類似于函數(shù)或過程。一個類還可以定義 域,或稱之為狀態(tài)變量,這些域與類的 實例相關(guān)聯(lián),而這些實例叫做 對象。類可以從 超類繼承行為和狀態(tài),從而形成互相關(guān)的類的層次結(jié)構(gòu),該層次結(jié)構(gòu)允許在其頂部將相關(guān)的代碼分解為類,從而有利于重復(fù)使用。行為是通過向目標(biāo)接受者對象發(fā)送一個 消息來調(diào)用的,此消息就是執(zhí)行一個為該類定義的方法的請求。選擇執(zhí)行什么方法來響應(yīng)一個消息叫做 動態(tài)調(diào)用 ,依據(jù)的是接收消息的對象的運行時類。例如 ColoredBall 類的一個實例,可能用一種與 Ball 類的實例不同的方法響應(yīng) draw 消息。這種收到同一消息而做出不同響應(yīng)的能力,主要得益于 Java 語言的可擴展性優(yōu)勢,而這種優(yōu)勢正是面向?qū)ο螅∣O)的團體所大力稱道的。

  Java 語言在工業(yè)和教育領(lǐng)域都得到了廣泛應(yīng)用,并且仍然是一種廣受歡迎的 Web 編程語言。與 C++ 不同,Java 類定義放在一個單獨的自含式文件中,既沒有單獨的頭文件也沒有執(zhí)行文件,并且 Java 語言基本上沒有定義的次序相關(guān)性。在出現(xiàn)方法體時,它總是緊隨方法特征聲明之后定義。此外,Java 語言缺少集成處理器。這些特性合在一起,使 Java 源程序在語法上很簡潔,從而使 Java 語言成為使用 XML 表示的最理想的語言。(這種方法對其他語言的適應(yīng)能力將在 “下一步工作” 中進一步討論。)

  XML:可擴展標(biāo)記語言

  XML 是一種標(biāo)準(zhǔn)的可擴展標(biāo)記語言 [ 9 ],是 SGML(標(biāo)準(zhǔn)通用標(biāo)記語言)的子集 [ 37 ]。萬維網(wǎng)聯(lián)盟 (W3C) 將 XML 設(shè)計得既小巧又簡單,同時仍保持與 SGML 兼容。盡管 HTML(超文本標(biāo)記語言)當(dāng)前是標(biāo)準(zhǔn)的 Web 文檔語言,W3C 正在將 XML 定位為 HTML 替代語言。標(biāo)記文檔時,HTML 僅允許編程人員使用預(yù)先定義的一套固定標(biāo)記,而 XML 卻可以方便地使用用戶定義的標(biāo)記,來適應(yīng)手頭文檔和數(shù)據(jù)的標(biāo)記要求 [ 27][ 28]。

  XML 文檔只是由使用標(biāo)記符進行標(biāo)記的文本簡單地組成,這些標(biāo)記符含在尖括號內(nèi)。下面是一個簡單例子:

  MomDadGregMy tripThe weather is terrific!

   是 email 元素的開啟標(biāo)記,本例結(jié)尾的 是對應(yīng)的關(guān)閉標(biāo)記。文本和其他嵌套的標(biāo)記可出現(xiàn)在開啟和關(guān)閉標(biāo)記結(jié)構(gòu)之間。出現(xiàn)空元素是允許的;空元素以專門的形式縮略,將開啟標(biāo)記和關(guān)閉標(biāo)記合并在一起: 。在上述文檔中,email 元素包含兩個直接子元素:head 和 body。此外, XML 開啟標(biāo)記可以與元素的屬性/值對相關(guān)聯(lián),例如,上面 body 元素的 encoding 屬性值為 ascii。若要一個 XML 文檔是 合式 的,則該文檔必須完全遵循 XML 文檔要求的大量的語法規(guī)則(例如標(biāo)記必須配對并正確嵌套,屬性值必須格式正確并放在引號內(nèi),等等)。

  XML 文檔的一個更嚴格的特點是 有效性 。當(dāng)且僅當(dāng)一個 XML 文檔既是合式的,又符合其指定的 文檔類型定義 (或稱 DTD )時,該 XML 文檔才是有效的。文檔類型定義是一種形式描述,用于一類 XML 文檔使用的特定語言的語法,它定義所有已允許的元素名稱,并描述每一類元素可以擁有的屬性,同時,它還限制一個有效的 XML 文檔內(nèi)的嵌套結(jié)構(gòu)。就下面的文檔定義類型 (DTD) 而言,前面的 XML 示例是有效的:

  <!-- email DTD -->

  按照此文檔類型定義 (DTD),有六種元素類型。email 元素必須正好包含一個 head,后面正好跟一個 body 元素。Head 也同樣必須包含一個或多個 to 元素,然后是一個 from 元素,后面跟一個可選的 subject 元素。元素的次序必須是指定的次序。這些元素中的每一個都可以包含文本(又稱 已分析的字符數(shù)據(jù) 或 PCDATA)。文檔定義類型 (DTD) 中的單一 ATTLIST 聲明規(guī)定,body 元素 可以 為 encrypted 屬性指定一個值,并且 必須為 encoding 屬性指定 ascii 或 mime。encoding-attribute 的 ENTITY 聲明(在 DTD 頂部)是一種分解出冗余文本的簡單方法;即引號之間給出的文本,可按原樣替換到下面的 ATTLIST 聲明中(并且,重要的是,它可以用在多個 ATTLIST 中)。

  如果上述準(zhǔn)則有任何一個未得到滿足,則聲明遵循此文檔定義類型(DTD)的 XML 文檔無效。例如,如果某個 email 文檔中缺少 from 元素,則該文檔是無效的,雖然它可能仍然是合式的。

  當(dāng)您在 XML 中制作數(shù)據(jù)模型時,主要的設(shè)計決策是在嵌套元素或使用屬性之間作出選擇。在上例中,如果我們這樣選擇的話,本來也可以把 head 中包含的全部元素都合并到 email 元素的各個屬性中去。在使用屬性和嵌套元素之間有一些重要區(qū)別:

  • 屬性/值對是無序的,而嵌套的子元素具有規(guī)定的次序。
  • 屬性的值可以只包含字符數(shù)據(jù),不可以包括其他標(biāo)記,而嵌套的子元素可以隨意地進一步嵌套。
  • 只能給每個屬性一個值,而一個父元素可以包含多個屬于同一類的元素(例如,我們可以讓多個 to 元素包含在 head 中)。

  雖然上面的區(qū)別有時可以決定使用這種技術(shù)還是那種技術(shù),但最初的決策往往是一個愛好問題。但是,以后使用由此產(chǎn)生的文檔的經(jīng)驗,可能會啟發(fā)人們重新去考察這個決策,以便使文檔中所需的某些操作變得容易或簡單。

  XML 的另一種有用的數(shù)據(jù)模型編制特性是,通過 id 屬性給元素附上一個唯一標(biāo)識符,然后其他元素的 idref 就可以引用這些元素。一個合式的 XML 文檔,必須讓每一個 idref 值與文檔中的一個給定 id 匹配。id/idref 鏈接描述一些優(yōu)勢,這些優(yōu)勢能夠使 XML 表示通用的定向圖,而不只是表示樹目錄。

  一些工具(如 Emacs 編輯模式、基于結(jié)構(gòu)的編輯器、DTD 語法分析器、驗證實用程序、查詢系統(tǒng)、格式轉(zhuǎn)換和樣式語言,以及許多其他工具)能夠很好地支持 XML,這在一定程度上是由于 XML 是從 SGML 繼承而來的。許多其他 W3C comments都與 XML 有關(guān),包括級聯(lián)樣式表 [ 8]、XSL(可擴展樣式表語言)[ 19]、XSLT (用于轉(zhuǎn)換的 XSL)[ 14]、XPath [ 16 ] 和 DOM(文檔對象模型)[ 2]。

  Java 標(biāo)記語言 (JavaML)

  Java 標(biāo)記語言提供了一套完整的 Java 源代碼自描述表示。與傳統(tǒng)的基于字符的程序表示不同,JavaML 以基于 XML 語法的元素嵌套方式,直接反映了軟件產(chǎn)品的結(jié)構(gòu)。此外,通過使用 XML 的 id 和 idref 鏈接,JavaML 還在程序圖中表現(xiàn)出了更多的側(cè)面。

  由于 XML 是一種基于文本的表示,所以它保留了傳統(tǒng)源代碼表示的許多優(yōu)點。而 JavaML 是一種 XML 的應(yīng)用程序,所以它易于進行語法分析;并且,現(xiàn)有的所有用于 XML 的工具,都可用于以 JavaML 表示的 Java 源代碼。JavaML 的各種工具可以利用現(xiàn)有的基礎(chǔ)結(jié)構(gòu)和規(guī)范表示法來增強其互操作性。

  可能的方法

  雖然使用 XML 應(yīng)用程序來編制源代碼的基本方法是相當(dāng)直接的,但到底使用哪種可能的標(biāo)記語言,仍然有一個很大的設(shè)計空間。最明顯的可能性是直接將 XML 用作一個典型的抽象語法樹文本轉(zhuǎn)儲格式,該語法樹源于對源代碼的語法分析?,F(xiàn)考慮下面這個簡單的 Java 程序:

  import java.applet.*;import java.awt.*;public class FirstAppletextends Applet {public void paint(Graphics g) {g.drawString("FirstApplet", 25, 50);}}

  執(zhí)行上例中抽象語法樹明顯的(但極不令人滿意的)轉(zhuǎn)換,可能會產(chǎn)生 僅第一行代碼 的如下 XML 形式:

  importjava.applet. * ;...

  毫無疑問,這種轉(zhuǎn)換與理想相去甚遠:它冗長得令人無法接受,并且它給出了底層語法的許多令人乏味的細節(jié),這些語法原本是用來分析傳統(tǒng)源代碼表示的。

  另一種可能性是直接標(biāo)記 Java 源程序而不更改程序的文本(即僅添加標(biāo)記)。這種方法可能把 FirstApplet.java 實現(xiàn)轉(zhuǎn)換為:

  import java.applet.*;import java.awt.*;public classFirstAppletextendsApplet {publicvoidpaint(Graphicsg){g.drawString("FirstApplet", 25, 50);} }

  這一格式朝著一種更有用的標(biāo)記語言的方向邁了一大步。我們已經(jīng)肯定地向源代碼添加了值,而轉(zhuǎn)回傳統(tǒng)的表示法也很容易:只要刪除所有 tag,并留下元素的內(nèi)容(這種刪除標(biāo)記的方法,與 stripsgml [ 31 ] 實用程序的作法,如出一轍)。雖然這種表示似乎對許多任務(wù)有用,但它仍然存在一些問題。首先,編碼的許多詳細信息包含在元素的文本內(nèi)容中,如果我們想確定要導(dǎo)入什么軟件包, XML 查詢將需要對聲明導(dǎo)入的元素進行詞法分析。這種分析用起來不方便,而且沒有利用 XML 提供的能力。也許更為重要的一點是,上述的 XML 表示法保留了傳統(tǒng)源代碼的人為因素,而另一種表示法則可能允許我們不考慮語法細節(jié)進行抽象,使我們自己從這些語法重負中完全解脫出來。

  選擇的表示

  我選擇原型 JavaML 表示,旨在制定 Java 語言(實際上包括類似的面向?qū)ο螅┑木幊陶Z言結(jié)構(gòu)模型,而不依賴特定語言的語法。人們可以很容易想到有一個 Smalltalk 標(biāo)記語言(SmalltalkML),與此想法非常類似,甚至可以想到應(yīng)該有一個面向?qū)ο髽?biāo)記語言(OOML),它既可以轉(zhuǎn)換成傳統(tǒng)的 Java 源代碼,又可以轉(zhuǎn)換成 Smalltalk 的外部定義格式。心中有了這個目標(biāo),于是首先按這些結(jié)構(gòu)原則設(shè)計出 JavaML,然后對它不斷地進行提煉,使它在功能和可讀性方面都堪稱優(yōu)秀的標(biāo)記語言。

  JavaML 由 附錄 A 中的文檔類型定義 (DTD) 來確定,但最好還是用示例來說明。對于上面列出的 FirstApplet.java 源代碼,我們給出如圖 1 所示的 JavaML 程序。

  圖 1.轉(zhuǎn)換成 JavaML 的 FirstApplet.java

  1 2 34 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

  在 JavaML 中,諸如方法、超類、消息發(fā)送和字面值數(shù)字之類的概念,都是直接在文檔內(nèi)容的元素和屬性中表示的。JavaML 的表示法用元素的嵌套來反映編程語言的結(jié)構(gòu)。例如,文本串 “FirstApplet” 是消息發(fā)送的一部分,這樣 literal-string 元素就嵌套在 send 元素內(nèi)。如果像圖 2a 和圖 2b 那樣,以可視形式給出源代碼時,這種嵌套就更明顯了。有關(guān)的更多例子,請參見 JavaML 網(wǎng)頁 [ 4]。

  細心的讀者會看到, JavaML 表示的源代碼的長度約比傳統(tǒng)的源代碼長三倍。源代碼變長是轉(zhuǎn)化成自描述數(shù)據(jù)格式(如 XML)的基本代價。有一點很重要,即編程人員在某些任務(wù)(包括一般開發(fā)和程序編輯)中能夠使用簡明扼要的傳統(tǒng)表示法,盡管 JavaML 可能是底層表示法。JavaML 是對傳統(tǒng)源代碼表示的補充,并且特別適合在工具軟件中使用,同時仍然可由開發(fā)人員訪問并直接讀取。

  圖 2a. 由 XML Notepad 實用程序 [ 44 ] 顯示的 FirstApplet 示例 JavaML 表示法樹形圖

  圖 2b. XML Spy [ 36 ]顯示 的 FirstApplet 示例的 JavaML 表示法樹形圖

 

  設(shè)計決策

  JavaML 所提供的不只是源程序的結(jié)構(gòu)。請注意,將圖 1 第 17 行的形參 g 用作了消息發(fā)送的目標(biāo),該 var-ref 標(biāo)記的 idref 屬性向后指向所引用的 formal-argument 元素(通過其 id 屬性)。(在一個文檔內(nèi),為要引用的元素選擇的 id 值必須是唯一的,以便每一個標(biāo)識符都用一個整數(shù)標(biāo)記,從而使其值各不相同。)這種鏈接是標(biāo)準(zhǔn)的 XML,這樣 XML 工具就能夠從一個變量的使用追溯到變量的定義,例如,可獲得變量的類型信息。局部變量(即代碼段內(nèi)聲明的變量)也有類似的鏈接,程序結(jié)構(gòu)圖的其他方面還可以有更多鏈接。盡管單一的 var-use 標(biāo)記已足以指示在任何地方出現(xiàn)的一個變量,但 JavaML 能夠在變量值的引用和用作左值的變量之間進行區(qū)分:var-ref 元素用于前者,var-set 用于后者。

  在整個 JavaML 中,除非元素值的結(jié)構(gòu)比簡單文本字符串更加復(fù)雜,否則程序員隨時可以使用元素的屬性。元素的屬性可用于諸如 synchronized 和 final 之類的修飾符,也可用于諸如 public 或 private 之類的可視性設(shè)置,但屬性不用于類型之類的特性,因為類型具有某種結(jié)構(gòu)形式:類型可由一個基本名和一個維數(shù)組成,并且它還可以引用實現(xiàn)該類型的類的定義,如果您想這樣做的話。如果,比方說,一個返回類型只是方法元素的一個屬性值,那么最終用戶將不得不對屬性的值 "int[][]" 執(zhí)行字符串處理(這是令人不能接受的),以確定該二維數(shù)組的基本類型是原始類型 int。實際上,類型編寫為顯式子元素,如 。

  JavaML 推廣了一些相關(guān)的概念,使某些分析過程得以簡化,但保留了實現(xiàn)其他任務(wù)可能需要的一些特征。例如,45 和 1.9 分別表示為 。另一種可能的標(biāo)記是 ,但分別使用不同的元素類就淡化了兩個值都是數(shù)字這層緊密關(guān)系,并且表示法的使用更加復(fù)雜化。相反,使用單一元素標(biāo)記,并依據(jù)一個 kind 屬性來區(qū)分這些文字,這樣,我們?nèi)钥梢詤^(qū)分浮點型文字和整型文字,而在通常情況下,我們得到的是與 Java 語言類似的數(shù)字類型的靈活性。

  JavaML 對程序語言結(jié)構(gòu)的另一處推廣見之于循環(huán)。for 循環(huán) 和 while 循環(huán)均可視為廣義的循環(huán)結(jié)構(gòu):以 0 或其他值作的初始化值、每次循環(huán)之前進行一次檢測、對 0 或其他值進行更新操作,以及一組包括循環(huán)結(jié)束指令的語句。因此,JavaML 不分別使用 for-loop 和 while-loop 兩個元素類,而是只使用單一的 loop 元素,這個循環(huán)元素具有 kind 屬性,它的值可以是 for 或是 while。當(dāng)轉(zhuǎn)換一個 while 循環(huán)時,它既沒有 initializer,也沒有 update 子元素,而一個 for 循環(huán)可能包含許多 initializer 和 update 子元素。另外, do 循環(huán)所具有的一些獨特的 do-loop 元素仍用于 do 循環(huán),因為 do 循環(huán)把檢測放在循環(huán)的末尾而不是循環(huán)的開始。

  作為另外一個例子,我們把實例字段和類(即靜態(tài)的)字段都表示成具有 static 屬性的 field 元素,以便對它們進行區(qū)分。雖然實例字段和類字段這兩個概念之間的差異遠遠超過 do 循環(huán)和 while 循環(huán)之間的差異,但是用單一元素表示這兩種字段仍然是大有好處的。

  局部變量聲明是一種語法速記,它給我們提出了有關(guān)聲明底層表示的有趣的問題。代碼段 int dx, dy; 定義了兩個 int 類型的變量,但是這個代碼段可能隱隱約約帶有這樣的意思:這兩個變量具有相同的類型。相反,請看一看代碼段 int weight, i;。這段代碼可能就沒有這種暗示的意味,它使用語法速記僅僅是為了語言的簡潔。因為很難自動識別這兩種情況,故對于使用這種速記法的變量聲明語句,JavaML 運用了屬性 continued="true",從而直接保留了這一語法特性。

  在 JavaML 中,處理源代碼中的注釋語句尤其麻煩。目前,DTD 允許某些“重要”元素(包括 class、anonymous-class、interface、method、 field、block、loop)指定一個 comment 屬性。確定將哪些注釋附加到哪些元素上,是一項具有挑戰(zhàn)性的工作;當(dāng)前的實施方案只是簡單地將注釋排隊,并且將上一個“重要”元素指定屬性以來出現(xiàn)的所有注釋,都包含到當(dāng)前這個元素的 comment 屬性中。

  另外一個解決注釋問題的可能方案是,簡單地把注釋語句插入 JavaML 表示法中,在進行語法分析時,注釋語句僅僅作為散布在正常程序結(jié)構(gòu)中的字符數(shù)據(jù),這樣就把語義分析的問題留給了其他軟件工具。遺憾的是,這種方法將使各種元素具有“混合內(nèi)容”,在檢查 DTD 一致性時,驗證能力將會降低。使用 XML 模式 [ 51 ] 來取代 DTD,可以使這種方法更為有效。

  轉(zhuǎn)換器實現(xiàn)

  為了試驗 JavaML 的設(shè)計效果并獲得使用這種表示法的經(jīng)驗,必須實現(xiàn)從 Java 傳統(tǒng)源代碼表示到 JavaML 的轉(zhuǎn)換器。在 IBM Jikes Java 編譯器框架 [ 35 ] 中,我為每個抽象結(jié)構(gòu)樹(AST)節(jié)點都添加了一個 XMLUnparse 方法。這種更改,再加上使用一些小的代碼段來管理用于請求 XML 輸出的選項,形成了一個強健而快速的 JavaML 轉(zhuǎn)換器。我總共向 Jikes 框架添加了大約 1650 行既非注釋也非空行的 C++ 代碼,以支持 JavaML。

  該轉(zhuǎn)換器已經(jīng)測試過,共轉(zhuǎn)換了 15,000 行多種樣本程序,其中包括 4,300 行的 Cassowary Constraint Solving Toolkit [ 5 ] 和各式各樣的 applet [ 50 ] 20 多個。然后,使用 James Clark 的 Jade 軟件包的 nsgmls 工具 [ 12 ],對每個轉(zhuǎn)換的文件做有關(guān) JavaML 的 DTD 驗證。在基于 RedHat6 的雙 Pentium III-450 機器上,整個回歸測試的處理只需要 12 秒鐘。

  此外還實現(xiàn)了 XSLT 樣式表轉(zhuǎn)換,該樣式表輸出了用 JavaML 表示法表示的傳統(tǒng)源代碼。此樣式表由 65 個模板規(guī)則和不到 600 行代碼構(gòu)成。對許多程序是這樣測試(既用 Saxon [ 39] 又用 XT [ 15 ])的:將一個文件轉(zhuǎn)換為 JavaML 文件,再把它轉(zhuǎn)回原文件,然后重新轉(zhuǎn)換為 JavaML 文件 ? 在最后結(jié)果和第一次轉(zhuǎn)換成的 JavaML 文件之間不存在差別。所有的源代碼均可從 JavaML 主頁 [ 4] 獲得。

  利用 XML

  JavaML 將 XML 用作 Java 源程序可供替換的另一種結(jié)構(gòu)化表示法。僅從語法抽象不必考慮 Java 語言的語法細節(jié)這一點來說,已經(jīng)非常方便了;但 JavaML 還有一個更重要的好處:那就是能夠利用為支持 SGML 和 XML 而開發(fā)的豐富的基礎(chǔ)結(jié)構(gòu)。我們可以使用、組合及擴展現(xiàn)有的 SGML 和 XML 工具,而不必從暫存區(qū)構(gòu)建分析和轉(zhuǎn)換工具,來處理程序的專用二進制結(jié)構(gòu)化格式。XML 工具含有豐富的功能部件,這些功能部件包括查詢和轉(zhuǎn)換工具、文檔識別和合并工具 [ 32 ] 以及一些簡單的 API,可直接處理文檔。限于篇幅,本文僅討論三種組合工具的使用:

愛丁堡大學(xué)(Edinburgh University [ 52 ]) 的 XML 工具箱,包含 sgcount、sgrpg、sggrep 等等

  XSLT [ 14] 處理器(例如 XT [ 15] 和 Saxon [ 39 ])和 XML 語法分析器 XP [ 13 ]

  Perl XML:: DOM 軟件包 [ 20 ],向 XML 樹展示了一個 DOM 一 級 [ 2 ] 接口

  這只是在使用 JavaML 時,非常有用的工具的很少一部分。在下面的示例中,我們將查詢 Hangman.java.xml,它是 Hangman applet 的 JavaML 表示,該 applet 可從 Sun Microsystems 的 applet 頁 [ 50 ] 獲得,也可從 JavaML 主頁 [ 4 ] 獲得。雖然從現(xiàn)實世界的標(biāo)準(zhǔn)來看,這些示例不大,但是 XML 工具 和 SGML 工具的目標(biāo)是處理像大部頭的書那么長的程序,所以實現(xiàn)時設(shè)計了很強的可伸縮性。

  軟件工程的一項通用任務(wù)(不論好壞)是積累關(guān)于原文件的標(biāo)準(zhǔn)。借助 JavaML,SGML 實用程序 sgcount 就出色地總結(jié)了 Java 程序的結(jié)構(gòu)(輸出的命令已經(jīng)過刪節(jié)并略加編輯,以便于在此展示):

  % sgcount Hangman.java.xml                   outputs:            arguments 103array-initializer 4assignment-expr 60catch 3class 1if 27true-case 27false-case 7field 28field-access 18import 5java-source-program 1literal-char 5literal-boolean 5literal-null 5literal-number 127literal-string 61local-variable 23loop 13method 18new 4new-array 5return 5send 99type 96var-ref 262var-set 52...   

  在上面的輸出中,每一行列出一個元素類和該元素在文檔中出現(xiàn)的次數(shù)。這樣,我們很容易看出共有 18 個方法元素,因而就有 18 種 method 定義。類似地,我們可以看出有 1 個類定義、262 個變量引用、99 個消息發(fā)送和 61 個字符串文字。此摘要與其說是一個典型的詞法分析(例如代碼行數(shù)字),還不如說是對程序內(nèi)容的說明。

  如果我們想看一看一個程序包含的字符串文字,我們可以在該程序的 JavaML 表示中使用 sggrep 來完成這項瑣碎的工作:

  % sggrep '.*/literal-string' < Hangman.java.xml    outputs:...   

  請注意 sggrep 的輸出仍然是一個(不一定有效,甚至不一定是合式的) XML 文檔。因此,我們可以在 UNIX 的管道中排列 SGML 和 XML 工具,使這些工具以一種新穎的,有用的方式結(jié)合在一起。例如,在某些情況下,把結(jié)果轉(zhuǎn)回普通的 Java 源程序表示是非常必要的,這樣可以幫助我們的軟件工程師。我們可以使用 results-to-plain-source 實現(xiàn)這個功能,results-to-plain-source 是一個圍繞 XSLT 樣式表(該樣式表可以把 JavaML 轉(zhuǎn)回簡單源代碼)的外殼:

  % sggrep '.*/literal-string' < Hangman.java.xml | results-to-plain-source    outputs:"audio/dance.au""img/dancing-duke/T"".gif""img/hanging-duke/h"".gif""Courier""Courier"...   

  也可以根據(jù)元素的屬性在 JavaML 源程序中查詢一個元素。例如,如果想找到所有的消息發(fā)送setFont,可以很容易地得到精確的結(jié)果:

  % sggrep '.*/send[message=setFont]' < Hangman.java.xml         outputs:       

  在這種結(jié)構(gòu)性標(biāo)記中,七個字符 "setFont" 出現(xiàn)的地方有注釋,文本串,或者變量名,但是這些信息都不會在查詢結(jié)果中得到體現(xiàn)。一個類似的操作就是利用詞法工具去檢索信息,其結(jié)果將包含同樣的錯誤的正數(shù)。請試想如果你僅僅使用詞法工具,去查找各種強制類型轉(zhuǎn)換的表達式,將是什么情形 -- Java 表達式中大量使用的括號將使這個工作非常困難,但是,對 JavaML 來說那只是小菜一碟,因為可以使用 cast-expr 元素。

  另外一種常見的分析是,在實現(xiàn)轉(zhuǎn)換之前由編譯器進行語法檢查。例如,在 Java 代碼中,只有抽象類才具有抽象方法。在編譯過程中,如果程序違反了這條規(guī)則,那么編譯器會標(biāo)記一個語法錯誤。我們可以在一個 JavaML 文檔中查詢出包含抽象方法的具體類(也就是非抽象類):

  % sggrep -q '.*/class[abstract!=true]/method[abstract=true]' < Hangman.java.xml

  當(dāng)然,輸出的結(jié)果肯定是空的,因為我們的目標(biāo)文檔(也就是被分析的程序)沒有違反這條語法規(guī)則。

  Java 編程新手經(jīng)常犯的錯誤之一就是,在應(yīng)該使用等值檢測符 == 的地方不小心使用了賦值運算符 =。 雖然在編譯階段中,Java 的類型檢查器可以捕獲絕大部分此類錯誤,但是如果被賦值的變量是 boolean 型變量,那么這種錯誤將會逃過類型檢查器的檢測。如果想發(fā)現(xiàn)這種結(jié)構(gòu)性錯誤,那么 JavaML 中的 sggrep 可以使我們很輕松地完成工作:

  % sggrep -q '.*/if/test/assignment-expr' < Hangman.java.xml

  程序 sgrpg (SGML RePort Generator) 可以把高水平的查詢,對子元素的約束和查詢結(jié)果的輸出格式結(jié)合起來(一個查詢工具的通用語句變化表 [ 24 ])。例如:

  % sgrpg '.*/method' '.*/send[message=drawLine]' '' '%s %s' visibility name < Hangman.java.xml    outputs:public paint   

  可搜索包含消息 drawLine 的消息發(fā)送的方法定義。如上所示,程序立即輸出匹配元素的的 visibility 屬性和 name 屬性,這正好同我們的直覺相符,因為 paint() 是唯一調(diào)用 drawLine 的方法。

  只需利用標(biāo)準(zhǔn)的 XML 工具提供的查詢能力,就可以進行大量的分析。我們能做的其他事情包括從循環(huán)體內(nèi)部的返回,所有整型變量的定義,所有不符合項目命名慣例的字符串變量,等等。

  前面的查詢反映了當(dāng)前 XML 查詢工具的一個缺點: 大多數(shù)反應(yīng)只是對匹配的元素作出的 -- 它們不能提供元素在文檔中出現(xiàn)處的上下文信息。雖然在把 XML 文檔嚴格地看作一個數(shù)據(jù)庫時,這種操作是合適的,但是軟件工程師可能想知道查詢結(jié)果發(fā)生在 JavaML 文件中什么地方,這樣可以把結(jié)果映射回原始文檔,以便對原始文檔進行手工編輯和閱讀。為了闡明 JavaML 中存在的這種困境,我把有關(guān)原始程序代碼結(jié)構(gòu)位置的信息附加在各種元素的屬性中。位置信息包括起始行,終止行以及結(jié)構(gòu)的列數(shù)(文件名放在祖先類的 java-class-file 元素中)。

  除了查詢之外,當(dāng)對軟件產(chǎn)品進行修改和擴展時,轉(zhuǎn)換源代碼是非常有用的。一般來說,查詢工具僅僅是從源文檔中撿出符合條件的元素,或者從多個文檔中撿出幾個元素的組合。功能更為強大的轉(zhuǎn)換工具包括 XSLT [ 14], DSSSL [ 38 ], 或者使用一個能訪問多種語言(例如 Perl, Python, Java, 和 C++ )的 DOM (文件對象模型 Document Object Model) 接口直接處理文檔 [ 2 ]。例如,我們可以直接使用 XSLT 樣式表把所有名為 isBall 的方法重命名為 FIsBall :

  <!-- mostly do an identity transform -->

  執(zhí)行過程如下:

  xt source.java.xml method-rename.xsl oldname=isBall newname=FIsBall

  盡管使用文本編輯器或者 Sed 可以獲得類似的文本轉(zhuǎn)換的結(jié)果,但是這類工具會改過了頭,它們會修改所有順序出現(xiàn) isBall 這六個字符的地方。以文本為基礎(chǔ)的轉(zhuǎn)換可能會錯誤地影響變量名,文本串,注釋和包。而 JavaML 表示的主要優(yōu)點之一是: 我們可以對影響到的結(jié)構(gòu)進行更為精細的,以語義為基礎(chǔ)的控制。

  其他可能的轉(zhuǎn)化包括使用類型表,輸出一個程序的可瀏覽的 HTML 格式的頁面(見圖 3 )或者強調(diào)語法的 PostScript。在函數(shù)的入口和出口增加調(diào)試或者測試代碼也是一件非常容易的事情(見圖 4)。

  圖 3. Hangman.java.xml,經(jīng)過 XSLT HTML 極妙的打印和索引程序處理

  方法索引同每個方法定義的開頭相鏈接,使用彩色編碼和斜體字,可以起到突出語法的顯示效果。

  圖 4. 調(diào)用 Tracer.StartMethod(方法名)和 Tracer.Exitmethod(方法名) 檢測某個 Java 類的所有方法的 Perl 程序

  #!/usr/bin/perl -wuse XML::DOM;use IO::Handle;my $filename = shift @ARGV;my $parser = new XML::DOM::Parser;my $doc = $parser->parsefile ($filename);my $nodes = $doc->getElementsByTagName("method");for (my $i = 0; $i < $nodes->getLength(); $i++){my $method = $nodes->item($i);my $block = $method->getElementsByTagName("block")->item(0);my $name = $method->getAttribute("name");my $start_code= SendMessageBlock($doc,"Tracer","StartMethod", $name);my $exit_code= SendMessageBlock($doc,"Tracer","ExitMethod", $name);$block->insertBefore($start_code, $block->getFirstChild());$block->appendChild($exit_code);}print $doc->toString;sub SendMessageBlock {my ($doc,$target_var,$method_name,$data) = (@_);# insert, e.g: Tracer.StartMethod("paint");return parseXMLFragment($doc,<<"__END_FRAGMENT__"

  相關(guān)工作

  JavaML 的重要優(yōu)點之一,就是它可以利用不斷擴展的同 SGML 和 XML 相關(guān)的軟件工具,作為自己的基礎(chǔ),這些軟件在前面已經(jīng)介紹過。許多研究人員幾乎都采用類似的方法,來解決軟件工程升級和開發(fā)工具升級問題,他們已經(jīng)取得了不同程度的成功。

  通過匹配 C 程序中的抽象結(jié)構(gòu)樹 (AST)模式,TAWK [ 29] 對 AWK [ 21 ] 的語句變化表進行了擴展。許多 XML 查詢工具為 JavaML 提供了相同的功能,而且其中的事件操作框架同 SAX (XML 的簡單 API) [ 43] 使用的框架非常類似。

  ASTLog [ 18] 擴展了 Prolog [ 17 ] 邏輯編程語言,這種語言可以對模擬抽象結(jié)構(gòu)樹(AST)的外部數(shù)據(jù)庫進行推理。與 Prolog 不同,ASTLog 根據(jù)一個當(dāng)前的對象求值。把 Crew 所使用的方法用于 XML 可能非常有趣,但是大量的 XML 工具軟件已經(jīng)按照一種更為傳統(tǒng)(可能不太方便)的框架,提供了相同的功能。

  GRAS [ 40 ] 是一個面向圖像的,用于軟件工程環(huán)境的數(shù)據(jù)庫系統(tǒng)。編譯器的前端可以把普通的 C, Modula-3, 和 Modula-2 程序表示的源代碼整合到數(shù)據(jù)庫中去。這種數(shù)據(jù)庫方法在存儲 XML 方面已經(jīng)證明是非常有用的,尤其是用 JavaML 設(shè)計軟件工程應(yīng)用程序時,數(shù)據(jù)庫方法更是顯示出它的優(yōu)越性。

  軟件開發(fā)基礎(chǔ) (Software Development Foundation [ 46 ]) 基于 XML 的開放式體系結(jié)構(gòu), 它用來設(shè)計編程環(huán)境下的開發(fā)工具。有一種稱為 CSF (代碼結(jié)構(gòu)格式)的 XML 數(shù)據(jù)庫格式,可以用來存儲關(guān)系,但是它不包括任何已經(jīng)執(zhí)行的計算過程的細節(jié)。 Chava [ 41 ] 也采用類似的方法,不過它是以 C 程序數(shù)據(jù)庫為基礎(chǔ)的[ 11 ]。 Chava 也允許通過對字節(jié)代碼執(zhí)行逆向工程來查詢 Java 代碼。

  CCEL [ 22 ] 為 C++ 編寫的軟件產(chǎn)品提供了一種表達非語言意義(也就是說不能用語言表達)的超語言。JavaML 通過以下方法來提供相同的功能:編寫一些簡單的查詢以搜索指定常量的違規(guī),同時在整個開發(fā)周期的各個階段,如編輯,編譯和回歸測試過程中,報告查詢結(jié)果。

  微軟公司的意念編程小組 (Intentional Programming group [ 47 ])一直在努力開發(fā)一種更為抽象的,與具體語法無關(guān)的計算過程表示。他們的目標(biāo)看來是允許軟件開發(fā)人員描述新的抽象方法,并且找到一種技術(shù)使得這些抽象精簡為已知的原語。從本質(zhì)上講,他們感興趣的是讓軟件開發(fā)人員在編寫軟件的過程中創(chuàng)造出域?qū)S玫恼Z言。作為這種方法的一個代表,JavaML 特別令人激動。我們可以把新的抽象方法作為文檔類型定義(DTD)的漸次擴展。為了使新類型的文檔(可以稱為 Java++ML)仍能在已有的 Java 編譯器中編譯,開發(fā)人員只需要簡單地編寫一個從 Java++ML 到 JavaML 的轉(zhuǎn)換。由于 DTD非常容易擴展,因此這種方法應(yīng)該是站得住腳的,而且它很可能為進一步的工作開創(chuàng)富有成果的途徑。運用這種技術(shù)時,有幾種實用程序會有用處,例如 perlSGML 包的 dtd2html 和 dtddiff [ 31],它們用于文檔定義類型(DTD)的文檔編制和比較。

  下一步工作

  雖然本文只是為 Java 語言提供了一種標(biāo)記語言,但是本文提出的基本方法也可以用于其他語言,甚至可以在不同的語言之間進行轉(zhuǎn)換。根據(jù)表示法忽略具體語法細節(jié)進行抽象的程度,JavaML 也可能允許導(dǎo)入可視化表示(例如統(tǒng)一模型語言圖 [ 1][ 35 ])。由于 XSL 和 DSSSL 的強大功能,生產(chǎn)關(guān)于軟件產(chǎn)品重要特性的可視化表示已經(jīng)是指日可待的事情了。

  把本文提出的方法應(yīng)用于 C++ 語言,即另外一個流行的面向?qū)ο蟮木幊陶Z言時,一個非常棘手的問題是 C 語言的預(yù)處理程序。C 語言的預(yù)處理程序首先通過一個文本處理,允許使用那些不能用核心的 C++ 語言表達的抽象。這些抽象對代碼的可理解性和可維護性都非常重要,但是他們同語法分析技術(shù) [ 23][ 6] 不能很好地交互。

  對當(dāng)前轉(zhuǎn)換系統(tǒng)的有益的擴展之一,就是對更多的元素進行橫向鏈接。類型元素可以在其他 JavaML 文件中引用他們定義的類。導(dǎo)入聲明可以為導(dǎo)入的包引用頂層的文檔。還有許多可能性都是行得通的。

  當(dāng)前能把 JavaML 轉(zhuǎn)回傳統(tǒng)源代碼的轉(zhuǎn)換器是基于 XSLT 的。增加一個 Jikes 前端就可以使編譯器直接閱讀 JavaML。為實現(xiàn)這種功能,將使用一個 XML 語法分析器(例如 XML4C++ [ 33 ]),從 JavaML 源代碼構(gòu)建 XML DOM, 然后利用 DOM API 可以很方便地循環(huán)建立 Jikes 內(nèi)部抽象結(jié)構(gòu)樹 (AST)。運用 Jikes 以前就擁有的、傳統(tǒng)的逆向解析器,可以把 JavaML 轉(zhuǎn)回簡單源代碼。

  使用 JavaML 作為主要的源代碼表示將具有簡化編譯器的潛在功能,這不僅僅限于對傳統(tǒng)的前端編譯器進行簡化。一旦編譯器知道輸入的是一份有效的 JavaML 文檔,編譯器就可以省略某些語法分析。如果能說明在給定的條件下不可能出現(xiàn)哪些語法錯誤,那將是非常有用的。由于 XML Schema [ 51][ 7 ] 給出了一套更為精致的 XML 文檔有效性規(guī)范,因此在工作文檔最后確定之后,把 JavaML 而不是 DTD 移植進來將可能非常有益。另外,編輯環(huán)境中可以很方便地以直接查詢的形式(例如前面 "利用 XML" 中給出的一些例子)移入更多的語法分析功能。

  用簡潔的文本表示法書寫源程序是程序員最樂于接受的方法,因此他們不可能在很短的時間拋棄他們心愛的文本編輯器。我們必須研究更好的方法,以實現(xiàn)傳統(tǒng)的源程序表示法和 JavaML 之間的交互式的和漸進式的轉(zhuǎn)換。然后,這種功能就能直接用來支持使用簡單文本格式的 XML 表示的交互式編輯,而簡單文本格式是工程師們情有獨鐘的。關(guān)于結(jié)構(gòu)性文本編輯器,已有大量的工作 [ 30][ 45 ],它們之間有緊密的聯(lián)系,并且最終可望獲得承認,同時提供無限的資源。由于 XML 技術(shù)在商業(yè)上的重要性日益增長,這些資源目前就會用來解決問題。

  結(jié)論

  JavaML 是一個可選的、基于 XML 的 Java 源程序表示。與傳統(tǒng)的文本源程序表示不同,JavaML 可以使軟件工具對 Java 程序中的結(jié)構(gòu),很方便地進行編程水平的分析推理。這是因為 JavaML 可以更為直接地表示程序的結(jié)構(gòu)。

  有了 JavaML,大量既有的 XML 和 SGML 工具就能對 Java 源程序執(zhí)行各種有趣的和有用的分析與轉(zhuǎn)換。XML 工具軟件正在不斷地改進,以支持基于 XML 的文檔的不斷更新的基礎(chǔ)結(jié)構(gòu)。最終,JavaML 將代替 Java 程序的傳統(tǒng)源代碼表示,成為 Java 程序的存儲格式,而在整個程序開發(fā)過程中,當(dāng)開發(fā)人員同軟件產(chǎn)品的結(jié)構(gòu)化表示進行交互時,文本語法分析將僅僅成為幾種可能的途徑之一。

  致謝

  我衷心地感謝 Zack Ives,感謝他的批評,他同我的探討,以及他為我進行的錄入工作。我還要感謝 Corin Anderson 和 Alan Borning,感謝他們對這篇論文初稿提出的寶貴的批評comments。我還要感謝 Miguel Figueroa, Karl-Trygve Kalleberg, Craig Kaplan, Todd Millstein, Stig E. Sand 和 Stefan Bjarni Sigurdsson,感謝他們使我受益匪淺的討論。非常感謝 IBM 構(gòu)建了 Jikes 編譯器框架并把它公之于眾,同時非常感謝 Mike Ernst 指導(dǎo)我如何使用 Jikes 編譯器。以上工作受到了華盛頓大學(xué)計算機科學(xué)與工程系 Wilma Bradley 獎學(xué)金和國家科學(xué)基金第 IIS-9975990 號基金 (NSF Grant No. IIS-9975990)的資助。


向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI