aboutsummaryrefslogtreecommitdiff
path: root/Sil/Util/Parser.icl
blob: 34cf057350aef826baaaaca2b21fb163046cc881 (plain) (blame)
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
implementation module Sil.Util.Parser

import StdList
import StdOverloaded

import Control.Applicative
import Control.Monad
import Data.Error
from Data.Func import $
import Data.Functor
import Data.List
import Data.Maybe

import Sil.Error

fromPositioned :: (Positioned a) -> a
fromPositioned p = p.pos_val

:: ParseState a =
	{ ps_line  :: Int
	, ps_input :: [ParseInput a]
	, ps_read  :: [ParseInput a]
	}

makeParseState :: [ParseInput a] -> ParseState a
makeParseState i = {ps_line=1, ps_input=i, ps_read=[]}

nextToken :: (ParseState a) -> (Maybe a, ParseState a)
nextToken ps = case ps.ps_input of
	[]             -> (Nothing, ps)
	[PI_Token t:i] -> (Just t, {ps & ps_read=[PI_Token t:ps.ps_read], ps_input=i})
	[PI_NewLine:i] -> nextToken {ps & ps_line=ps.ps_line + 1, ps_read=[PI_NewLine:ps.ps_read], ps_input=i}

tokenBack :: (ParseState a) -> ParseState a
tokenBack ps = case ps.ps_read of
	[]             -> ps
	[PI_Token t:r] -> {ps & ps_read=r, ps_input=[PI_Token t:ps.ps_input]}
	[PI_NewLine:r] -> tokenBack {ps & ps_read=r, ps_input=[PI_NewLine:ps.ps_input], ps_line=ps.ps_line-1}

instance Functor (Parser a) where
	fmap f m = liftM f m

instance Applicative (Parser a) where
	pure a     = Parser \st -> (Ok a, st)
	(<*>) sf p = ap sf p

instance Monad (Parser a) where
	bind p f = Parser \st -> case runParser p st of
		(Ok r, rest) -> runParser (f r) rest
		(Error e, _) -> (Error e, st)

instance Alternative (Parser a) where
	empty       = Parser \st -> (Error $ UnknownError "empty in Parser", st)
	(<|>) p1 p2 = Parser \st -> case runParser p1 st of
		(Ok r, rest)     -> (Ok r, rest)
		(Error e1, rest) -> case runParser p2 st of
			(Error e2, rest) -> (Error e2, st)
			(Ok r, rest)     -> (Ok r, rest)

instance name String where name s = s

runParser :: (Parser a b) (ParseState a) -> (MaybeError Error b, ParseState a)
runParser (Parser f) i = f i

getPositioner :: Parser a (b -> Positioned b)
getPositioner = Parser \st -> (Ok \x -> {pos_line=st.ps_line, pos_val=x}, st)

(<?>) :: (Parser a b) Error -> Parser a b
(<?>) p e = Parser \i -> case runParser p i of
	(Error _, rest) -> (Error e, rest)
	o               -> o

fail :: Parser a b
fail = empty

top :: Parser a a
top = Parser \st -> case nextToken st of
	(Nothing, st) -> (Error $ UnknownError "top in Parser failed", st)
	(Just x,  st) -> (Ok x, st)

peek :: Parser a a
peek = Parser \st -> case nextToken st of
	(Nothing, st) -> (Error $ UnknownError "peek in Parser failed", st)
	(Just x,  st) -> (Ok x, tokenBack st)

satisfy :: (a -> Bool) -> Parser a a
satisfy f = top >>= \r -> if (f r) (pure r) fail

check :: (a -> Bool) -> Parser a a
check f = peek >>= \r -> if (f r) (pure r) fail

(until) infix 2 :: (Parser a b) (Parser a c) -> Parser a [b]
(until) p guard = try $ until` p guard [] 
where
	until` :: (Parser a b) (Parser a c) [b] -> Parser a [b]
	until` p guard acc = Parser \st -> case runParser guard st of
		(Ok _, rest) -> (Ok acc, rest)
		(Error _, _) -> case runParser p st of
			(Ok r, rest) -> runParser (until` p guard [r:acc]) rest
			(Error e, _) -> (Error e, st)

	try :: (Parser a b) -> Parser a b
	try p = Parser \st -> case runParser p st of
		(Error e, _) -> (Error e, st)
		(Ok r, rest) -> (Ok r, rest)

item :: a -> Parser a a | ==, name a
item a  = satisfy ((==) a) <?> P_Expected (name a)

list :: [a] -> Parser a [a] | ==, name a
list as = mapM item as

seplist :: a (Parser a b) -> Parser a [b] | ==, name a
seplist sep p = liftM2 (\es e-> es ++ [e]) (some (p <* item sep)) p
	<|> liftM pure p
	<|> pure empty

eof :: Parser a ()
eof = Parser \st -> case nextToken st of
	(Nothing, st) -> (Ok (), st)
	(_, st)       -> (Error $ P_Expected "eof", st)