用XML实现编程语言间的互译(中级版)(转帖)(5分)

  • 主题发起人 主题发起人 taowen
  • 开始时间 开始时间
T

taowen

Unregistered / Unconfirmed
GUEST, unregistred user!
编程语言间的隔阂虽然不如人类语言间的隔阂那么大,但确实是比较困挠程序员的一个问题。如果能通过某种方法实现象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/;
do
wntarget=/;/;
up=source.search(uptarget);
do
wn=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/;
do
wntarget=/;/;
up=source.search(uptarget);
do
wn=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.search(ifin)==-1)
{
auses[i*2]=first;
auses[i*2+1]=0;
}
else
{
auses[i*2]=first.substring(0,first.search(ifin));
auses[i*2+1]=first.substring(first.search(ifleft)+1,first.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);
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);
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)的标准。关键的互译开始了。
这里面,问题多多。越想越迷茫,所以贴出来,请高手指点一二。小弟在此谢过了!toowiner@163.com
 
越看越迷茫
 
可喜可贺——俺也在研究编程语言的互译问题,不过我认为时下Delphi,C++,Java的互译是比较现实的,
至于Basic,它和前面的编程语言相差太多,难度太大了。
http://www.smiling.com.cn/group/posts/view_forum.ecgi?group_id=20448&amp;res_message_id=3
 
对于代码重用性的追求,一直是计算机界的一个重要努力方向。
大概有几种方向
一 是源代码级重用,主要体现在类库、ApplicationFramework(应用程序框架)的建设。
比如 VCL,MFC等。这类实现的机制和大规模的实际使用,主要依赖面对对象(OO)
的发展成果。
二 是在两进制代码级别的重用,这需要一些实现规范。实际应用的有com,cobra。
三 制订一些轻量级的调用规范,实际应用的有soap。
就tuti看来,这个中间语言的构想,基本无实现可能。
因为程序所编辑的代码,其实只是一部分。很多东西是由编译器或者应用程序框架实现的。
现在实际使用中实现多语言的,只有C++bulider 支持delphi.这是由于两者本来就是同一
公司产品,更重要的是所用的ApplicationFramework是同一套,即VCL。
而要做到跨编译器、跨类库实现源代码重用几乎不可能。做到一些,也会局限性很大。
而要在二进制重用,看看com规范,就知道有多麻烦了。

 
多人接受答案了。
 
后退
顶部