編程語言間的隔閡雖然不如人類語言間的隔閡那麼大,但確實是比較困撓程序員的一個問題。如果能通過某種方法實現象Delphi->c之類的轉換,將是一件引人注目的事情,但這也許並不能使人們花大量的時間來實現這樣的轉換。我們來看,如果你是一個Delphi或C++Builder的高手,你一定做過這兩者間的轉換吧。每天都有大量的人做這類事的事情將帶來多麼大的浪費呀。而且,如果真的有可能實現的話,無疑會為開發智能編程機器積累技術和經驗,給象國產的易語言這類生僻的編程語言更大的生機。為此,我作了一些思考。
首先,我們應當慢慢來。我假設所要面對的是普通的Windows GUI程序,為使用更多的先進技術(大部分的商業軟件就是如此)。因為Windows編程幾乎全部基於Windows API中的函數。所以,有比較好的共性。在選擇轉換技術上我選擇了XML。因為它得到了廣泛的支持,且有很強的擴展性。主題思想如下圖:
V B
||
\ /
\/
XML(面向具體的編程語言,僅僅考慮完善的描述不考慮通用性。
||
\ /
\/
Delphi =====>> XML(同上)====>>>XPML(我瞎編的,一種通用性的程序描述格式,使用XML)…………
/\
/ \
||
||
XML(同上)
/\
/ \
||
||
C++Builder
這種花瓣形的互譯模式,可以減少許多過程。轉換時面對的都是統一的標准格式XPML。簡明可操作。
然後要著手是使編程語言到描述其的XML語言的轉換。我已經坐了一小步,定了一個描述Delphi語言源文件的XML格式,描述了dpr,pas,dfm文件。如下:
<?XML version="1.0" encoding="gb2312"?>
<Delphi>
<project>
<program>Project1
</program>
<uses><name>Forms</name>
</uses>
<uses><name>Unit1</name><path>Unit1.pas</path><comment>Form1</comment>
</uses>
<res>
</res>
<Initialize>
<exp><Application><Initialize></Initialize></Application></exp>
<exp><Application><CreateForm><param>TForm1</param><param>Form1</param></CreateForm></Application></exp>
<exp><Application><Run></Run></Application></exp>
</Initialize>
</project>
<description>
<Unit1>
<Form1 source='TForm1'>
<attribute>
<Left>192</Left>
<Top>107</Top>
<Width>544</Width>
<Height>375</Height>
<Caption>'Hello World'</Caption>
<Color>clBtnFace</Color>
<Font>
<Charset>DEFAULT_CHARSET</Charset>
<Color>clWindowText</Color>
<Height>-11</Height>
<Name>'MS Sans Serif'</Name>
<Style>[]</Style>
</Font>
<OldCreateOrder>False</OldCreateOrder>
<PixelsPerInch>96</PixelsPerInch>
<TextHeight>13</TextHeight>
</attribute>
</Form1>
</Unit1>
</description>
<source>
<Unit1>
<interface>
<uses>Windows
</uses>
<uses>Messages
</uses>
<uses>SysUtils
</uses>
<uses>Classes
</uses>
<uses>Graphics
</uses>
<uses>Controls
</uses>
<uses>Forms
</uses>
<uses>Dialogs
</uses>
</interface>
<implementation>
</implementation>
</Unit1>
</source>
</Delphi>
然後編出具體的代碼,實現這一步的轉換,我也坐了一小步,實現了dpr->XML的一部分,即轉換工程名,Uses段和資源段,初始化段上為實施。如下,程序使用Windows Scripting Host寫的,很業余,運行請保存為*.JS雙擊即可。
// Windows Script Host to convert Delphi's project file into XML file
//
// ------------------------------------------------------------------------
// Copyright (C) 2001 hcstudio
//
// You have a royalty-free right to use, modify, reproduce and distribute
// the Application Files (and/or any modifIEd version) in any way
// you find useful, provided that you agree that hcstudio has no warranty,
// obligations or liability for any Application Files.
// ------------------------------------------------------------------------
// This script will convert Delphi's project file into XML file.
var source;
var program,uses,resource;
var program=new Array();
var uses = new Array();
filename="Project1.dpr";
source=ReadFile(filename);
program=FindProgram(source);
uses=FindUses(program[1]);
resource=FindResource(uses[uses.length-1]);
program=program[0];
CreateXML(program,uses,resource);
//////////////////////////////////////////////////////////////////////////////////
//
// ReadFile to parse and return the file content as string
//
function ReadFile(filename)
{
var fso,file,stream,source;
fso = new ActiveXObject("Scripting.FileSystemObject");
file = fso.GetFile(filename);
stream = file.OpenAsTextStream(1,-2);
source=stream.readall();
return(source);
}
//////////////////////////////////////////////////////////////////////////////////
//
// Find the Program name and return the rest
//
function FindProgram(source)
{
var program,next,uptarget,downtarget,up,down;
var toReturn;
uptarget=/program/;
downtarget=/;/;
up=source.search(uptarget);
down=source.search(downtarget);
program=source.substring(up,down);
uptarget=/\s/;
up=program.search(uptarget);
program=program.slice(up);
next=source.slice(down+1);
var toReturn=new Array();
toReturn[0]=program;
toReturn[1]=next;
return(toReturn);
}
//////////////////////////////////////////////////////////////////////////////////
//
// A group of function to find uses
//
function FindUses(source)
{
var uses;
uses=new Array();
var Uses,uptarget,downtarget,up,down;
uptarget=/uses/;
downtarget=/;/;
up=source.search(uptarget);
down=source.search(downtarget);
Uses=source.substring(up,down);
uptarget=/\s/;
up=Uses.search(uptarget);
Uses=Uses.slice(up);
uses=FindUsesDetail(Uses);
next=source.slice(down+1);
uses[uses.length]=next;
return(uses);
}
function FindUsesDetail(Uses)
{
var auses,first,second,ifin,ifleft,ifright,i;
first=new Array();
auses=new Array();
first=Uses.split(",");
ifin=/\sin\s/;
ifleft=/'*'/;
ifright=/\./;
for(i=0;i<first.length;i++)
{
if(first[i].search(ifin)==-1)
{
auses[i*2]=first[i];
auses[i*2+1]=0;
}
else
{
auses[i*2]=first[i].substring(0,first[i].search(ifin));
auses[i*2+1]=first[i].substring(first[i].search(ifleft)+1,first[i].search(ifright)+4);
}
}
return(auses);
}
//////////////////////////////////////////////////////////////////////////////////
//
// Find the Resource and return the next
//
function FindResource(source)
{
var ifres,resource, j,found;
ifres=/{/;
var resource=new Array();
j=0;
do
{
if(found!=-1)
{
found=source.search(ifres);
resource[j]=source.substring((found+3),source.search(/}/));
j++;
source=source.slice(source.search(/}/)+1);
}
}
while (found!=-1);
resource[resource.length]=source;
return(resource);
}
//////////////////////////////////////////////////////////////////////////////////
//
// to createXML file using program,uses(array of string)
//
function CreateXML(program,uses,resource)
{
var filename;
filename="Delphi.XML";
WriteFlag(filename);
var i;
var xmlDoc = new ActiveXObject("MsXML2.DOMDocument");
XMLDoc.load(filename);
var rootElement=XMLDoc.createElement("Delphi");
var projectElement=XMLDoc.createElement("Project");
var programElement=XMLDoc.createElement("program");
var programElementText=XMLDoc.createTextNode(program);
programElement.appendChild(programElementText);
projectElement.appendChild(programElement);
for(i=0;i<uses.length-1;i=i+2)
{
var usesElement=XMLDoc.createElement("uses");
var usesnameElement=XMLDoc.createElement("name");
var usespathElement=XMLDoc.createElement("path");
var usesnameElementText=XMLDoc.createTextNode(uses[i]);
var usespathElementText=XMLDoc.createTextNode(uses[i+1]);
usesnameElement.appendChild(usesnameElementText);
usespathElement.appendChild(usespathElementText);
usesElement.appendChild(usesnameElement);
usesElement.appendChild(usespathElement);
projectElement.appendChild(usesElement);
}
for(i=0;i<resource.length-2;i++)
{
var resourceElement=XMLDoc.createElement("resource");
var resourceElementText=XMLDoc.createTextNode(resource[i]);
resourceElement.appendChild(resourceElementText);
projectElement.appendChild(resourceElement);
}
rootElement.appendChild(projectElement);
XMLDoc.appendChild(rootElement);
XMLDoc.save(filename);
}
function WriteFlag(filename)
{
var fso,file,stream,source;
fso = new ActiveXObject("Scripting.FileSystemObject");
file = fso.CreateTextFile(filename,true);
file.WriteLine("<?XML version=\"1.0\" encoding=\"gb2312\"?>");
file.Close();
}
//////////////////////////////////////////////////////////////////////////////////
//
// for debug use
//
function Display(program)
{
var WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Popup(program);
}
最後綜合各種語言的XML描述形式,定出XPML(Extensive Programming Markup Language)的標准。關鍵的互譯開始了。