Browse Source

utility: init

gretmn102 3 years ago
parent
commit
11bda224cc
11 changed files with 276 additions and 19 deletions
  1. 2 0
      .gitignore
  2. 4 3
      .vscode/tasks.json
  3. 3 0
      Test/Test.fsproj
  4. 9 0
      Utility/App.config
  5. 168 0
      Utility/Program.fs
  6. 19 0
      Utility/README.md
  7. 23 0
      Utility/Utility.fsproj
  8. 2 0
      Utility/paket.references
  9. 15 16
      build.fsx
  10. 1 0
      paket.dependencies
  11. 30 0
      paket.lock

+ 2 - 0
.gitignore

@@ -396,3 +396,5 @@ paket-files/
 /Utils/
 
 /Test/Mocks/
+
+/RunUtils.cmd

+ 4 - 3
.vscode/tasks.json

@@ -18,13 +18,14 @@
             "problemMatcher": []
         },
         {
-            "label": "build&run",
+            "label": "BuildUtility",
             "type": "shell",
             "command": "build.cmd",
             "args": [
                 "-t",
-                "RunMainProj"
-            ]
+                "BuildUtility"
+            ],
+            "problemMatcher": []
         },
         {
             "label": "TrimTrailingWhitespace",

+ 3 - 0
Test/Test.fsproj

@@ -17,6 +17,9 @@
     <ProjectReference Include="..\QspServer\QspServer.fsproj">
       <Name>QspServer.fsproj</Name>
     </ProjectReference>
+    <ProjectReference Include="..\Utility\Utility.fsproj">
+      <Name>Utility.fsproj</Name>
+    </ProjectReference>
   </ItemGroup>
   <ItemGroup>
     <None Include="App.config" />

+ 9 - 0
Utility/App.config

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+    <startup> 
+        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
+    </startup>
+    <appSettings>
+        <!-- <add key="txt2qsp" value="path,args" /> -->
+    </appSettings>
+</configuration>

+ 168 - 0
Utility/Program.fs

@@ -0,0 +1,168 @@
+module Program
+open Argu
+open FsharpMyExtension
+open FsharpMyExtension.Either
+type FilePath = string
+type Txt2qspConfig = { Path: string; Args: string }
+
+let qspSourceExt = ".qsps"
+
+let changeExtensionToQsp (path:FilePath) =
+    System.IO.Path.ChangeExtension(path, qspSourceExt)
+
+let decodeGame config (src:FilePath) (dst:FilePath) =
+    if System.IO.File.Exists config.Path then
+        let args = sprintf "\"%s\" \"%s\" D %s" src dst config.Args
+        let startProcString path args =
+            printfn "start: `%s %s`" path args
+            let drivenOutput = new System.Text.StringBuilder()
+            Proc.startProc (fun e ->
+                drivenOutput.AppendLine(e) |> ignore
+            ) path args
+            |> fun code -> code, drivenOutput.ToString()
+        let code, output = startProcString config.Path args
+        if code = 0 then
+            Right dst
+        else
+            Left output
+    else
+        Left (sprintf "txt2qsp not found in '%s'" config.Path)
+
+
+let doFile txt2qspConfig src =
+    let dst = changeExtensionToQsp src
+    if System.IO.File.Exists dst then
+        Right (dst:FilePath)
+    else
+        decodeGame txt2qspConfig src dst
+
+let doDir txt2qspConfig dir =
+    System.IO.Directory.EnumerateFiles(dir, "*.qsp", System.IO.SearchOption.AllDirectories)
+    |> Seq.map (fun src ->
+        doFile txt2qspConfig src
+    )
+
+type CliArguments =
+    | Working_Directory of path:FilePath
+    | Txt2qsp of path:FilePath * args:string
+    | Source_Path of path:FilePath
+
+    interface IArgParserTemplate with
+        member s.Usage =
+            match s with
+            | Working_Directory _ -> "specify a working directory."
+            | Txt2qsp _ -> "specify a txt2gam (path : args)."
+            | Source_Path _ -> "path to encoded game (.qps) or decoded source game (.qsps)."
+
+module Parser = 
+    open FParsec
+    open Qsp.Parser.Generic
+    open Qsp.Parser.Main
+    let parserStmt str =
+        let emptyState =
+            { emptyState with PStmts = pstmts }
+        let p =
+            spaces >>. pstmt
+            .>> (getPosition >>= fun p ->
+                    updateUserState (fun st ->
+                        { st with LastSymbolPos = p}))
+        runParserOnString (p .>> pAfterAll)
+            emptyState
+            ""
+            str
+
+open Qsp.Ast
+let patternMatching pattern =
+    let rec f acc stmts =
+        stmts
+        |> List.collect (fun stmt ->
+            if stmt = pattern then
+                stmt::acc
+            else
+                match stmt with
+                | Assign(_, _)
+                | CallSt(_, _)
+                | Exit -> acc
+                | Act(_, body)
+                | AssignCode(_, body) -> f acc body
+                | StarPl(_) -> acc
+                | If(_, _, _) -> acc
+                | For(var, from, to', step, body) -> f acc body
+                | Label(_) -> acc
+                | Comment(_) -> acc
+        )
+    f []
+
+[<EntryPoint>]
+let main argv =
+    let parser = ArgumentParser.Create<CliArguments>(programName = "Utility.exe")
+    let enc = System.Text.Encoding.UTF8
+    let results = parser.Parse argv
+    let results = results.GetAllResults()
+    results |> printfn "%A"
+
+    let txt2qspConfig =
+        results
+        |> List.tryPick (function
+            | Txt2qsp(path, args) ->
+                { Path = path; Args = args }
+                |> Some
+            | _ -> None
+        ) |> Either.ofOption "notDefinedTxt2qspConfig"
+    let path =
+        results
+        |> List.tryPick (function
+            | Source_Path src ->
+                match String.toLower (System.IO.Path.GetExtension src) with
+                | ".qsp" ->
+                    txt2qspConfig
+                    |> Either.bind (fun config ->
+                        doFile config src
+                    )
+                    |> Some
+                | ".qsps" -> Some (Right src)
+                | ext ->
+                    Some (Left (sprintf "expected .qsp or .qsps extension but %s\nin\n%s" ext src))
+            | _ -> None
+        )
+        |> Either.ofOption "not defined path"
+        |> Either.concat
+
+    let tree =
+        path
+        |> Either.bind (fun path ->
+            match Qsp.Parser.Main.startOnFile enc path with
+            | FParsec.CharParsers.Success(tree, st, _) ->
+                Right tree
+            | FParsec.CharParsers.Failure(err, st, _) ->
+                Left err
+        )
+    let parse locs =
+        // the ideal solution would be to parse the text on the fly, but need to somehow define the boundaries of Stream
+        let terminator = ";;"
+        printfn "input statement (`%s` — end):" terminator
+        let rec f acc =
+            let line = System.Console.ReadLine()
+            let acc = line::acc
+            if line.Contains terminator then
+                List.rev acc |> System.String.Concat
+            else
+                f acc
+        let str = f []
+        match Parser.parserStmt str with
+        | FParsec.CharParsers.Success(pattern, st, _) ->
+            locs
+            |> List.map (fun (Location (locName, loc)) ->
+                locName, patternMatching pattern loc
+            )
+            |> Right
+        | FParsec.CharParsers.Failure(err, st, _) ->
+            Left err
+
+    tree
+    |> Either.bind parse
+    |> sprintf "%A"
+    |> printfn "%A"
+    // |> uncurry System.IO.File.WriteAllText "output.txt"
+
+    0

+ 19 - 0
Utility/README.md

@@ -0,0 +1,19 @@
+# Утилита для помощи в разработке языка QSP
+
+## Идея
+
+> Вообще я уже где-то писал, что полезно было бы сделать утилиту для массового сканирования игр на языковые конструкции
+> Чтобы легче было принимать решения об изменениях
+> Раньше у меня была такая, но просто с поиском текста
+> Заодно если что-то используется в 1-2-3 играх, то можно было бы сразу подправить
+
+1. Указать папку
+2. Выбрать режим работы:
+   1. Тупо RegEx по всему исходнику, но это неинтересно
+   2. Поиск токенов (например, нужно узнать, сколько раз встречается особенный `&`, который сцепляет строки)
+   3. Шаблонный AST
+
+Выводит:
+Имя файла, локация, строка
+Можно еще номер строки показать
+Ну и все для начала

+ 23 - 0
Utility/Utility.fsproj

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFrameworks>netcoreapp3.1;net461</TargetFrameworks>
+    <Optimize>true</Optimize>
+    <Tailcalls>true</Tailcalls>
+    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
+  </PropertyGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\paket-files\github.com\gretmn102\FsharpMyExtension\FsharpMyExtension\FsharpMyExtension\FsharpMyExtension.fsproj">
+      <Name>FsharpMyExtension.fsproj</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\QSParse\QSParse.fsproj">
+      <Name>QSParse.fsproj</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="App.config" />
+    <Compile Include="Program.fs" />
+  </ItemGroup>
+  <Import Project="..\.paket\Paket.Restore.targets" />
+</Project>

+ 2 - 0
Utility/paket.references

@@ -0,0 +1,2 @@
+FSharp.Core
+Argu

+ 15 - 16
build.fsx

@@ -23,6 +23,8 @@ let testProjPath = @"Test/Test.fsproj"
 let serverProjName = "QspServer"
 let parserProjName = "QSParse"
 let serverProjPath = f serverProjName
+let utilityProjName = "Utility"
+let utilityProjpath = "Utility/Utility.fsproj"
 // --------------------------------------------------------------------------------------
 // Helpers
 // --------------------------------------------------------------------------------------
@@ -34,36 +36,33 @@ let targetFrameworks = ["net461"; "netcoreapp3.1"]
 // --------------------------------------------------------------------------------------
 // Targets
 // --------------------------------------------------------------------------------------
-Target.create "BuildServer" (fun _ ->
-    serverProjPath
-    |> Fake.IO.Path.getDirectory
-    |> DotNet.build (fun x ->
+let dotnetBuild =
+    DotNet.build (fun x ->
         // Чтобы в Linux'е не компилировался net461, дан этот костыль:
         { x with
                 Configuration = buildConf
-                Framework = 
+                Framework =
                     if not Environment.isWindows then
                         Some "netcoreapp3.1"
                     else
                         None
                 }
         |> dtntSmpl)
+Target.create "BuildServer" (fun _ ->
+    serverProjPath
+    |> Fake.IO.Path.getDirectory
+    |> dotnetBuild
 )
 
 Target.create "BuildTest" (fun _ ->
     testProjPath
     |> Fake.IO.Path.getDirectory
-    |> DotNet.build (fun x ->
-        // Чтобы в Linux'е не компилировался net461, дан этот костыль:
-        { x with
-                Configuration = buildConf
-                Framework = 
-                    if not Environment.isWindows then
-                        Some "netcoreapp3.1"
-                    else
-                        None
-                }
-        |> dtntSmpl)
+    |> dotnetBuild
+)
+Target.create "BuildUtility" (fun _ ->
+    utilityProjpath
+    |> Fake.IO.Path.getDirectory
+    |> dotnetBuild
 )
 
 Target.create "Copy3rd" <| fun _ ->

+ 1 - 0
paket.dependencies

@@ -7,6 +7,7 @@ nuget FParsec
 nuget FSharp.Core
 nuget Fuchu
 nuget Newtonsoft.Json
+nuget Argu
 
 github gretmn102/LSP-API src/LanguageServerProtocol.fs
 git https://github.com/gretmn102/FsharpMyExtension.git

+ 30 - 0
paket.lock

@@ -2,6 +2,9 @@ STORAGE: NONE
 RESTRICTION: || (== net461) (== netcoreapp3.1) (== netstandard2.0)
 NUGET
   remote: https://api.nuget.org/v3/index.json
+    Argu (6.1.1)
+      FSharp.Core (>= 4.3.2) - restriction: || (&& (== net461) (>= netstandard2.0)) (== netcoreapp3.1) (== netstandard2.0)
+      System.Configuration.ConfigurationManager (>= 4.4) - restriction: || (&& (== net461) (>= netstandard2.0)) (== netcoreapp3.1) (== netstandard2.0)
     FAKE (5.16)
     FParsec (1.1.1)
       FSharp.Core (>= 4.3.4)
@@ -9,8 +12,35 @@ NUGET
     FSharp.Core (4.7.2)
     Fuchu (1.1)
       FSharp.Core (>= 4.3.4)
+    Microsoft.NETCore.Platforms (3.1.2) - restriction: || (&& (== net461) (>= netcoreapp2.0)) (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.0))
+    Microsoft.Win32.SystemEvents (4.7) - restriction: || (&& (== net461) (>= netcoreapp3.0)) (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp3.0))
+      Microsoft.NETCore.Platforms (>= 3.1) - restriction: || (&& (== net461) (>= netcoreapp2.0)) (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.0))
     Newtonsoft.Json (12.0.3)
+    System.Buffers (4.5.1) - restriction: || (&& (== net461) (== netcoreapp3.1)) (&& (== netcoreapp3.1) (>= monoandroid)) (&& (== netcoreapp3.1) (>= monotouch)) (&& (== netcoreapp3.1) (>= net461)) (&& (== netcoreapp3.1) (< netcoreapp2.0)) (&& (== netcoreapp3.1) (< netstandard1.1)) (&& (== netcoreapp3.1) (< netstandard2.0)) (&& (== netcoreapp3.1) (>= xamarinios)) (&& (== netcoreapp3.1) (>= xamarinmac)) (&& (== netcoreapp3.1) (>= xamarintvos)) (&& (== netcoreapp3.1) (>= xamarinwatchos)) (== netstandard2.0)
+    System.Configuration.ConfigurationManager (4.7) - restriction: || (&& (== net461) (>= netstandard2.0)) (== netcoreapp3.1) (== netstandard2.0)
+      System.Security.Cryptography.ProtectedData (>= 4.7) - restriction: || (== netcoreapp3.1) (== netstandard2.0)
+      System.Security.Permissions (>= 4.7)
+    System.Drawing.Common (4.7) - restriction: || (&& (== net461) (>= netcoreapp3.0)) (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp3.0))
+      Microsoft.NETCore.Platforms (>= 3.1) - restriction: || (&& (== net461) (>= netcoreapp2.0)) (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.0))
+      Microsoft.Win32.SystemEvents (>= 4.7) - restriction: || (&& (== net461) (>= netcoreapp2.0)) (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.0))
+    System.Memory (4.5.4) - restriction: || (&& (== net461) (== netcoreapp3.1)) (&& (== netcoreapp3.1) (< netcoreapp2.1)) (== netstandard2.0)
+      System.Buffers (>= 4.5.1) - restriction: || (== net461) (&& (== netcoreapp3.1) (>= monoandroid)) (&& (== netcoreapp3.1) (>= monotouch)) (&& (== netcoreapp3.1) (>= net461)) (&& (== netcoreapp3.1) (< netcoreapp2.0)) (&& (== netcoreapp3.1) (< netstandard1.1)) (&& (== netcoreapp3.1) (< netstandard2.0)) (&& (== netcoreapp3.1) (>= xamarinios)) (&& (== netcoreapp3.1) (>= xamarinmac)) (&& (== netcoreapp3.1) (>= xamarintvos)) (&& (== netcoreapp3.1) (>= xamarinwatchos)) (== netstandard2.0)
+      System.Numerics.Vectors (>= 4.4) - restriction: || (&& (== net461) (< net45) (>= netstandard2.0)) (&& (== netcoreapp3.1) (< netcoreapp2.0)) (== netstandard2.0)
+      System.Runtime.CompilerServices.Unsafe (>= 4.5.3) - restriction: || (== net461) (&& (== netcoreapp3.1) (>= monoandroid)) (&& (== netcoreapp3.1) (>= monotouch)) (&& (== netcoreapp3.1) (>= net461)) (&& (== netcoreapp3.1) (< netcoreapp2.0)) (&& (== netcoreapp3.1) (< netcoreapp2.1)) (&& (== netcoreapp3.1) (< netstandard1.1)) (&& (== netcoreapp3.1) (< netstandard2.0)) (&& (== netcoreapp3.1) (>= uap10.1)) (&& (== netcoreapp3.1) (>= xamarinios)) (&& (== netcoreapp3.1) (>= xamarinmac)) (&& (== netcoreapp3.1) (>= xamarintvos)) (&& (== netcoreapp3.1) (>= xamarinwatchos)) (== netstandard2.0)
+    System.Numerics.Vectors (4.5) - restriction: || (&& (== net461) (== netcoreapp3.1)) (&& (== netcoreapp3.1) (< netcoreapp2.0)) (== netstandard2.0)
+    System.Runtime.CompilerServices.Unsafe (4.7.1) - restriction: || (&& (== net461) (== netcoreapp3.1)) (&& (== netcoreapp3.1) (>= monoandroid)) (&& (== netcoreapp3.1) (>= monotouch)) (&& (== netcoreapp3.1) (>= net461)) (&& (== netcoreapp3.1) (< netcoreapp2.0)) (&& (== netcoreapp3.1) (< netcoreapp2.1)) (&& (== netcoreapp3.1) (< netstandard1.1)) (&& (== netcoreapp3.1) (< netstandard2.0)) (&& (== netcoreapp3.1) (>= uap10.1)) (&& (== netcoreapp3.1) (>= xamarinios)) (&& (== netcoreapp3.1) (>= xamarinmac)) (&& (== netcoreapp3.1) (>= xamarintvos)) (&& (== netcoreapp3.1) (>= xamarinwatchos)) (== netstandard2.0)
+    System.Security.AccessControl (4.7) - restriction: || (&& (== net461) (>= netstandard2.0)) (== netcoreapp3.1) (== netstandard2.0)
+      Microsoft.NETCore.Platforms (>= 3.1) - restriction: || (&& (== net461) (>= netcoreapp2.0)) (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.0))
+      System.Security.Principal.Windows (>= 4.7)
+    System.Security.Cryptography.ProtectedData (4.7) - restriction: || (== netcoreapp3.1) (== netstandard2.0)
+      System.Memory (>= 4.5.3) - restriction: || (&& (== net461) (< net46) (>= netstandard2.0)) (&& (== netcoreapp3.1) (< netcoreapp2.1)) (== netstandard2.0)
+    System.Security.Permissions (4.7) - restriction: || (&& (== net461) (>= netstandard2.0)) (== netcoreapp3.1) (== netstandard2.0)
+      System.Security.AccessControl (>= 4.7)
+      System.Windows.Extensions (>= 4.7) - restriction: || (&& (== net461) (>= netcoreapp3.0)) (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp3.0))
+    System.Security.Principal.Windows (4.7) - restriction: || (&& (== net461) (>= netcoreapp2.0)) (&& (== net461) (>= netstandard2.0)) (== netcoreapp3.1) (== netstandard2.0)
     System.ValueTuple (4.5) - restriction: || (== net461) (&& (== netcoreapp3.1) (>= net45)) (&& (== netstandard2.0) (>= net45))
+    System.Windows.Extensions (4.7) - restriction: || (&& (== net461) (>= netcoreapp3.0)) (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp3.0))
+      System.Drawing.Common (>= 4.7) - restriction: || (&& (== net461) (>= netcoreapp3.0)) (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp3.0))
 GITHUB
   remote: gretmn102/LSP-API
     src/LanguageServerProtocol.fs (00797a8541ae01b7fa0631cd9bc8fdfd6923caf5)