2010-03-24 74 views
5

基本上我不知道從哪裏開始,我需要爲我的應用程序添加一個不太複雜的行腳本,只是爲了執行預定義的命令,例如:小命令行腳本(如Autocad命令)一行編輯器

命令>新建發票 - >創建新發票

命令>的客戶檔案 - >其中卡斯特ID =客戶ID

命令>運行結束日開放客戶形式 - 運行一天結束的過程

command> scr 1020 - >打開表格ID = 1020

我該如何開始? 我沒有推薦任何第三方組件(解析器,評估器等)的問題。

缺少的是基本結構沒有細節,只是一個理論的實現。

感謝, Objectberg

+0

該腳本語言應該有多複雜?如果只是一些相對簡單的命令,你可以使用'TStringList'來解析命令行。 – jpfollenius 2010-03-24 18:03:56

+0

以及它遠離TStringList實現,它有許多可選參數,如: 命令>按名稱查找客戶約翰* 命令>通過電話查找聯繫人0012541 * 因此,您可以看到命令結構是我的考慮點,可能參數的有效性。 我希望它是一個靈活的系統,可以根據我的客戶需求隨時添加\修改命令。 – Objectsberg 2010-03-24 18:29:27

回答

0

你可以看看TCL。這是它的最初目的 - 成爲一個工具命令語言框架,您可以將其嵌入到另一個程序中。 Tcl提供了一個包含變量和控制結構(循環等)的語言語法。您可以添加tcl命令和函數來訪問您的程序功能。

0

第一個問題:如果它是有限數量的罐頭命令,爲什麼不直接使用菜單來實現呢?

但是,如果你想要真正的腳本,你可以插入Delphi的腳本引擎很多。然而,它們大多數都是基於真正的編程語言,這聽起來比你想要的要複雜得多。

如果你想設計自己的簡單腳本語言,你需要一些關於解析器理論的知識。我建議環視GOLD Parser site,它有一些可用的理論信息,還有一些工具可以幫助你設置自己的語言規則。它在該網站上提供了Delphi實現。

+0

嗯,在我的情況下,菜單實現是沒有問題的,因爲需求不在抽象調用中,例如,您必須通過腳本定義客戶ID,菜單不可能通過菜單來打開客戶配置文件表單,然後強制用戶點擊搜索按鈕或手動輸入客戶ID,以及腳本的目的是通過直接在命令行鍵入cust prof 來消除這些步驟。我看着黃金分析器,它是一個很棒的工具,但它超出了我的基本要求。 但無論如何非常感謝您分享您的偉大想法和經驗。 – Objectsberg 2010-03-24 18:21:44

0

我覺得TMS和Greatis有這個腳本。

0

您可以將Python與Python for Delphi集成。如果我沒有記錯,在演示中有「命令行示例」。

0

像你的建議這樣的行腳本不是很難寫,你可以很容易地使用tStringList,將分隔符設置爲空格,設置每行的文本屬性,然後評估第一項和調度剩下的「參數」就行了到一個特定的功能。如果您不符合預期的標準,則處理錯誤情況並停止處理腳本。

如果您尋找的不僅僅是簡單的線腳本,還可以看看PascalScript,它允許您使用熟悉的pascal語言編寫腳本。

2

也許你會喜歡這個,也許不會。但它聽起來實際上也是你想獲得一些基本的理解。您可能會喜歡我認爲的關於如何由Jack Crenshaw編譯編譯器的經典首讀。你可以在this address找到它。它不僅僅是你要找的東西,它是用Turbo Pascal編寫的,敘述實際上很有趣。

好運。

+0

感謝您的鏈接,優秀閱讀 – 2010-03-25 10:28:26

+0

我是一名全職會計和兼職程序員。我一直說會計興奮並不多,但通過閱讀這個「流行機制」的方法來編寫一個編譯器,我真的很興奮。 – jrodenhi 2010-03-25 16:43:44

2

如果它足夠簡單(即使有可選參數),基於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; 

如果你有多個可選參數(例如,FIND CUST BY NAME John AND LASTNAME Smith)然後,而不是硬編碼的StringList偏移就像我之前所做的那樣,刪除了的StringList你每個參數處理它(或將其添加到您的查詢)。這樣,當它是空的時候,你知道你已經完成了這一行,而你只需要看看AArgs[0]看看你是否認出了下一個位。

0

如果您認真對待「自己動手」,請獲取Terence Parr的「The Definitive ANTLR Reference」副本。

這是所有面向Java的,但給解析一個很好的背景,它生成實際上可以理解的解析器代碼。

德爾福產品還有一個商業ANTLR,但我沒有真正嘗試過。