-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathParsec.hs
55 lines (44 loc) · 1.54 KB
/
Parsec.hs
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
49
50
51
52
53
54
module Parsec ( module Orig, module Parsec ) where
import Text.Parsec as Orig hiding (char,string,Stream,parse,satisfy,oneOf,noneOf)
import qualified Text.Parsec as Base (char,string,satisfy)
import Control.Monad.Reader
type Stream = String
data RS = RS
{ skipLineContinuation :: Bool }
type Parser = ParsecT Stream () (Reader RS)
lineConts :: Parser ()
lineConts = do
many $ try $ Base.string "\\\n"
return ()
dontSkipLineConts p = do
-- skip line conts before, do not skip inside
lineConts
local dontSkip p
where
dontSkip rs = rs { skipLineContinuation = False }
-- if skipLineContinuation is True, line continuation will be skipped /before/
-- the char
satisfy :: (Char -> Bool) -> Parser Char
satisfy f = try $ do
skiplc <- asks skipLineContinuation
if skiplc
then do lineConts; Base.satisfy f
else Base.satisfy f
-- if skipLineContinuation is True, line continuation will be skipped /before/
-- the char
char :: Char -> Parser Char
char x = try $ do
skiplc <- asks skipLineContinuation
if skiplc
then do lineConts; Base.char x
else Base.char x
-- if skipLineContinuation is True, line continuation will be skipped before and
-- inside the string
string :: String -> Parser String
string s = try $ do
sequence $ map char s
return s
parse :: Parser a -> SourceName -> Stream -> Either ParseError a
parse p name s = runReader (runPT p () name s) RS { skipLineContinuation = True }
oneOf cs = try $ satisfy (\c -> elem c cs)
noneOf cs = try $ satisfy (\c -> not (elem c cs))