Browse Source

feat: `step` in `for`

gretmn102 3 years ago
parent
commit
0e9a311b21
5 changed files with 30 additions and 4 deletions
  1. 1 1
      QSParse/Ast.fs
  2. 1 0
      QSParse/Defines.fs
  3. 4 2
      QSParse/Parsec.fs
  4. 6 1
      QSParse/Show.fs
  5. 18 0
      Test/Test.fs

+ 1 - 1
QSParse/Ast.fs

@@ -159,7 +159,7 @@ and Statement =
     | StarPl of Expr
     | If of Expr * Statement list * Statement list
     | Act of Expr list * Statement list
-    | For of var:Var * from:Expr * to':Expr * body:Statement list
+    | For of var:Var * from:Expr * to':Expr * step:Expr option * body:Statement list
     | Label of string
     | Comment of string
     | Exit

+ 1 - 0
QSParse/Defines.fs

@@ -1213,4 +1213,5 @@ let keywords =
             ] |> String.concat "\n"
         "for", dscr
         "to", "**TO** — ключевое слово для конструкции FOR"
+        "step", "**STEP** — ключевое слово для конструкции FOR"
     ]

+ 4 - 2
QSParse/Parsec.fs

@@ -301,14 +301,16 @@ let pstmt =
             .>> ws .>>. pexpr
             .>> genKeywordParser "to"
             .>> ws .>>. pexpr
+            .>>. opt (genKeywordParser "step"
+                      .>> ws >>. pexpr)
             .>> pcolonKeyword
 
         pipe2
             pForHeader
             ((ws >>? skipNewline >>. spaces >>. pstmts .>> pendKeyword)
               <|> (spaces >>. pInlineStmts .>> optional pendKeyword))
-            (fun ((var, fromExpr), toExpr) body ->
-                For(var, fromExpr, toExpr, body))
+            (fun (((var, fromExpr), toExpr), stepExpr) body ->
+                For(var, fromExpr, toExpr, stepExpr, body))
     let pIf =
         let pifKeyword : _ Parser =
             genKeywordParser "if"

+ 6 - 1
QSParse/Show.fs

@@ -271,7 +271,7 @@ let showStmt indentsOption (formatConfig:FormatConfig) =
                             (f' >> List.map ((<<) tabs))
                     yield showString "end"
             ]
-        | For(var, fromExpr, toExpr, body) ->
+        | For(var, fromExpr, toExpr, stepExpr, body) ->
             let header =
                 showString "for"
                 << showSpace << showVar var
@@ -279,6 +279,11 @@ let showStmt indentsOption (formatConfig:FormatConfig) =
                 << showSpace << showExpr fromExpr
                 << showSpace << showString "to"
                 << showSpace << showExpr toExpr
+                << (stepExpr
+                    |> Option.map (fun expr ->
+                        showSpace << showString "step"
+                        << showSpace << showExpr expr
+                    ) |> Option.defaultValue empty)
                 << showChar ':'
             [
                 match body with

+ 18 - 0
Test/Test.fs

@@ -688,6 +688,7 @@ let forTests =
                   Expr
                     (Plus, Expr (Divide, Val (Int 45), Var (ImplicitNumericType, "x")),
                      Var (ImplicitNumericType, "y")),
+                  None,
                   [StarPl (Var (ImplicitNumericType, "stmt"))]))
             Assert.Equal("", Right exp, runStmtsEof input)
         testCase "inline `for i = 4 + x to 45 / x + y: stmt`" <| fun () ->
@@ -703,6 +704,23 @@ let forTests =
                   Expr
                     (Plus, Expr (Divide, Val (Int 45), Var (ImplicitNumericType, "x")),
                      Var (ImplicitNumericType, "y")),
+                  None,
+                  [StarPl (Var (ImplicitNumericType, "stmt"))]))
+            Assert.Equal("", Right exp, runStmts input)
+        testCase "inline `for i = 4 + x to 45 / x + y step x + 1: stmt`" <| fun () ->
+            let input =
+                [
+                    "for i = 4 + x to 45 / x + y step x + 1: stmt"
+                    "'statement that not belong to construction'"
+                ] |> String.concat "\n"
+            let exp =
+              (For
+                 ((ImplicitNumericType, "i"),
+                  Expr (Plus, Val (Int 4), Var (ImplicitNumericType, "x")),
+                  Expr
+                    (Plus, Expr (Divide, Val (Int 45), Var (ImplicitNumericType, "x")),
+                     Var (ImplicitNumericType, "y")),
+                  Some (Expr (Plus, Var (ImplicitNumericType, "x"), Val (Int 1))),
                   [StarPl (Var (ImplicitNumericType, "stmt"))]))
             Assert.Equal("", Right exp, runStmts input)
     ]