blob: 79c30bef21cc58784732794216be094e89ef8366 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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)
|