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"]
|
2024-08-01 23:09:57 +02:00
|
|
|
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")]
|
2024-08-01 23:09:57 +02:00
|
|
|
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
|