Skip to content

Commit 4882dce

Browse files
committed
add token parsing for function calls and add function types
1 parent 6c76c93 commit 4882dce

File tree

3 files changed

+35
-3
lines changed

3 files changed

+35
-3
lines changed

lib/Mentat/ParseTypes.hs

+2-2
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ data Token
8383
data Function = Function String [String] Expr deriving (Show, Eq)
8484

8585
-- | Used as an intermediate step in the parsing process to validate parens and sort them into sub trees
86-
data TokTree = TLeaf Token | TNode Bracket [TokTree] | TFxn Function deriving (Show, Eq)
86+
data TokTree = TLeaf Token | TNode Bracket [TokTree] | TFxn String [[TokTree]] deriving (Show, Eq)
8787

8888

8989
-- | Literal values of float or boolean
@@ -95,7 +95,7 @@ data Expr
9595
= LitE Literal
9696
| VarE String
9797
| BinOpE BinOp Expr Expr
98-
| FxnE Function
98+
| FxnE String [Expr]
9999
deriving (Show, Eq)
100100

101101

lib/Mentat/Tokenizer.hs

+18
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
module Mentat.Tokenizer where
22
import Mentat.ParseTypes
3+
import Data.List.Split ( splitOn )
34

45
tokSubTree :: TokTree -> [TokTree]
56
tokSubTree (TNode _ ts) = ts
@@ -20,6 +21,15 @@ parseInner (TClose x : xs) (y : ys)
2021
| x /= y = Left $ MismatchedBracket (y : ys) (TClose x : xs)
2122
| otherwise = Right (xs, [])
2223
parseInner (TClose x : xs) [] = Left $ UnclosedBracket [] (TClose x : xs)
24+
parseInner (TId name : TOpen Paren : cRest) stack = do
25+
let maybeFxn = parseFxnCall (TId name : TOpen Paren : cRest)
26+
case maybeFxn of
27+
Right (restAfterFxn, fxnCall) -> do
28+
(restToks, rest) <- parseInner restAfterFxn stack
29+
pure (restToks, fxnCall : rest)
30+
Left _ -> do
31+
(restTokens, rest) <- parseInner (TOpen Paren : cRest) stack
32+
pure (restTokens, TLeaf (TId name) : rest)
2333
parseInner (TOpen x : xs) stack = do
2434
-- don't need cases since errors are infective
2535
(tokAfterInner, inner) <- parseInner xs (x : stack) -- parse inner for bracket x
@@ -29,3 +39,11 @@ parseInner (x : xs) stack = do
2939
(restTokens, rest) <- parseInner xs stack
3040
pure (restTokens, TLeaf x : rest)
3141

42+
parseFxnCall :: [Token] -> Either Error ([Token], TokTree)
43+
parseFxnCall (TId name : TOpen Paren : TClose Paren : rest) = Right (rest, TFxn name [[]])
44+
parseFxnCall (TId name : TOpen Paren : call) = do
45+
(rest, argToks) <- parseInner call [Paren]
46+
let args = splitOn [TLeaf TSep] argToks
47+
Right (rest, TFxn name args)
48+
parseFxnCall _ = Left UnfinishedTokenStream -- add an error
49+

test/TokenizerSpec.hs

+15-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import Mentat.ParseTypes
66
import Mentat.Tokenizer
77
import Prelude hiding (lex)
88
import Test.Hspec
9-
import Data.Foldable (concat)
109

1110
concatTokenList :: [Token] -> String
1211
concatTokenList [] = ""
@@ -66,4 +65,19 @@ spec = do
6665
case tokTreeResult of
6766
Right tokTrees -> tokTrees `shouldBe` expected
6867
Left err -> error $ "unexpected error " ++ show err
68+
describe "Parsing function calls into TokTrees" $ do
69+
let cases =
70+
[ ("f()", [TFxn "f" [[]]])
71+
, ("f(1, 2)", [TFxn "f" [[TLeaf $ TNumber 1], [TLeaf $ TNumber 2]]])
72+
, ("f(n - 1)", [TFxn "f" [[TLeaf $ TId "n", TLeaf $ TOp Sub, TLeaf $ TNumber 1]]])
73+
, ("f(f(n + 1))", [TFxn "f" [[TFxn "f" [[TLeaf $ TId "n", TLeaf $ TOp Add, TLeaf $ TNumber 1]]]]])
74+
, ("f(2 * (n - 1))",[TFxn "f" [[ TLeaf $ TNumber 2, TLeaf $ TOp Mul, TNode Paren [TLeaf $ TId "n", TLeaf $ TOp Sub, TLeaf $ TNumber 1]]]])
75+
]
76+
77+
forM_ cases $ \(input, expected) ->
78+
it ("Parses: " ++ show input) $ do
79+
let tokTreeResult = parseTokTree $ lex input
80+
case tokTreeResult of
81+
Right tokTrees -> tokTrees `shouldBe` expected
82+
Left err -> error $ "unexpected error " ++ show err
6983

0 commit comments

Comments
 (0)