编程语言间的隔阂虽然不如人类语言间的隔阂那么大,但确实是比较困挠程序员的一个问题。如果能通过某种方法实现象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 delphis 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 delphis 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)的标准。关键的互译开始了。