Delphi 小型命令行脚本编写器(如Autocad命令)单行编辑器

Delphi 小型命令行脚本编写器(如Autocad命令)单行编辑器,delphi,delphi-2010,Delphi,Delphi 2010,基本上我不知道从哪里开始,我需要为我的应用程序添加一个不太复杂的行脚本,只是为了执行预定义的命令,例如: 命令>新发票-->创建新发票 命令>客户配置文件-->打开客户表单,其中客户id=客户id 命令>运行日终-运行日终流程 命令>scr 1020-->打开表单id=1020 我怎么开始? 我没有问题推荐任何第三方组件(解析器、计算器等) 缺少的是基本结构,没有细节,只是一个实现的理论 谢谢, Objectberg您可以看看tcl。这就是它最初的目的——成为一个可以嵌入到另一个程序中的工具命令

基本上我不知道从哪里开始,我需要为我的应用程序添加一个不太复杂的行脚本,只是为了执行预定义的命令,例如:

命令>新发票-->创建新发票

命令>客户配置文件-->打开客户表单,其中客户id=客户id

命令>运行日终-运行日终流程

命令>scr 1020-->打开表单id=1020

我怎么开始? 我没有问题推荐任何第三方组件(解析器、计算器等)

缺少的是基本结构,没有细节,只是一个实现的理论

谢谢,
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*,因此您可以看到,命令结构是我考虑的重点和可能参数的有效性。我希望它是一个灵活的系统,我可以根据客户的需要动态添加\修改命令。菜单的实现在我的情况下是不可能的