diff options
| author | Jan Tuomi <jans.tuomi@gmail.com> | 2022-01-29 23:11:03 +0200 |
|---|---|---|
| committer | Jan Tuomi <jans.tuomi@gmail.com> | 2022-01-29 23:11:03 +0200 |
| commit | 649319b1dafb130801638c5a156e37d9e865ba5c (patch) | |
| tree | 7bc633565d87c3bbebc7c67f6bbda10db6c13f21 /src/parser.hs | |
| parent | 4d1a0eea5a433724764b4178d16fcb50d1c2b6bc (diff) | |
Implement strings as phrases of chars
Diffstat (limited to 'src/parser.hs')
| -rw-r--r-- | src/parser.hs | 48 |
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) |
