elna/tests/Language/Elna/ParserSpec.hs

147 lines
6.2 KiB
Haskell
Raw Normal View History

2024-12-11 21:44:32 +01:00
{- This Source Code Form is subject to the terms of the Mozilla Public License,
v. 2.0. If a copy of the MPL was not distributed with this file, You can
obtain one at https://mozilla.org/MPL/2.0/. -}
2024-07-23 22:44:42 +02:00
module Language.Elna.ParserSpec
( spec
) where
2024-07-25 01:39:53 +02:00
import Test.Hspec (Spec, describe, it)
2024-07-23 22:44:42 +02:00
import Test.Hspec.Megaparsec (shouldParse, shouldSucceedOn, parseSatisfies)
import Language.Elna.Parser (programP)
import Text.Megaparsec (parse)
import Language.Elna.AST
( Declaration(..)
2024-07-25 01:39:53 +02:00
, Expression(..)
, Literal(..)
, Statement(..)
2024-07-23 22:44:42 +02:00
, Parameter(..)
, Program(..)
2024-07-25 01:39:53 +02:00
, VariableDeclaration(..)
2024-07-23 22:44:42 +02:00
, TypeExpression(..)
)
spec :: Spec
spec =
describe "programP" $ do
it "parses an empty main function" $
parse programP "" `shouldSucceedOn` "proc main() {}"
it "parses type definition for a type starting like array" $
let expected = Program [TypeDefinition "t" $ NamedType "arr"]
actual = parse programP "" "type t = arr;"
2024-07-23 22:44:42 +02:00
in actual `shouldParse` expected
it "parses array type definition" $
2024-07-26 12:22:07 +02:00
let expected = Program [TypeDefinition "t" $ ArrayType 10 (NamedType "int")]
actual = parse programP "" "type t = array[10] of int;"
2024-07-23 22:44:42 +02:00
in actual `shouldParse` expected
it "parses parameters" $
2024-07-26 12:22:07 +02:00
let given = "proc main(x: int) {}"
parameters = [Parameter "x" (NamedType "int") False]
2024-07-23 22:44:42 +02:00
expected = Program [ProcedureDefinition "main" parameters [] []]
actual = parse programP "" given
in actual `shouldParse` expected
it "parses ref parameters" $
2024-07-26 12:22:07 +02:00
let given = "proc main(x: int, ref y: boolean) {}"
2024-07-23 22:44:42 +02:00
parameters =
2024-07-26 12:22:07 +02:00
[ Parameter "x" (NamedType "int") False
2024-07-23 22:44:42 +02:00
, Parameter "y" (NamedType "boolean") True
]
expected = Program [ProcedureDefinition "main" parameters [] []]
actual = parse programP "" given
in actual `shouldParse` expected
it "parses variable declaration" $
2024-07-26 12:22:07 +02:00
let given = "proc main() { var x: int; }"
2024-07-23 22:44:42 +02:00
expected (Program [ProcedureDefinition _ _ variables _]) =
not $ null variables
expected _ = False
actual = parse programP "" given
in actual `parseSatisfies` expected
2024-07-25 01:39:53 +02:00
it "parses negation" $
2024-07-26 12:22:07 +02:00
let given = "proc main(x: int) { var y: int; y := -x; }"
parameters = pure $ Parameter "x" (NamedType "int") False
2024-07-25 01:39:53 +02:00
variables = pure
$ VariableDeclaration "y"
2024-07-26 12:22:07 +02:00
$ NamedType "int"
2024-07-25 01:39:53 +02:00
body = pure
$ AssignmentStatement (VariableExpression "y")
$ NegationExpression
$ VariableExpression "x"
expected = Program
[ProcedureDefinition "main" parameters variables body]
actual = parse programP "" given
in actual `shouldParse` expected
it "parses comparison with lower precedence than other binary operators" $
let given = "proc main() { var x: boolean; x := 1 + 2 = 3 * 4; }"
variables = pure
$ VariableDeclaration "x"
$ NamedType "boolean"
lhs = SumExpression (LiteralExpression (IntegerLiteral 1))
$ LiteralExpression (IntegerLiteral 2)
rhs = ProductExpression (LiteralExpression (IntegerLiteral 3))
$ LiteralExpression (IntegerLiteral 4)
body = pure
$ AssignmentStatement (VariableExpression "x")
$ EqualExpression lhs rhs
expected = Program
[ProcedureDefinition "main" [] variables body]
actual = parse programP "" given
in actual `shouldParse` expected
it "parses hexadecimals" $
2024-07-26 12:22:07 +02:00
let given = "proc main() { var x: int; x := 0x10; }"
2024-07-25 01:39:53 +02:00
variables = pure
$ VariableDeclaration "x"
2024-07-26 12:22:07 +02:00
$ NamedType "int"
2024-07-25 01:39:53 +02:00
body = pure
$ AssignmentStatement (VariableExpression "x")
$ LiteralExpression (HexadecimalLiteral 16)
expected = Program
[ProcedureDefinition "main" [] variables body]
actual = parse programP "" given
in actual `shouldParse` expected
it "parses procedure calls" $
let given = "proc main() { f('c'); }"
body = pure
$ CallStatement "f" [LiteralExpression (CharacterLiteral 99)]
expected = Program
[ProcedureDefinition "main" [] [] body]
actual = parse programP "" given
in actual `shouldParse` expected
it "parses an if statement" $
let given = "proc main() { if (true) ; }"
body = pure
$ IfStatement (LiteralExpression $ BooleanLiteral True) EmptyStatement Nothing
expected = Program
[ProcedureDefinition "main" [] [] body]
actual = parse programP "" given
in actual `shouldParse` expected
it "associates else with the nearst if statement" $
let given = "proc main() { if (true) if (false) ; else ; }"
if' = IfStatement (LiteralExpression $ BooleanLiteral False) EmptyStatement
$ Just EmptyStatement
body = pure
$ IfStatement (LiteralExpression $ BooleanLiteral True) if' Nothing
expected = Program
[ProcedureDefinition "main" [] [] body]
actual = parse programP "" given
in actual `shouldParse` expected
it "parses a while statement" $
let given = "proc main() { while (true) ; }"
body = pure
$ WhileStatement (LiteralExpression $ BooleanLiteral True) EmptyStatement
expected = Program
[ProcedureDefinition "main" [] [] body]
actual = parse programP "" given
in actual `shouldParse` expected