123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865 |
- open FsharpMyExtension
- open FsharpMyExtension
- open FsharpMyExtension.Either
- open FParsec
- #if INTERACTIVE
- #load @"..\QSParse\Tokens.fs"
- #load @"..\QSParse\Ast.fs"
- #load @"..\QSParse\Defines.fs"
- #load @"..\QSParse\Show.fs"
- #load @"..\QSParse\ParserGeneric.fs"
- #load @"..\QSParse\ParserExpr.fs"
- #load @"..\QSParse\Parsec.fs"
- #endif
- open Qsp
- open Qsp.Ast
- open Qsp.Parser.Generic
- open Qsp.Parser.Expr
- open Fuchu
- [<Tests>]
- let pexprTest =
- let runExpr str =
- runStateEither pexpr Qsp.Parser.Generic.emptyState str
- |> snd
- let sprintExpr =
- Show.simpleShowExpr (failwithf "showStmtsInline not implemented %A")
- >> FsharpMyExtension.ShowList.show
- let runExprShow str =
- runExpr str
- |> Either.map sprintExpr
- let equalWithShow (exp:Expr) (act:Either<_, Expr>) =
- match act with
- | Left _ ->
- failtestf "%A" act
- | Right act ->
- if exp <> act then
- failtestf "Expected:\n%A\n\"%s\"\n\nActual:\n%A\n\"%s\"" exp (sprintExpr exp) act (sprintExpr act)
- let testf input exp =
- testCase input <| fun () ->
- equalWithShow exp (runExpr input)
- testList "pexpr test" [
- testCase "строчные бинарные операторы и названия переменных, которые начинаются с них" <| fun () ->
- let input = "notFollowedBy" // Уж точно не должно быть "no tFollowedBy"
- let exp =
- Var (NumericType, "notFollowedBy")
- Assert.Equal("", Right exp, runExpr input)
- testCase "строчные бинарные операторы и названия переменных, которые начинаются с них" <| fun () ->
- let input = "object"
- let exp =
- Var (NumericType, "object")
- Assert.Equal("", Right exp, runExpr input)
- testCase "строчные бинарные операторы и названия переменных, которые начинаются с них" <| fun () ->
- let input = "obj something"
- let exp =
- UnarExpr (Obj, Var (NumericType, "something"))
- Assert.Equal("", Right exp, runExpr input)
- let input = "var1 and var2 and no var3 and obj var4"
- let exp =
- Expr
- (And,
- Expr
- (And,
- Expr
- (And, Var (NumericType, "var1"),
- Var (NumericType, "var2")),
- UnarExpr (No, Var (NumericType, "var3"))),
- UnarExpr (Obj, Var (NumericType, "var4")))
- testf input exp
- testCase "2" <| fun () ->
- let input = "var1[var1 + var2] and func(arg1, arg2[expr], x + y)"
- let exp = "var1[var1 + var2] and func(arg1, arg2[expr], x + y)"
- Assert.Equal("", Right exp, runExprShow input)
- testCase "3" <| fun () ->
- let input = "a = 10 or b = 20 and c = 30"
- let exp = "(a = 10) or ((b = 20) and (c = 30))"
- Assert.Equal("", Right exp, runExprShow input)
- testCase "4" <| fun () ->
- let input = "a = pstam> (pmaxstam/4)*2 and pstam <= (pmaxstam/4)*3"
- let exp = "((a = pstam) > ((pmaxstam / 4) * 2)) and (pstam <= ((pmaxstam / 4) * 3))"
- Assert.Equal("", Right exp, runExprShow input)
- testCase "no obj 'apple'" <| fun () ->
- let input = "no obj 'apple'"
- let exp =
- UnarExpr (No, UnarExpr (Obj, Val (String [[StringKind "apple"]])))
- Assert.Equal("", Right exp, runExpr input)
- let input = "- x"
- let exp =
- UnarExpr (Neg, Var (NumericType, "x"))
- testf input exp
- let input = "-x + -y"
- let exp =
- Expr
- (Plus, UnarExpr (Neg, Var (NumericType, "x")),
- UnarExpr (Neg, Var (NumericType, "y")))
- testf input exp
- let input =
- [
- "x + _"
- " "
- " _"
- " _"
- ""
- " z + y"
- ] |> String.concat "\n"
- let exp =
- Expr
- (Plus,
- Expr (Plus, Var (NumericType, "x"), Var (NumericType, "z")),
- Var (NumericType, "y"))
- testf input exp
- let input =
- "input 'How do you do?'"
- let exp =
- Func (Predef Defines.Input, [Val (String [[StringKind "How do you do?"]])])
- testf input exp
- ]
- // #load "Parsec.fs"
- [<Tests>]
- let assignTest =
- let runExpr str =
- Qsp.Parser.Generic.runStateEither (Qsp.Parser.Main.pAssign FParsec.Primitives.pzero) Qsp.Parser.Generic.emptyState str
- |> snd
- testList "assignTest" [
- testCase "implicit assign implicit var" <| fun () ->
- let input = "x = 21 + 21"
- let exp =
- (Assign
- (false, AssignVar (NumericType, "x"),
- Expr (Plus, Val (Int 21), Val (Int 21))))
- Assert.Equal("", Right exp, runExpr input)
- testCase "implicit assign implicit array var" <| fun () ->
- let input = "x[expr] = 42"
- let exp =
- (Assign
- (false, AssignArr
- ((NumericType, "x"), Var (NumericType, "expr")),
- Val (Int 42)))
- Assert.Equal("", Right exp, runExpr input)
- testCase "implicit `-=` implicit var" <| fun () ->
- let input = "years -= 10"
- let exp =
- (Assign
- (false, AssignVar (NumericType, "years"),
- Expr (Minus, Var (NumericType, "years"), Val (Int 10))))
- Assert.Equal("", Right exp, runExpr input)
- testCase "implicit `-=` implicit var 2" <| fun () ->
- let input = "php -= 3*emdmg*2 - parm"
- let exp =
- (Assign
- (false, AssignVar (NumericType, "php"),
- Expr
- (Minus, Var (NumericType, "php"),
- Expr
- (Minus,
- Expr
- (Times,
- Expr (Times, Val (Int 3), Var (NumericType, "emdmg")),
- Val (Int 2)), Var (NumericType, "parm")))))
- Assert.Equal("", Right exp, runExpr input)
- testCase "5" <| fun () ->
- let input = "a = a = no -a > b"
- let exp =
- (Assign
- (false, AssignVar (NumericType, "a"),
- Expr
- (Eq, Var (NumericType, "a"),
- UnarExpr
- (No,
- Expr
- (Gt, UnarExpr (Neg, Var (NumericType, "a")),
- Var (NumericType, "b"))))))
- Assert.Equal("", Right exp, runExpr input)
- testCase "implicit assign explicit array var" <| fun () ->
- let input = "$x[expr] = 42"
- let exp =
- (Assign
- (false, AssignArr ((StringType, "x"), Var (NumericType, "expr")),
- Val (Int 42)))
- Assert.Equal("", Right exp, runExpr input)
- testCase "#x = 21 + 21" <| fun () ->
- let input = "#x = 21 + 21"
- let exp =
- (Assign
- (false, AssignVar (NumericType, "#x"),
- Expr (Plus, Val (Int 21), Val (Int 21))))
- Assert.Equal("", Right exp, runExpr input)
- testCase "`x[] = 1`" <| fun () ->
- let input = "x[] = 1"
- let exp =
- Assign (false, AssignArrAppend (NumericType, "x"), Val (Int 1))
- Assert.Equal("", Right exp, runExpr input)
- // ложные случаи:
- testCase "attempt assign function" <| fun () ->
- let input = "f(expr) = 42" // поскольку `=` — это одновременно и оператор присваивания и оператор равности, так что сойдет за выражение
- let exp =
- [
- "Error in Ln: 1 Col: 1"
- "f(expr) = 42"
- "^"
- "Expecting: '$', 'let' (case-insensitive) or 'set'"
- "(case-insensitive)"
- ""
- "The parser backtracked after:"
- " Error in Ln: 1 Col: 2"
- " f(expr) = 42"
- " ^"
- " Expecting: '*=', '+=', '-=', '/=', '=', '[' or '_'"
- ""
- ] |> String.concat "\r\n"
- Assert.Equal("", Left exp, runExpr input)
- testCase "attempt assign var without body" <| fun () ->
- let input = "justName"
- let act =
- runExpr input
- |> Option.ofEither
- Assert.None("", act)
- testCase "attempt assign var without body space" <| fun () ->
- let input = "justName "
- let act =
- runExpr input
- |> Option.ofEither
- Assert.None("", act)
- testCase "just `x[expr]`" <| fun () ->
- let input = "x[expr]"
- let act =
- runExpr input
- |> Option.ofEither
- Assert.None("", act)
- ]
- [<Tests>]
- let stringLiteralTest =
- testList "stringLiteralTest" [
- testCase "1" <| fun () ->
- Assert.Equal("", Right " ", runEither stringLiteral "\" \"")
- testCase "2" <| fun () ->
- Assert.Equal("", Right "\"", runEither stringLiteral "\"\"\"\"")
- testCase "3" <| fun () ->
- Assert.Equal("", Right "\"'\"", runEither stringLiteral "\"\"\"'\"\"\"")
- testCase "5" <| fun () ->
- Assert.Equal("", Right "", runEither stringLiteral "''")
- testCase "6" <| fun () ->
- Assert.Equal("", Right "'", runEither stringLiteral "''''")
- testCase "4" <| fun () ->
- Assert.Equal("", Right "\"", runEither stringLiteral "'\"'")
- testCase "braces1" <| fun () ->
- Assert.Equal("", Right "abc", runEither stringLiteral "{abc}")
- testCase "braces escaped" <| fun () ->
- Assert.Equal("", Right "}", runEither stringLiteral "{}}}")
- ]
- let emptyPos = NoEqualityPosition positionEmpty
- let emptyPoss x = x |> List.map (fun x -> emptyPos, x)
- let StaticStmts x =
- emptyPoss x
- |> StaticStmts
- let If(expr, thenBody, elseBody) =
- If(expr, emptyPoss thenBody, emptyPoss elseBody)
- let Act(exprs, thenBody) = Act(exprs, emptyPoss thenBody)
- let equalTwoPosStmt (note, stmt1, stmt2) =
- match stmt1, stmt2 with
- | Right stmt1', Right stmt2' ->
- if stmt1' <> stmt2' then
- failtestf "Expected:\n%A\n\nActual:\n%A\nWarning: ignores Position when comparing!" stmt1 stmt2
- | _ -> failtestf "Expected:\n%A\n\nActual:\n%A\nWarning: ignores Position when comparing!" stmt1 stmt2
- let exprEqual (note, expr1, expr2) =
- match expr1, expr2 with
- | Right expr1', Right expr2' ->
- if expr1' <> expr2' then
- failtestf "Expected:\n%A\n\nActual:\n%A\nWarning: ignores Position when comparing!" expr1 expr2
- | _ -> failtestf "Expected:\n%A\n\nActual:\n%A\nWarning: ignores Position when comparing!" expr1 expr2
- [<Tests>]
- let stringLiteralWithTokenTest =
- let runEither str =
- Qsp.Parser.Generic.runStateEither
- (stringLiteralWithToken pexpr)
- { Qsp.Parser.Generic.emptyState with
- PStmts = Parser.Main.pstmts
- }
- str
- |> snd
- let f str =
- [[StringKind str]]
- testList "stringLiteralWithTokenTest" [
- testCase "1" <| fun () ->
- Assert.Equal("", Right (f " "), runEither "\" \"")
- testCase "2" <| fun () ->
- Assert.Equal("", Right (f "\""), runEither "\"\"\"\"")
- testCase "3" <| fun () ->
- Assert.Equal("", Right (f "\"'\""), runEither "\"\"\"'\"\"\"")
- testCase "5" <| fun () ->
- Assert.Equal("", Right [[]], runEither "''")
- testCase "6" <| fun () ->
- Assert.Equal("", Right (f "'"), runEither "''''")
- testCase "4" <| fun () ->
- Assert.Equal("", Right (f "\""), runEither "'\"'")
- testCase "multiline `'` test" <| fun () ->
- let input =
- [
- "'"
- " a"
- "'"
- ] |> String.concat "\n"
- let exp =
- [
- []
- [ StringKind " a"]
- []
- ]
- Assert.Equal("", Right exp, runEither input)
- testCase "multiline `'` test2" <| fun () ->
- let input =
- [
- "'"
- " a"
- ""
- "b"
- "'"
- ] |> String.concat "\n"
- let exp =
- [
- []
- [ StringKind " a" ]
- []
- [ StringKind "b" ]
- []
- ]
- Assert.Equal("", Right exp, runEither input)
- testCase "test '<<''x''>>'" <| fun () ->
- let input = "'<<''x''>>'"
- let exp = [[ExprKind (Val (String [[StringKind "x"]]))]]
- Assert.Equal("", Right exp, runEither input)
- testCase "test '<<''<<''''x''''>>''>>'" <| fun () ->
- let input = "'<<''<<''''x''''>>''>>'"
- let exp = [[ExprKind (Val (String [[ExprKind (Val (String [[StringKind "x"]]))]]))]]
- Assert.Equal("", Right exp, runEither input)
- testCase "test '<<''<<''''<<''''''''x''''''''>>''''>>''>>'" <| fun () ->
- let input = "'<<''<<''''<<''''''''x''''''''>>''''>>''>>'"
- let exp =
- [[ExprKind
- (Val
- (String
- [[ExprKind
- (Val (String [[ExprKind (Val (String [[StringKind "x"]]))]]))]]))]]
- Assert.Equal("", Right exp, runEither input)
- testCase "test \"<<'x'>>\"" <| fun () ->
- let input = "\"<<'x'>>\""
- let exp = [[ExprKind (Val (String [[StringKind "x"]]))]]
- Assert.Equal("", Right exp, runEither input)
- testCase "test '<a href=\"exec:GT ''changes''\">changes</a>'" <| fun () ->
- let input = "'<a href=\"exec:GT ''changes''\">changes</a>'"
- let exp =
- [[HyperLinkKind
- (StaticStmts [Proc ("GT", [Val (String [[StringKind "changes"]])])],
- [[StringKind "changes"]])]]
- Assert.Equal("", Right exp, runEither input)
- testCase "test '<a href=\"exec: ''<<''x''>>''\">action</a>'" <| fun () ->
- let input = "'<a href=\"exec: ''<<''x''>>''\">action</a>'"
- let exp =
- [[HyperLinkKind (Raw " '<<'x'>>'", [[StringKind "action"]])]]
- Assert.Equal("", Right exp, runEither input)
- ]
- [<Tests>]
- let pbracesTests =
- let runEither str =
- Qsp.Parser.Generic.runStateEither
- (pbraces Tokens.TokenType.StringBraced)
- Qsp.Parser.Generic.emptyState
- str
- |> snd
- testList "stringLiteralWithTokenTest" [
- testCase "base" <| fun () ->
- Assert.Equal("", Right "", runEither "{}")
- testCase "braces1" <| fun () ->
- Assert.Equal("", Right "abc", runEither "{abc}")
- testCase "1" <| fun () ->
- let input =
- [
- "{"
- " asdf"
- " {"
- " asdf"
- " }"
- "}"
- ] |> String.concat "\n"
- let exp =
- [
- ""
- " asdf"
- " {"
- " asdf"
- " }"
- ""
- ] |> String.concat "\n"
- Assert.Equal("", Right exp, runEither input)
- ]
- [<Tests>]
- let pcallProcTests =
- let runStmts str =
- Qsp.Parser.Generic.runStateEither Qsp.Parser.Main.pcallProc Qsp.Parser.Generic.emptyState str
- |> snd
- testList "pcallProcTests" [
- testCase "pcallProcTests base" <| fun () ->
- let input = "someProc arg1"
- let exp =
- Proc ("someProc", [Var (NumericType, "arg1")])
- Assert.Equal("", Right exp, runStmts input)
- testCase "pcallProcTests base many args" <| fun () ->
- let input = "someProc z / 2, x + y"
- let exp =
- (Proc
- ("someProc",
- [Expr (Divide, Var (NumericType, "z"), Val (Int 2));
- Expr
- (Plus, Var (NumericType, "x"), Var (NumericType, "y"))]))
- Assert.Equal("", Right exp, runStmts input)
- testCase "pcallProcTests false with space" <| fun () ->
- let input = "someProc "
- // let exp =
- // [
- // "Error in Ln: 1 Col: 1"
- // "someProc "
- // "^"
- // ""
- // "The parser backtracked after:"
- // " Error in Ln: 1 Col: 10"
- // " someProc "
- // " ^"
- // " Note: The error occurred at the end of the input stream."
- // " Expecting: identifier, integer number (32-bit, signed), prefix operator, '\"',"
- // " '#', '$', '\\'', '(', '_' or '{'"
- // ""
- // ] |> String.concat "\r\n"
- // Assert.Equal("", Left exp, runStmts input)
- let act =
- runStmts input
- |> Option.ofEither
- Assert.None("", act)
- testCase "pcallProcTests false" <| fun () ->
- let input = "someProc"
- // let exp =
- // [
- // "Error in Ln: 1 Col: 1"
- // "someProc"
- // "^"
- // ""
- // "The parser backtracked after:"
- // " Error in Ln: 1 Col: 9"
- // " someProc"
- // " ^"
- // " Note: The error occurred at the end of the input stream."
- // " Unknown Error(s)"
- // ""
- // ] |> String.concat "\r\n"
- // Assert.Equal("", Left exp, runStmts input)
- let act =
- runStmts input
- |> Option.ofEither
- Assert.None("", act)
- testCase "*pl" <| fun () ->
- let input = "*pl"
- let exp = Proc ("*pl", [])
- Assert.Equal("", Right exp, runStmts input)
- testCase "*pl arg1, arg2" <| fun () ->
- let input = "*pl arg1, arg2"
- let exp =
- (Proc
- ("*pl",
- [Var (NumericType, "arg1"); Var (NumericType, "arg2")]))
- Assert.Equal("", Right exp, runStmts input)
- testCase "call `p2 x`, который начинается на заданный оператор `p`, но образует новый" <| fun () ->
- let input = "p2 x"
- let exp =
- Proc ("p2", [Var (NumericType, "x")])
- Assert.Equal("", Right exp, runStmts input)
- testCase "call ad-hoc `add obj`" <| fun () ->
- let input = "add obj"
- let exp =
- Proc ("addobj", [])
- Assert.Equal("", Right exp, runStmts input)
- testCase "call ad-hoc `close all`" <| fun () ->
- let input = "close all"
- let exp =
- Proc ("close all", [])
- Assert.Equal("", Right exp, runStmts input)
- ]
- let printStmts stmts =
- List.collect (Show.showStmt (Qsp.Show.UsingSpaces 4) Show.FormatConfig.Default) stmts
- |> ShowList.joinEmpty "\n"
- |> ShowList.show
- let printStmt stmt =
- Qsp.Show.showStmt (Qsp.Show.UsingSpaces 4) Show.FormatConfig.Default stmt
- |> ShowList.joinEmpty "\n"
- |> ShowList.show
- let StarPl arg = Proc("*pl", [arg])
- [<Tests>]
- let ifTests =
- let runStmts str =
- Qsp.Parser.Generic.runStateEither
- Qsp.Parser.Main.pstmt
- Qsp.Parser.Generic.emptyState str
- |> snd
- let runStmtsEof str =
- Qsp.Parser.Generic.runStateEither
- (Qsp.Parser.Main.pstmt .>> eof)
- Qsp.Parser.Generic.emptyState str
- |> snd
- testList "ifTests" [
- testCase "inline if" <| fun () ->
- let input =
- [
- "if expr: gt 'hall'"
- "'statement that not belong to construction'"
- ] |> String.concat "\n"
- let exp =
- (emptyPos, If
- (Var (NumericType, "expr"), [Proc ("gt", [Val (String [[StringKind "hall"]])])],
- []))
- equalTwoPosStmt("", Right exp, runStmts input)
- testCase "inline if 2" <| fun () ->
- let input =
- [
- "if expr:"
- " if expr2: stmt1"
- " if expr3:"
- " stmt1"
- " else stmt2"
- " if expr4: stmt3"
- "elseif expr5:"
- " stmt6"
- "elseif expr6: stmt4"
- ] |> String.concat "\n"
- // tested
- let exp =
- If
- (Var (NumericType, "expr"),
- [If
- (Var (NumericType, "expr2"),
- [StarPl (Var (NumericType, "stmt1"))], []);
- If
- (Var (NumericType, "expr3"),
- [StarPl (Var (NumericType, "stmt1"))],
- [StarPl (Var (NumericType, "stmt2"))]);
- If
- (Var (NumericType, "expr4"),
- [StarPl (Var (NumericType, "stmt3"))], [])],
- [If
- (Var (NumericType, "expr5"),
- [StarPl (Var (NumericType, "stmt6"))],
- [If
- (Var (NumericType, "expr6"),
- [StarPl (Var (NumericType, "stmt4"))], [])])])
- equalTwoPosStmt("", Right (emptyPos, exp), runStmtsEof input)
- testCase "simple if" <| fun () ->
- let input =
- [
- "if expr:"
- " someStmt"
- "end"
- ] |> String.concat "\n"
- let exp =
- (If
- (Var (NumericType, "expr"),
- [StarPl (Var (NumericType, "someStmt"))], []))
- equalTwoPosStmt("", Right (emptyPos, exp), runStmtsEof input)
- testCase "elseif test" <| fun () ->
- let input =
- [
- "if expr1:"
- " stmt1"
- "elseif expr2:"
- " stmt2"
- "elseif expr3:"
- " stmt3"
- "else"
- " stmt4"
- "end"
- ] |> String.concat "\n"
- let exp =
- (If
- (Var (NumericType, "expr1"),
- [StarPl (Var (NumericType, "stmt1"))],
- [If
- (Var (NumericType, "expr2"),
- [StarPl (Var (NumericType, "stmt2"))],
- [If
- (Var (NumericType, "expr3"),
- [StarPl (Var (NumericType, "stmt3"))],
- [StarPl (Var (NumericType, "stmt4"))])])]))
- equalTwoPosStmt("", Right (emptyPos, exp), runStmtsEof input)
- testCase "elseif test2" <| fun () ->
- let input =
- [
- "if expr1:"
- " stmt1"
- "elseif expr2:"
- " stmt2"
- "elseif expr3:"
- " stmt3"
- "end"
- ] |> String.concat "\n"
- let exp =
- (If
- (Var (NumericType, "expr1"),
- [StarPl (Var (NumericType, "stmt1"))],
- [If
- (Var (NumericType, "expr2"),
- [StarPl (Var (NumericType, "stmt2"))],
- [If
- (Var (NumericType, "expr3"),
- [StarPl (Var (NumericType, "stmt3"))], [])])]))
- equalTwoPosStmt("", Right (emptyPos, exp), runStmtsEof input)
- testCase "another inline if" <| fun () ->
- let input =
- [
- "if expr:"
- "elseif expr: stmt"
- ] |> String.concat "\n"
- let exp =
- (If
- (Var (NumericType, "expr"), [],
- [If
- (Var (NumericType, "expr"),
- [StarPl (Var (NumericType, "stmt"))], [])]))
- equalTwoPosStmt("", Right (emptyPos, exp), runStmtsEof input)
- testCase "elseif test2" <| fun () ->
- let input =
- [
- "if expr1:"
- " stmt1"
- "elseif expr2:"
- " stmt2"
- " if expr4:"
- " stmt4"
- " elseif expr5:"
- " stmt5"
- " end"
- " stmt6"
- "elseif expr3:"
- " stmt3"
- "end"
- ] |> String.concat "\n"
- let exp =
- (If
- (Var (NumericType, "expr1"),
- [StarPl (Var (NumericType, "stmt1"))],
- [If
- (Var (NumericType, "expr2"),
- [StarPl (Var (NumericType, "stmt2"));
- If
- (Var (NumericType, "expr4"),
- [StarPl (Var (NumericType, "stmt4"))],
- [If
- (Var (NumericType, "expr5"),
- [StarPl (Var (NumericType, "stmt5"))], [])]);
- StarPl (Var (NumericType, "stmt6"))],
- [If
- (Var (NumericType, "expr3"),
- [StarPl (Var (NumericType, "stmt3"))], [])])]))
- equalTwoPosStmt("", Right (emptyPos, exp), runStmtsEof input)
- testCase "if" <| fun () ->
- let input =
- [
- "if expr1:"
- " stmt1"
- " act 'arg': pl"
- "elseif expr2:"
- " if expr3: stmt2 else stmt3 if expr4: stmt4 elseif expr5: stmt5"
- " stmt6"
- "end"
- ] |> String.concat "\n"
- let exp =
- (If
- (Var (NumericType, "expr1"),
- [StarPl (Var (NumericType, "stmt1"));
- Act ([Val (String [[StringKind "arg"]])], [Proc ("pl", [])])],
- [If
- (Var (NumericType, "expr2"),
- [If
- (Var (NumericType, "expr3"),
- [StarPl (Var (NumericType, "stmt2"))],
- [StarPl (Var (NumericType, "stmt3"));
- If
- (Var (NumericType, "expr4"),
- [StarPl (Var (NumericType, "stmt4"))],
- [If
- (Var (NumericType, "expr5"),
- [StarPl (Var (NumericType, "stmt5"))], [])])]);
- StarPl (Var (NumericType, "stmt6"))], [])]))
- equalTwoPosStmt("", Right (emptyPos, exp), runStmtsEof input)
- ]
- [<Tests>]
- let stmtTests =
- let runStmts str =
- Qsp.Parser.Generic.runStateEither
- Qsp.Parser.Main.pstmt
- Qsp.Parser.Generic.emptyState str
- |> snd
- let runStmtsEof str =
- Qsp.Parser.Generic.runStateEither
- (Qsp.Parser.Main.pstmt .>> eof)
- Qsp.Parser.Generic.emptyState str
- |> snd
- testList "stmtTests" [
- testCase "inline act" <| fun () ->
- let input =
- [
- "act 'some act': gt 'hall'"
- "'statement that not belong to construction'"
- ] |> String.concat "\n"
- let exp =
- Act ([Val (String [[StringKind "some act"]])], [Proc ("gt", [Val (String [[StringKind "hall"]])])])
- equalTwoPosStmt("", Right (emptyPos, exp), runStmts input)
- // порядок разбора
- testCase "stmt `years -= 10`" <| fun () ->
- let input = "years -= 10"
- let exp =
- (Assign
- (false, AssignVar (NumericType, "years"),
- Expr (Minus, Var (NumericType, "years"), Val (Int 10))))
- equalTwoPosStmt("", Right (emptyPos, exp), runStmtsEof input)
- testCase "call function as expression" <| fun () ->
- // f(1) — должно обрабатываться раньше, чем `callProc arg1, arg2`
- let input = "iif(somevar >= 2, 'thenBody', 'elseBody')"
- let exp =
- (StarPl
- (Func
- (Predef Defines.Iif,
- [Expr (Ge, Var (NumericType, "somevar"), Val (Int 2));
- Val (String [[StringKind "thenBody"]]); Val (String [[StringKind "elseBody"]])])))
- equalTwoPosStmt("", Right (emptyPos, exp), runStmtsEof input)
- testCase "call procedure" <| fun () ->
- let input = "gt 'begin', 'real_character'"
- let exp =
- Proc ("gt", [Val (String [[StringKind "begin"]]); Val (String [[StringKind "real_character"]])])
- equalTwoPosStmt("", Right (emptyPos, exp), runStmtsEof input)
- // testCase "call " <| fun () ->
- // let input = "The(Lady), or, the, Tiger"
- // let exp =
- // CallSt ("gt", [Val (String "begin"); Val (String "real_character")])
- // Assert.Equal("", Right exp, runStmts input)
- ]
- module TestOnMocks =
- type T = Location list
- let enc = System.Text.Encoding.UTF8
- let startOnFile path =
- match Qsp.Parser.Main.startOnFile enc path with
- | Success(x, _, _) -> x
- | Failure(x, _, _) -> failwithf "%s\n%s" path x
- let replaceOrNot expPath actPath =
- printfn "\"%s\"\nnot equal\n\"%s\""
- (System.IO.Path.GetFullPath expPath)
- (System.IO.Path.GetFullPath actPath)
- let rec whileYOrN () =
- match System.Console.ReadKey().Key with
- | System.ConsoleKey.Y -> true
- | System.ConsoleKey.N -> false
- | x ->
- printfn "need (y/n) but %A" x
- whileYOrN ()
- printfn "Replace? (y/n)"
- let res = whileYOrN()
- if res then
- System.IO.File.Copy(actPath, expPath, true)
- printfn "replaced"
- res
- let addExpToPath path =
- path
- |> Path.changeFileNameWithoutExt (sprintf "%sExp")
- let outputDir = @"..\..\..\Mocks"
- let copyAsExp path =
- System.IO.File.Copy(path, addExpToPath path, true)
- let getPathActLocal (pathAct:string) =
- sprintf "%s\\%s" outputDir (System.IO.Path.GetFileName pathAct)
- |> fun x -> System.IO.Path.ChangeExtension(x, ".json")
- let showTest path =
- let srcPath = path
- let parseActPath = getPathActLocal srcPath
- let parseExpPath = addExpToPath parseActPath
- let getPath (path:string) =
- sprintf "%s\\%s" outputDir (System.IO.Path.GetFileName path)
- |> fun x -> System.IO.Path.ChangeExtension(x, ".qsps")
- let showActPath = getPath srcPath
- let showExpPath = addExpToPath showActPath
- let act =
- // if System.IO.File.Exists parseExpPath then
- // let src : T = Json.desf parseExpPath
- // src |> Qsp.Show.printLocs Qsp.Show.UsingTabs
- // else
- let act = startOnFile srcPath
- // act |> Json.serf parseExpPath
- // failwithf "\"%s\" не найден, потому пришлось его создать. Естественно, все тесты пошли коту под хвост." parseExpPath
- act |> Qsp.Show.printLocs Qsp.Show.UsingTabs Show.FormatConfig.Default
- let exp =
- if System.IO.File.Exists showExpPath then
- System.IO.File.ReadAllText showExpPath
- else
- System.IO.File.WriteAllText(showExpPath, act)
- failwithf "\"%s\" не найден, потому пришлось его создать. Естественно, все тесты пошли коту под хвост." showExpPath
- if exp <> act then
- System.IO.File.WriteAllText(showActPath, act)
- if replaceOrNot showExpPath showActPath then ()
- else failwithf "not pass"
- let mockTestList = "mock tests"
- [<Tests>]
- let showTests =
- let mocksDir = outputDir + @"\Src"
- let tests =
- if System.IO.Directory.Exists mocksDir then
- System.IO.Directory.GetFiles(mocksDir, "*.qsps")
- |> Array.map (fun path ->
- testCase (sprintf "'%s' test" (System.IO.Path.GetFullPath path)) <| fun () ->
- showTest path
- Assert.Equal("", true, true)
- )
- else [||]
- testList mockTestList tests
- [<EntryPoint;System.STAThread>]
- let main args =
- let isFullTest () =
- let rec whileYOrN () =
- match System.Console.ReadKey().Key with
- | System.ConsoleKey.Y -> true
- | System.ConsoleKey.N -> false
- | x ->
- printfn "`y` or `n` but %A" x
- whileYOrN ()
- printfn "Full test? (`y` or `n`)"
- whileYOrN ()
- let f isFullTest =
- if isFullTest then
- defaultMainThisAssembly args
- else
- defaultMainThisAssemblyFilter args
- (fun x ->
- x.Where(fun x -> not <| x.StartsWith TestOnMocks.mockTestList))
- match args with
- | [|"--full"|] -> f true
- | [||] ->
- f (isFullTest ())
- | _ ->
- printfn "`--full` or pass args but: %A" args
- 1
|