-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
fd7f20e
commit f87a1a1
Showing
9 changed files
with
167 additions
and
87 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
module Ast.Parser.Env where | ||
|
||
import qualified Ast.Types as AT | ||
|
||
-- | The environment for storing custom type definitions. | ||
newtype Env = Env [(String, AT.Type)] | ||
|
||
-- | Creates an empty environment. | ||
emptyEnv :: Env | ||
emptyEnv = Env [] | ||
|
||
-- | Inserts a custom type into the environment. | ||
-- If the type already exists, it overwrites it. | ||
insertType :: String -> AT.Type -> Env -> Env | ||
insertType name ty (Env env) = Env ((name, ty) : filter ((/= name) . fst) env) | ||
|
||
-- | Looks up a custom type in the environment by its name. | ||
lookupType :: String -> Env -> Maybe AT.Type | ||
lookupType name (Env env) = lookup name env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,66 +1,71 @@ | ||
module Ast.Parser.LiteralSpec (spec) where | ||
|
||
import qualified Ast.Parser.Env as E | ||
import qualified Ast.Parser.Literal as AL | ||
import qualified Ast.Types as AT | ||
import qualified Control.Monad.State as S | ||
import Data.Either (isLeft) | ||
import Test.Hspec | ||
import qualified Text.Megaparsec as M | ||
|
||
spec :: Spec | ||
spec = do | ||
let initialEnv = E.emptyEnv | ||
let parseWithEnv input = fst $ S.runState (M.runParserT AL.parseLiteral "" input) initialEnv | ||
|
||
describe "parseInt" $ do | ||
it "parses positive integers" $ do | ||
M.parse AL.parseLiteral "" "123" `shouldBe` Right (AT.LInt 123) | ||
parseWithEnv "123" `shouldBe` Right (AT.LInt 123) | ||
|
||
it "parses negative integers" $ do | ||
M.parse AL.parseLiteral "" "-456" `shouldBe` Right (AT.LInt (-456)) | ||
parseWithEnv "-456" `shouldBe` Right (AT.LInt (-456)) | ||
|
||
it "fails on non-integer input" $ do | ||
isLeft (M.parse AL.parseLiteral "" "abc") `shouldBe` True | ||
isLeft (parseWithEnv "abc") `shouldBe` True | ||
|
||
describe "parseFloat" $ do | ||
it "parses positive floats" $ do | ||
M.parse AL.parseLiteral "" "123.45" `shouldBe` Right (AT.LFloat 123.45) | ||
parseWithEnv "123.45" `shouldBe` Right (AT.LFloat 123.45) | ||
|
||
it "parses negative floats" $ do | ||
M.parse AL.parseLiteral "" "-67.89" `shouldBe` Right (AT.LFloat (-67.89)) | ||
parseWithEnv "-67.89" `shouldBe` Right (AT.LFloat (-67.89)) | ||
|
||
it "fails on non-float input" $ do | ||
isLeft (M.parse AL.parseLiteral "" "abc") `shouldBe` True | ||
isLeft (parseWithEnv "abc") `shouldBe` True | ||
|
||
describe "parseBool" $ do | ||
it "parses true" $ do | ||
M.parse AL.parseLiteral "" "true" `shouldBe` Right (AT.LBool True) | ||
parseWithEnv "true" `shouldBe` Right (AT.LBool True) | ||
|
||
it "parses false" $ do | ||
M.parse AL.parseLiteral "" "false" `shouldBe` Right (AT.LBool False) | ||
parseWithEnv "false" `shouldBe` Right (AT.LBool False) | ||
|
||
it "fails on invalid input" $ do | ||
isLeft (M.parse AL.parseLiteral "" "maybe") `shouldBe` True | ||
isLeft (parseWithEnv "maybe") `shouldBe` True | ||
|
||
describe "parseChar" $ do | ||
it "parses a single character" $ do | ||
M.parse AL.parseLiteral "" "'a'" `shouldBe` Right (AT.LChar 'a') | ||
parseWithEnv "'a'" `shouldBe` Right (AT.LChar 'a') | ||
|
||
it "fails on invalid input" $ do | ||
isLeft (M.parse AL.parseLiteral "" "'abc'") `shouldBe` True | ||
isLeft (parseWithEnv "'abc'") `shouldBe` True | ||
|
||
describe "parseArray" $ do | ||
it "parses an array of integers" $ do | ||
M.parse AL.parseLiteral "" "[1,2,3]" `shouldBe` Right (AT.LArray [AT.LInt 1, AT.LInt 2, AT.LInt 3]) | ||
parseWithEnv "[1,2,3]" `shouldBe` Right (AT.LArray [AT.LInt 1, AT.LInt 2, AT.LInt 3]) | ||
|
||
it "parses an array of mixed literals" $ do | ||
M.parse AL.parseLiteral "" "[true,'a',123]" `shouldBe` Right (AT.LArray [AT.LBool True, AT.LChar 'a', AT.LInt 123]) | ||
parseWithEnv "[true,'a',123]" `shouldBe` Right (AT.LArray [AT.LBool True, AT.LChar 'a', AT.LInt 123]) | ||
|
||
it "parses a string literal as an array of characters" $ do | ||
M.parse AL.parseLiteral "" "\"hello\"" `shouldBe` Right (AT.LArray (map AT.LChar "hello")) | ||
parseWithEnv "\"hello\"" `shouldBe` Right (AT.LArray (map AT.LChar "hello")) | ||
|
||
it "fails on invalid input" $ do | ||
isLeft (M.parse AL.parseLiteral "" "[1,true,]") `shouldBe` True | ||
isLeft (parseWithEnv "[1,true,]") `shouldBe` True | ||
|
||
describe "parseNull" $ do | ||
it "parses null" $ do | ||
M.parse AL.parseLiteral "" "null" `shouldBe` Right AT.LNull | ||
parseWithEnv "null" `shouldBe` Right AT.LNull | ||
|
||
it "fails on non-null input" $ do | ||
isLeft (M.parse AL.parseLiteral "" "none") `shouldBe` True | ||
isLeft (parseWithEnv "none") `shouldBe` True |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,76 +1,82 @@ | ||
module Ast.Parser.OperationSpec where | ||
|
||
import qualified Ast.Parser.Env as E | ||
import qualified Ast.Parser.Operation as AO | ||
import qualified Ast.Types as AT | ||
import qualified Control.Monad.State as S | ||
import Data.Either (isLeft) | ||
import Test.Hspec | ||
import qualified Text.Megaparsec as M | ||
|
||
spec :: Spec | ||
spec = do | ||
let initialEnv = E.emptyEnv | ||
let parseWithEnv input = fst $ S.runState (M.runParserT AO.parseOperation "" input) initialEnv | ||
|
||
describe "parseOperation" $ do | ||
it "parses addition operator" $ do | ||
M.parse AO.parseOperation "" "+" `shouldBe` Right AT.Add | ||
parseWithEnv "+" `shouldBe` Right AT.Add | ||
|
||
it "parses subtraction operator" $ do | ||
M.parse AO.parseOperation "" "-" `shouldBe` Right AT.Sub | ||
parseWithEnv "-" `shouldBe` Right AT.Sub | ||
|
||
it "parses multiplication operator" $ do | ||
M.parse AO.parseOperation "" "*" `shouldBe` Right AT.Mul | ||
parseWithEnv "*" `shouldBe` Right AT.Mul | ||
|
||
it "parses division operator" $ do | ||
M.parse AO.parseOperation "" "/" `shouldBe` Right AT.Div | ||
parseWithEnv "/" `shouldBe` Right AT.Div | ||
|
||
it "parses modulo operator" $ do | ||
M.parse AO.parseOperation "" "mod" `shouldBe` Right AT.Mod | ||
parseWithEnv "mod" `shouldBe` Right AT.Mod | ||
|
||
it "parses bitwise AND operator" $ do | ||
M.parse AO.parseOperation "" "&" `shouldBe` Right AT.BitAnd | ||
parseWithEnv "&" `shouldBe` Right AT.BitAnd | ||
|
||
it "parses bitwise OR operator" $ do | ||
M.parse AO.parseOperation "" "|" `shouldBe` Right AT.BitOr | ||
parseWithEnv "|" `shouldBe` Right AT.BitOr | ||
|
||
it "parses bitwise XOR operator" $ do | ||
M.parse AO.parseOperation "" "^" `shouldBe` Right AT.BitXor | ||
parseWithEnv "^" `shouldBe` Right AT.BitXor | ||
|
||
it "parses left shift operator" $ do | ||
M.parse AO.parseOperation "" "<<" `shouldBe` Right AT.BitShl | ||
parseWithEnv "<<" `shouldBe` Right AT.BitShl | ||
|
||
it "parses right shift operator" $ do | ||
M.parse AO.parseOperation "" ">>" `shouldBe` Right AT.BitShr | ||
parseWithEnv ">>" `shouldBe` Right AT.BitShr | ||
|
||
it "parses less than operator" $ do | ||
M.parse AO.parseOperation "" "<" `shouldBe` Right AT.Lt | ||
parseWithEnv "<" `shouldBe` Right AT.Lt | ||
|
||
it "parses greater than operator" $ do | ||
M.parse AO.parseOperation "" ">" `shouldBe` Right AT.Gt | ||
parseWithEnv ">" `shouldBe` Right AT.Gt | ||
|
||
it "parses less than or equal to operator" $ do | ||
M.parse AO.parseOperation "" "<=" `shouldBe` Right AT.Lte | ||
parseWithEnv "<=" `shouldBe` Right AT.Lte | ||
|
||
it "parses greater than or equal to operator" $ do | ||
M.parse AO.parseOperation "" ">=" `shouldBe` Right AT.Gte | ||
parseWithEnv ">=" `shouldBe` Right AT.Gte | ||
|
||
it "parses equality operator" $ do | ||
M.parse AO.parseOperation "" "==" `shouldBe` Right AT.Eq | ||
parseWithEnv "==" `shouldBe` Right AT.Eq | ||
|
||
it "parses 'is' equality operator" $ do | ||
M.parse AO.parseOperation "" "is" `shouldBe` Right AT.Eq | ||
parseWithEnv "is" `shouldBe` Right AT.Eq | ||
|
||
it "parses inequality operator" $ do | ||
M.parse AO.parseOperation "" "!=" `shouldBe` Right AT.Ne | ||
parseWithEnv "!=" `shouldBe` Right AT.Ne | ||
|
||
it "parses logical AND operator" $ do | ||
M.parse AO.parseOperation "" "&&" `shouldBe` Right AT.And | ||
parseWithEnv "&&" `shouldBe` Right AT.And | ||
|
||
it "parses 'and' logical operator" $ do | ||
M.parse AO.parseOperation "" "and" `shouldBe` Right AT.And | ||
parseWithEnv "and" `shouldBe` Right AT.And | ||
|
||
it "parses logical OR operator" $ do | ||
M.parse AO.parseOperation "" "||" `shouldBe` Right AT.And | ||
parseWithEnv "||" `shouldBe` Right AT.Or | ||
|
||
it "parses 'or' logical operator" $ do | ||
M.parse AO.parseOperation "" "or" `shouldBe` Right AT.And | ||
parseWithEnv "or" `shouldBe` Right AT.Or | ||
|
||
it "returns error for invalid operator" $ do | ||
M.parse AO.parseOperation "" "invalid" `shouldSatisfy` isLeft | ||
let result = parseWithEnv "invalid" | ||
isLeft result `shouldBe` True |
Oops, something went wrong.