summaryrefslogtreecommitdiffstats
path: root/src/parser.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser.hs')
-rw-r--r--src/parser.hs48
1 files changed, 48 insertions, 0 deletions
diff --git a/src/parser.hs b/src/parser.hs
new file mode 100644
index 0000000..79c30be
--- /dev/null
+++ b/src/parser.hs
@@ -0,0 +1,48 @@
+module Parser where
+
+import qualified Data.Bifunctor as B
+import qualified Data.Hashable as DH
+import Data.List (isPrefixOf)
+import Data.Map (Map, (!))
+import qualified Data.Map as M
+import qualified Data.Text as T
+import LTypes
+import Utils
+
+parseWord rawStr
+ | isIntStr rawStr = LInteger (read rawStr)
+ | isFloatStr rawStr = LFloat $ read rawStr
+ | isCharStr rawStr = LChar $ rawStr !! 1
+ | "##" `isPrefixOf` rawStr = LStringLitRef $ drop 2 rawStr
+ | "$" `isPrefixOf` rawStr = LLabel $ tail rawStr
+ | otherwise = LSymbol rawStr
+
+removeComments source =
+ let lines_ = lines source $> map (T.pack .> T.splitOn (T.pack "--") .> head .> T.unpack)
+ in unlines lines_
+
+processStringLiterals source =
+ let refMap = M.empty
+ in processStringLiterals' Nothing refMap source
+
+processStringLiterals' :: Maybe String -> Map String String -> String -> (String, Map String String)
+processStringLiterals' currentM refMap [] = case currentM of
+ Just _ -> error "[error] nonterminated string literal"
+ Nothing -> ([], refMap)
+processStringLiterals' currentM refMap (c : source) = case c of
+ '"' -> case currentM of
+ Just str ->
+ let hash = DH.hash str $> show
+ newRefMap = M.insert hash str refMap
+ (resSource, resRefMap) = processStringLiterals' Nothing newRefMap source
+ in ("##" ++ hash ++ resSource, resRefMap)
+ Nothing ->
+ processStringLiterals' (Just "") refMap source
+ other -> case currentM of
+ Just str -> processStringLiterals' (Just $ str ++ [c]) refMap source
+ Nothing -> processStringLiterals' Nothing refMap source $> B.first (c :)
+
+parseSource source =
+ let woComments = source $> removeComments
+ (woStringLiterals, stringLiteralRefMap) = processStringLiterals woComments
+ in (woStringLiterals $> words .> map parseWord, stringLiteralRefMap)