Delphi 小型命令行脚本编写器(如Autocad命令)单行编辑器
基本上我不知道从哪里开始,我需要为我的应用程序添加一个不太复杂的行脚本,只是为了执行预定义的命令,例如: 命令>新发票-->创建新发票 命令>客户配置文件-->打开客户表单,其中客户id=客户id 命令>运行日终-运行日终流程 命令>scr 1020-->打开表单id=1020 我怎么开始? 我没有问题推荐任何第三方组件(解析器、计算器等) 缺少的是基本结构,没有细节,只是一个实现的理论 谢谢,Delphi 小型命令行脚本编写器(如Autocad命令)单行编辑器,delphi,delphi-2010,Delphi,Delphi 2010,基本上我不知道从哪里开始,我需要为我的应用程序添加一个不太复杂的行脚本,只是为了执行预定义的命令,例如: 命令>新发票-->创建新发票 命令>客户配置文件-->打开客户表单,其中客户id=客户id 命令>运行日终-运行日终流程 命令>scr 1020-->打开表单id=1020 我怎么开始? 我没有问题推荐任何第三方组件(解析器、计算器等) 缺少的是基本结构,没有细节,只是一个实现的理论 谢谢, Objectberg您可以看看tcl。这就是它最初的目的——成为一个可以嵌入到另一个程序中的工具命令
Objectberg您可以看看tcl。这就是它最初的目的——成为一个可以嵌入到另一个程序中的工具命令语言框架。Tcl提供了一种带有变量和控制结构(循环等)的语言语法。您可以添加tcl命令和函数来访问程序的功能。第一个问题:如果是有限数量的固定命令,为什么不使用菜单来实现它 但是如果你想要真正的脚本,有很多脚本引擎可以插入Delphi。不过,它们中的大多数都是基于真正的编程语言,这听起来比您要寻找的要复杂一些
如果你想设计自己的简单脚本语言,你需要一些关于解析器理论的知识。我建议您浏览一下,它提供了一些理论信息,还有一些工具可以帮助您建立自己的语言规则。它在站点上有一个Delphi实现。我认为TMS和Greatis为此提供了脚本。您可以将Python与。如果我没记错的话,在演示中有一个“命令行示例”。像你建议的那样的行脚本编写并不难,你可以很容易地使用tStringList,将分隔符设置为空格,为每行设置文本属性,然后计算第一项并分派其余的“参数”在特定函数的行上。如果不符合预期条件,则处理错误条件并停止处理脚本
如果您正在寻找的不仅仅是一个简单的行脚本编写器,请看一看,它允许您使用熟悉的pascal语言编写脚本。也许您会喜欢,也许不会。但听起来你也希望得到一些基本的理解。你可能会喜欢Jack Crenshaw关于如何构建编译器的经典初读。你可以在。它不仅仅是你想要的,但是它是用turbopascal写的,而且它的叙述读起来很有趣
祝你好运。如果它足够简单(即使有可选参数),那么基于TStringList的东西实际上可以正常工作。下面是一个简单的示例,让您开始学习:
type
TCommandRec = record
Command: string;
Proc: array(AArgs: TStringList);
end;
const
Commands: array(0..4) of TCommandRec = (
(Command: 'New'; Proc: DoNew),
(Command: 'Customer'; Proc: DoCustomer),
(Command: 'Run'; Proc: DoRun),
(Command: 'Scr'; Proc: DoScr),
(Command: 'Find'; Proc: DoFind));
procedure RunScript(const AFileName: string);
var
Script, Args: TStringList;
i, j: Integer;
begin
Script := TStringList.Create;
try
Script.LoadFromFile(AFileName);
Args := TStringList.Create;
try
Args.Delimiter := ' ';
for i := 0 to Script.Count - 1 do begin
Args.DelimitedText := Script[i];
for j := Low(Commands) to High(Commands) do
if SameText(Args[0], Commands[j].Command) then begin
Commands[j].Proc(Args);
Break;
end;
end;
finally
Args.Free;
end;
finally
Script.Free;
end;
end;
procedure DoRun(AArgs: TStringList);
begin
if SameText(AArgs[1], 'End-of-day') then
RunEndOfDayProcess
else if SameText(AArgs[1], 'Hourly') then
RunHourlyProcess
else
raise EInvalidScript.Create;
end;
procedure DoFind(AArgs: TStringList);
var
FindType: string;
begin
if (AArgs.Count <> 5) or not SameText(AArgs[2], 'by') then
raise EInvalidScript.Create;
if SameText(AArgs[1], 'Cust') then begin
if SameText(AArgs[3], 'Name') then
FindCustomer(AArgs[4], '')
else if SameText(AArgs[3], 'LastName') then
FindCustomer('', AArgs[4])
end
else if SameText(AArgs[1], 'Contact') then begin
...
end
else
raise EInvalidScript.Create;
end;
类型
t命令=记录
命令:字符串;
过程:数组(AArgs:TStringList);
结束;
常数
命令:TCommandRec的数组(0..4)=(
(命令:“新建”;程序:DoNew),
(命令:“客户”;过程:DoCustomer),
(命令:“Run”;进程:DoRun),
(命令:“Scr”;过程:DoScr),
(命令:“Find”;Proc:DoFind));
过程RunScript(const AFileName:string);
变量
脚本,Args:TStringList;
i、 j:整数;
开始
脚本:=TStringList.Create;
尝试
Script.LoadFromFile(AFileName);
Args:=TStringList.Create;
尝试
参数分隔符:='';
对于i:=0的脚本。计数-1是否开始
Args.DelimitedText:=脚本[i];
对于j:=低(命令)到高(命令)do
如果是SameText(参数[0],命令[j].Command),则开始
命令[j].Proc(Args);
打破
结束;
结束;
最后
Args.Free;
结束;
最后
脚本。免费;
结束;
结束;
程序DoRun(AArgs:TStringList);
开始
如果是SameText(AArgs[1],“一天结束”),那么
runendofday过程
否则,如果SameText(AArgs[1],“Hourly”)则
运行时进程
其他的
提高EInvalidScript.Create;
结束;
程序DoFind(AArgs:TStringList);
变量
FindType:字符串;
开始
如果(AArgs.Count 5)或不相同的文本(AArgs[2],“by”),则
提高EInvalidScript.Create;
如果是SameText(AArgs[1],“Cust”),则开始
如果是SameText(AArgs[3],“Name”),那么
FindCustomer(AArgs[4],'')
否则,如果SameText(AArgs[3],“LastName”),则
FindCustomer(“”,AArgs[4])
结束
否则,如果SameText(AArgs[1],“Contact”),则开始
...
结束
其他的
提高EInvalidScript.Create;
结束;
如果您有多个可选参数(例如,FIND CUST BY NAME John AND LASTNAME Smith
),则不要像上面那样硬编码stringlist偏移量,而是在处理时从stringlist中删除每个参数(或将其添加到查询中)。这样,当它是空的时,你就知道你已经完成了这一行,你只需要看看AArgs[0]
,看看你是否能认出下一位。如果你真的想“自己滚”,那就买一本特伦斯·帕尔的《最终的ANTLR参考》
它完全是面向Java的,但为解析提供了良好的背景,并生成了实际上可以理解的解析器代码
还有一个针对Delphi产品的商业ANTLR,但我还没有真正尝试过它。该脚本语言应该有多复杂?如果只是几个相对简单的命令,那么您可以使用
TStringList
来解析命令行,它有许多可选参数,如:command>Find Cust by Name John*command>Find Contact by phone 0012541*,因此您可以看到,命令结构是我考虑的重点和可能参数的有效性。我希望它是一个灵活的系统,我可以根据客户的需要动态添加\修改命令。菜单的实现在我的情况下是不可能的