<commit_before>module Commands.Parsers where

import Filesystem.Path.CurrentOS
import Filesystem.Path
import Text.Parsec

import Prelude hiding (until)


parseObjC :: String -> Either ParseError ([String], String)
parseObjC = parse objcFile ""

-- | extracts the imports and the implementation/interface code from a simple ".m" or ".h" file
objcFile = do
 inclusions <- many inclusion
 spaces
 body' <- body
 return (inclusions, body')

-- | crude parser: fails against whitespace
inclusion
 =   (everythingBetweenExclusively (string "#import ")  (char '\n'))
 <|> (everythingBetweenExclusively (string "#include ") (char '\n'))

-- | crude parser: fails against comments and strings
body
 =   (everythingBetweenInclusively (string "@implementation") (string "@end"))
 <|> (everythingBetweenInclusively (string "@interface")      (string "@end"))

everythingBetweenExclusively open close = try $ between open close (until close) 

everythingBetweenInclusively open close = try $ betweenInclusively open close (until close) 

-- | 'between' is exclusive
betweenInclusively open close parser = do
 x <- open
 y <- parser
 z <- close
 return $ x ++ y ++ z

-- | 
--
-- 'try' doesn't consume on failure and consumes on success
--
-- 'lookAhead' doesn't consume on success and errors on failure
until parser = anyChar `manyTill` ((try . lookAhead) parser)

<commit_msg>refactor: Monadic parsec to Applicative parsec<commit_after>module Commands.Parsers where

import Text.Parsec

import Prelude hiding (until)
import Control.Applicative ((<$>), (<*>), (<*), (*>))


parseObjC :: String -> Either ParseError ([String], String)
parseObjC = parse objcFile ""

-- | extracts the imports and the implementation/interface code from a simple ".m" or ".h" file
objcFile = (,) <$> (many inclusion <* spaces) <*> body

-- | crude parser: fails against whitespace
inclusion
 =   (try $ everythingBetweenExclusively (string "#import ")  (char '\n'))
 <|> (try $ everythingBetweenExclusively (string "#include ") (char '\n'))

-- | crude parser: fails against comments and strings
body
 =   (try $ everythingBetweenInclusively (string "@implementation") (string "@end"))
 <|> (try $ everythingBetweenInclusively (string "@interface")      (string "@end"))

everythingBetweenExclusively open close = between            open close (until close) 
everythingBetweenInclusively open close = betweenInclusively open close (until close) 

-- | 'between' is exclusive
betweenInclusively open close parser = (+++) <$> open <*> parser <*> close
 where (+++) x y z = x ++ y ++ z

-- | 
--
-- 'try' doesn't consume on failure and consumes on success
--
-- 'lookAhead' doesn't consume on success and errors on failure
until parser = anyChar `manyTill` ((try . lookAhead) parser)

-- $ cabal exec runhaskell sources/Commands/Parsers.hs
main = do
 parseObjC <$> readFile "actor.m" >>= print

{'fraction_non_alphanumeric': 0.129111266620014, 'fraction_numerical': 0.0, 'mean_word_length': 4.3439252336448595, 'pattern_counts': {'":': 0, '<': 22, '<?xml version=': 0, '>': 20, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4368039', 'n_tokens_mistral': 875, 'n_tokens_neox': 786, 'n_words': 292}