スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

F#雑記 SimpleFormConverter(3)

 前回からの続きです。 
 
前回までで 
 
前略 
/* 32*/            this.conv_btn = new System.Windows.Forms.Button(); 
/* 33*/            this.result_rtb = new System.Windows.Forms.RichTextBox(); 
/* 34*/            this.to_clip_btn = new System.Windows.Forms.Button(); 
/* 35*/            this.error_rtb = new System.Windows.Forms.RichTextBox(); 
/* 36*/            this.label1 = new System.Windows.Forms.Label(); 
/* 37*/            this.SuspendLayout(); 
/* 38*/            //  
/* 39*/            // load_btn 
/* 40*/            //  
/* 41*/            this.load_btn.Location = new System.Drawing.Point(21, 12); 
/* 42*/            this.load_btn.Name = "load_btn"; 
/* 43*/            this.load_btn.Size = new System.Drawing.Size(75, 23); 
後略 
 
とう形のテキストと、これを変換した、 
 
* 39*/            mainForm.SuspendLayout(); 
/* 40*/            //  
/* 41*/            // label1 
/* 42*/            //  
/* 43*/            label1.AutoSize = true; 
/* 44*/            label1.Location = new System.Drawing.Point(290, 166); 
/* 45*/            label1.Name = "label1"; 
中略 
/*144*/            // mainForm 
/*145*/            //  
/*146*/            mainForm.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); 
/*147*/            mainForm.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 
/*148*/            mainForm.ClientSize = new System.Drawing.Size(838, 469); 
/*149*/            mainForm.Controls.Add(cls_btn); 
/*150*/            mainForm.Controls.Add(result_rtb); 
/*151*/            mainForm.Controls.Add(Convert_btn); 
/*152*/            mainForm.Controls.Add(groupBox1); 
中略 
/*163*/            mainForm.PerformLayout(); 
/*164*/        } 
後略 
 
という名前のテキストが oriTextとformFlattenTextに割り付け、 
getConstractStrs oriText formFlattenTextという形でコンストラクタ関連の文 
  "let load_btn= new Button(Location = new Point(21, 12),Name = "load_btn",Size = new Size(75, 23),TabIndex = 0,Text = "Load",UseVisualStyleBackColor = true) 
let ori_source_rtb= new RichTextBox(Location = new Point(21, 41),Name = "ori_source_rtb",Size = new Size(819, 178),TabIndex = 1,Text = "") 
を得るところまで実装しました。 
今回はメソッド関連を実装します。 
ただフォーム、ボタン類等では、初期化部分でレイアウトや、コントロールへのコンポーネントの追加以外でメソッドが使われることがないので、今回はMenuStripとListBoxを追加し、さらにこれらにItemを追加したものを準備して、これに対して変換を考えます。 
 
さてフラット化されたコードで、MenuStrip,ListBoxでメソッドが呼び出されている部分を抜き出してみます。 
 
/* 55*/            //  
/* 56*/            // menuStrip1 
/* 57*/            //  
/* 58*/            menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 
/* 59*/            openToolStripMenuItem, 
/* 60*/            endToolStripMenuItem}); 
/* 66*/            //  
/* 67*/            // openToolStripMenuItem 
/* 68*/            //  
/* 69*/            openToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { 
/* 70*/            readToolStripMenuItem, 
/* 71*/            read2ToolStripMenuItem}); 
/*121*/            //  
/*122*/            // listBox1 
/*123*/            //  
/*126*/            listBox1.Items.AddRange(new object[] { 
/*127*/            "りんご", 
/*128*/            "いちご"}); 
 
 
まずフラット化されたソースとコントロール名を与えて、メソッド名(プロパティ含む)と引数を抽出する関数を定義します。 
> let getEachMethodStr (flatten_source:string) (contName:string)  = 
     let rgStr =  contName+"\.(?<MethodName>(\w|\.)+?)\(\s*(?<argValue>(.|\n)*?)\)\;" 
     let rg = new Regex (rgStr) 
     let matchCol = rg.Matches (flatten_source) 
     let methodNameArgValSeq = 
         seq{ 
            for mc in matchCol do 
                yield ( (mc.Groups.["MethodName"].Value).Trim(), "(" + (mc.Groups.["argValue"].Value).Trim() + ")") 
        } 
     methodNameArgValSeq 
     |> Seq.filter (fun (name,_) -> (not (name.Contains "SuspendLayout")) &&  
                                    (not (name.Contains "Controls.Add")) && 
                                    (not (name.Contains "PerformLayout")) && 
                                    (not (name.Contains "ResumeLayout")));; 
 
val getEachMethodStr : string -> string -> seq<string * string> 
 
テストしてみます。 
> getEachMethodStr formFlattenText "listBox1";; 
val it : seq<string * string> = 
  seq 
    [("Items.AddRange", 
      "(new object[] { 
            "りんご", 
            "いちご"})")] 
             
 
> getEachMethodStr formFlattenText "menuStrip1";; 
val it : seq<string * string> = 
  seq 
    [("Items.AddRange", 
      "(new System.Windows.Forms.ToolStripItem[] { 
            openToolStripMenuItem, 
            endToolStripMenuItem})")] 
 
引数と、メソッド名(プロパティ含む)が抽出できています。ただ、配列の定義はこのままではF#では使えないので、さらにこれを変換する関数を後で定義します。 
 
次に、すべてのコントロールを取り出した上でメソッド部分を変換していく関数を次に定義します。 
 
> let getMethodStrs (ori_source:string) (flatten_source:string) = 
    let sb = new System.Text.StringBuilder() 
    for (name,_) in Seq.append (getControlNamesAndType ori_source) (seq[(getFormName ori_source , "Form")]) do 
        for (methodName,arg) in (getEachMethodStr flatten_source name) do 
        sb.Append(name + "." +  methodName + arg +  "|>ignore \n") |> ignore     
    sb.ToString();; 
 
val getMethodStrs : string -> string -> string 
 
テストしてみます。 
 
> getMethodStrs oriText formFlattenText;; 
val it : string = 
  "menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 
            openToolStripMenuItem, 
            endToolStripMenuItem})|>ignore  
openToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { 
            readToolStripMenuItem, 
            read2ToolStripMenuItem})|>ignore  
listBox1.Items.AddRange(new object[] { 
            "りんご", 
            "いちご"})|>ignore  
 
では最後に配列部分をF#の形式に変換する関数を定義します。 
 
 
> let replaceSub (matchResult :System.Text.RegularExpressions.Match) = 
    let tempRes = "( [|" + matchResult.Groups.["part2"].Value + "|] :" +  matchResult.Groups.["part1"].Value + "[]))" 
    tempRes 
    |> myReplace "," ";" 
    |> myReplace "\n" "" 
    |> myReplace "System.Windows.Forms." "" 
    |> myReplace "\s+" " " 
    |> myReplace "object" "obj" 
 
let arrPartsReplace (source:string) = 
    let rg = new Regex("new\s+(?<part1>[\w\.]+?)\[\]\s*\{(?<part2>(.|\n)+?)\}\)") 
    rg.Replace(source, new MatchEvaluator(replaceSub));; 
 
val replaceSub : Match -> string 
val arrPartsReplace : string -> string 
(replaceSubはarrPartsReplaceの補助関数です。) 
 
テストしてみます。 
 
> arrPartsReplace (getMethodStrs oriText formFlattenText);; 
val it : string = 
  "menuStrip1.Items.AddRange(( [| openToolStripMenuItem; endToolStripMenuItem|] :ToolStripItem[]))|>ignore  
openToolStripMenuItem.DropDownItems.AddRange(( [| readToolStripMenuItem; read2ToolStripMenuItem|] :ToolStripItem[]))|>ignore  
listBox1.Items.AddRange(( [| "りんご"; "いちご"|] :obj[]))|>ignore  
 
次回はControl.Add部分の変換部分を実装して完成まで持っていきます。 
 
ここまでのコードは以下の通りです。 
 
open System 
open System.Text.RegularExpressions 
open System.Windows.Forms 
open System.Drawing 
 
//広域変数///////////////////////// 
let mutable oriText = "" 
let mutable formFlattenText = "" 
 
let getFormName (ori_source:string) = 
    let rg = new Regex("this.Name = \"(?<FormName>[\w]+)") 
    let matched = rg.Match(ori_source) 
    (matched.Groups.["FormName"].Value).Trim() 
 
 
let getControlNamesAndType (ori_source:string) = 
    let rg = new Regex("private\s+(?<typeOfComp>[\w|\.]+)\s+(?<name>[\w\.]+)\;") 
    let matchCol = rg.Matches(ori_source) 
    seq{ 
        for mc in matchCol do 
            yield ((mc.Groups.["name"].Value).Trim(), (mc.Groups.["typeOfComp"].Value).Trim()) 
        }   
 
let myReplace (regStr:string) (repStr:string) (oriSrcStr:string)= 
    (new Regex(regStr)).Replace(oriSrcStr,repStr) 
 
let getFlattenSource (ori_source:string) = 
    (getControlNamesAndType ori_source) 
    |> Seq.fold(fun str (name,_)  ->let replacePart = "this." + name 
                                    let newWord = "that." + name 
                                    myReplace replacePart newWord str 
                ) 
                ori_source 
    |> myReplace "this." ("this." + (getFormName ori_source) + ".")  
    |> myReplace "this." ""  
    |> myReplace "that." ""  
 
// getPropNameValueEqualStr フラットソーステキスト "load_btn";;で 
// seq    ["Location = new System.Drawing.Point(21, 12)"; "Name = "load_btn""; 
//         "Size = new System.Drawing.Size(75, 23)"; "TabIndex = 0"; ...]が返る 
let getPropNameValueEqualStr (flatten_source:string) (contName:string)  = 
     let rgStr =  contName+"\.(?<PropName>[^\s=]+?)\s*=\s*(?<PropValue>(.|\n)+?)\;" 
     let rg = new Regex (rgStr) 
     let matchCol = rg.Matches (flatten_source) 
     seq{ 
        for mc in matchCol do 
            yield ( (mc.Groups.["PropName"].Value) + " = " + (mc.Groups.["PropValue"].Value)) 
    } 
//let load_btn= new Button(Location = new Point(21, 12),Name = "load_btn",Size = new Size(75, 23),TabIndex = 0,Text = "Load",UseVisualStyleBackColor = true) 
//let ori_source_rtb= new RichTextBox(Location = new Point(21, 41),Name = "ori_source_rtb",Size = new Size(819, 178),TabIndex = 1,Text = "") 
let getConstractStrs (ori_source:string) (flatten_source:string) = 
    let sb = new System.Text.StringBuilder() 
    for (name,ptype) in Seq.append (getControlNamesAndType ori_source) (seq[(getFormName ori_source , "Form")]) do 
        let propNameValueEqualStrSeq = (getPropNameValueEqualStr flatten_source name)  
        let joinedStr = String.Join (",", propNameValueEqualStrSeq) 
        sb.Append("let " + name + "= " + "new " + ptype + "(" + joinedStr + ")" + "\n") |>ignore     
    sb.ToString() |> myReplace "System.Windows.Forms." "" |> myReplace "System.Drawing." "" 
 
//  seq [("Items.AddRange", 
//         "(new object[] { 
//              "りんご", 
//             "いちご"})")]等が返る 
let getEachMethodStr (flatten_source:string) (contName:string)  = 
     let rgStr =  contName+"\.(?<MethodName>(\w|\.)+?)\(\s*(?<argValue>(.|\n)*?)\)\;" 
     let rg = new Regex (rgStr) 
     let matchCol = rg.Matches (flatten_source) 
     let methodNameArgValSeq = 
         seq{ 
            for mc in matchCol do 
                yield ( (mc.Groups.["MethodName"].Value).Trim(), "(" + (mc.Groups.["argValue"].Value).Trim() + ")") 
        } 
     methodNameArgValSeq 
     |> Seq.filter (fun (name,_) -> (not (name.Contains "SuspendLayout")) &&  
                                    (not (name.Contains "Controls.Add")) && 
                                    (not (name.Contains "PerformLayout")) && 
                                    (not (name.Contains "ResumeLayout"))) 
 
//"menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 
//            openToolStripMenuItem, 
//            endToolStripMenuItem})|>ignore  
//openToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {......が返る 
let getMethodStrs (ori_source:string) (flatten_source:string) = 
    let sb = new System.Text.StringBuilder() 
    for (name,_) in Seq.append (getControlNamesAndType ori_source) (seq[(getFormName ori_source , "Form")]) do 
        for (methodName,arg) in (getEachMethodStr flatten_source name) do 
        sb.Append(name + "." +  methodName + arg +  "|>ignore \n") |> ignore     
    sb.ToString()  
 
//配列部分の変換関数 
let replaceSub (matchResult :System.Text.RegularExpressions.Match) = 
    let tempRes = "( [|" + matchResult.Groups.["part2"].Value + "|] :" +  matchResult.Groups.["part1"].Value + "[]))" 
    tempRes 
    |> myReplace "," ";" 
    |> myReplace "\n" "" 
    |> myReplace "System.Windows.Forms." "" 
    |> myReplace "\s+" " " 
    |> myReplace "object" "obj" 
 
let arrPartsReplace (source:string) = 
    let rg = new Regex("new\s+(?<part1>[\w\.]+?)\[\]\s*\{(?<part2>(.|\n)+?)\}\)") 
    rg.Replace(source, new MatchEvaluator(replaceSub)) 
 
 
let f2c x = x :> System.Windows.Forms.Control  
let load_btn= new Button(Location = new Point(21, 12),Name = "load_btn",Size = new Size(75, 23),TabIndex = 0,Text = "Load",UseVisualStyleBackColor = true) 
let ori_source_rtb= new RichTextBox(Location = new Point(21, 41),Name = "ori_source_rtb",Size = new Size(819, 178),TabIndex = 1,Text = "") 
let conv_btn= new Button(Location = new Point(21, 225),Name = "conv_btn",Size = new Size(144, 54),TabIndex = 2,Text = "Convert",UseVisualStyleBackColor = true) 
let result_rtb= new RichTextBox(Location = new Point(21, 285),Name = "result_rtb",Size = new Size(819, 254),TabIndex = 4,Text = "") 
let to_clip_btn= new Button(Location = new Point(744, 225),Name = "to_clip_btn",Size = new Size(96, 54),TabIndex = 3,Text = "To Clipborad",UseVisualStyleBackColor = true) 
let error_rtb= new RichTextBox(Location = new Point(173, 241),Name = "error_rtb",Size = new Size(553, 38),TabIndex = 5,TabStop = false,Text = "") 
let label1= new Label(AutoSize = true,Location = new Point(171, 222),Name = "label1",Size = new Size(30, 12),TabIndex = 6,Text = "Error") 
let mainForm= new Form(AutoScaleDimensions = new SizeF(6.0f, 12.0f),AutoScaleMode = AutoScaleMode.Font,ClientSize = new Size(864, 570),Name = "minForm",Text = "SimpleFormConverter Ver0.01") 
[ f2c label1; f2c error_rtb; f2c to_clip_btn; f2c result_rtb; f2c conv_btn; f2c ori_source_rtb; f2c load_btn] |> List.iter(fun cnt -> mainForm.Controls.Add cnt) 
 
load_btn.Click.Add 
    (fun _ -> try 
                let ofd = new OpenFileDialog(Filter = "Designer.csファイル(*.Designer.cs)|*.Designer.cs|すべてのファイル(*.*)|*.*") 
                if(ofd.ShowDialog() = DialogResult.OK) then 
                    use sr = new System.IO.StreamReader(ofd.FileName) 
                    ori_source_rtb.Text <- sr.ReadToEnd() 
                    oriText <- ori_source_rtb.Text 
                    formFlattenText <- getFlattenSource oriText 
              with 
                | ex -> error_rtb.Text <- ex.Message  
    ) 
 
 
conv_btn.Click.Add 
    (fun _ -> try 
                   result_rtb.Text <- getConstractStrs oriText formFlattenText 
              with 
                | ex -> error_rtb.Text <- ex.Message  
    ) 
 
mainForm.Show()
 
スポンサーサイト

テーマ : プログラミング
ジャンル : コンピュータ

コメントの投稿

非公開コメント

プロフィール

T GYOUTEN

Author:T GYOUTEN
F#と英単語とフリーソフトと読書に興味があります。
ホームページでフリーソフトも公開しています。どぞ御贔屓に。

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
フリーエリア
フリーエリア
blogram投票ボタン
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。