Skip to content

Commit 91652be

Browse files
committed
Fix Parser.Expr module, split up modules.
1 parent 3f9e7b9 commit 91652be

File tree

6 files changed

+231
-191
lines changed

6 files changed

+231
-191
lines changed

Makefile

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,18 @@ all: lib test
33
lib:
44
mkdir -p js/Text/Parsing
55
psc src/Text/Parsing/Parser.purs.hs \
6+
src/Text/Parsing/Parser/String.purs.hs \
7+
src/Text/Parsing/Parser/Combinators.purs.hs \
8+
src/Text/Parsing/Parser/Expr.purs.hs \
69
-o js/Text/Parsing/Parser.js \
710
-e js/Text/Parsing/Parser.e.purs.hs \
811
--module Text.Parsing.Parser --tco --magic-do
912

1013
test:
11-
psc src/Text/Parsing/Parser.purs.hs examples/test.purs.hs \
14+
psc src/Text/Parsing/Parser.purs.hs \
15+
src/Text/Parsing/Parser/String.purs.hs \
16+
src/Text/Parsing/Parser/Combinators.purs.hs \
17+
src/Text/Parsing/Parser/Expr.purs.hs \
18+
examples/test.purs.hs \
1219
-o js/test.js \
1320
--main --module Main --tco --magic-do

examples/test.purs.hs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import Data.Maybe
77
import Control.Monad.Eff
88
import Debug.Trace
99
import Text.Parsing.Parser
10+
import Text.Parsing.Parser.Combinators
11+
import Text.Parsing.Parser.Expr
12+
import Text.Parsing.Parser.String
1013

1114
parens :: forall a. ({} -> Parser String a) -> Parser String a
1215
parens = between (string "(") (string ")")
@@ -24,6 +27,22 @@ parseTest p input = case runParser p input of
2427
opTest = chainl char (do string "+"
2528
return (++)) ""
2629

30+
digit = (string "0" >>= \_ -> return 0)
31+
<|> (string "1" >>= \_ -> return 1)
32+
<|> (string "2" >>= \_ -> return 2)
33+
<|> (string "3" >>= \_ -> return 3)
34+
<|> (string "4" >>= \_ -> return 4)
35+
<|> (string "5" >>= \_ -> return 5)
36+
<|> (string "6" >>= \_ -> return 6)
37+
<|> (string "7" >>= \_ -> return 7)
38+
<|> (string "8" >>= \_ -> return 8)
39+
<|> (string "9" >>= \_ -> return 9)
40+
41+
exprTest = buildExprParser [[Infix (string "/" >>= \_ -> return (/)) AssocRight]
42+
,[Infix (string "*" >>= \_ -> return (*)) AssocRight]
43+
,[Infix (string "-" >>= \_ -> return (-)) AssocRight]
44+
,[Infix (string "+" >>= \_ -> return (+)) AssocRight]] digit
45+
2746
main = do
2847
parseTest (nested {}) "(((a)))"
2948
parseTest (many (string "a")) "aaa"
@@ -36,3 +55,4 @@ main = do
3655
eof
3756
return as) "a,a,a,"
3857
parseTest opTest "a+b+c"
58+
parseTest exprTest "1*2+3/4-5"

src/Text/Parsing/Parser.purs.hs

Lines changed: 1 addition & 190 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import Control.Monad
55
import Data.Array
66
import Data.Either
77
import Data.Maybe
8-
import Data.String
98

109
data ParseError = ParseError
1110
{ message :: String
@@ -47,204 +46,16 @@ instance monadParser :: Prelude.Monad (Parser s) where
4746
return a = Parser $ \s -> successResult s false a
4847
(>>=) p f = Parser $ \s -> case runParser p s of
4948
ParseResult ({ leftover = s', consumed = consumed, result = Left err }) -> failureResult s' consumed err
50-
ParseResult ({ leftover = s', consumed = consumed, result = Right a }) -> runParser (f a) s' -- TODO
49+
ParseResult ({ leftover = s', consumed = consumed, result = Right a }) -> runParser (f a) s'
5150

5251
instance monadAlternative :: Prelude.Alternative (Parser s) where
5352
empty = fail "No alternative"
5453
(<|>) p1 p2 = Parser $ \s -> case runParser p1 s of
5554
ParseResult ({ leftover = s', consumed = false, result = Left _ }) -> runParser p2 s
5655
res -> res
5756

58-
-- Polymorphic Parser Combinators
59-
6057
fail :: forall s a. String -> Parser s a
6158
fail message = Parser $ \s -> failureResult s false (parseError message)
6259

63-
(<?>) :: forall s a. Parser s a -> String -> Parser s a
64-
(<?>) p msg = p <|> fail msg
65-
66-
many :: forall s a. Parser s a -> Parser s [a]
67-
many p = many1 p <|> return []
68-
69-
many1 :: forall s a. Parser s a -> Parser s [a]
70-
many1 p = do a <- p
71-
as <- many p
72-
return (a : as)
73-
74-
between :: forall s a open close. Parser s open -> Parser s close -> ({} -> Parser s a) -> Parser s a
75-
between open close p = do
76-
open
77-
a <- p {}
78-
close
79-
return a
80-
81-
option :: forall s a. a -> Parser s a -> Parser s a
82-
option a p = p <|> return a
83-
84-
optional :: forall s a. Parser s a -> Parser s {}
85-
optional p = (do p
86-
return {}) <|> return {}
87-
88-
optionMaybe :: forall s a. Parser s a -> Parser s (Maybe a)
89-
optionMaybe p = option Nothing (Just <$> p)
90-
91-
try :: forall s a. Parser s a -> Parser s a
92-
try p = Parser $ \s -> case runParser p s of
93-
ParseResult ({ consumed = true, result = Left err }) -> failureResult s false err
94-
res -> res
95-
96-
sepBy :: forall s a sep. Parser s a -> Parser s sep -> Parser s [a]
97-
sepBy p sep = sepBy1 p sep <|> return []
98-
99-
sepBy1 :: forall s a sep. Parser s a -> Parser s sep -> Parser s [a]
100-
sepBy1 p sep = do
101-
a <- p
102-
as <- many $ do
103-
sep
104-
p
105-
return (a : as)
106-
107-
sepEndBy :: forall s a sep. Parser s a -> Parser s sep -> Parser s [a]
108-
sepEndBy p sep = sepEndBy1 p sep <|> return []
109-
110-
sepEndBy1 :: forall s a sep. Parser s a -> Parser s sep -> Parser s [a]
111-
sepEndBy1 p sep = do
112-
a <- p
113-
(do sep
114-
as <- sepEndBy p sep
115-
return (a : as)) <|> return [a]
116-
117-
endBy1 :: forall s a sep. Parser s a -> Parser s sep -> Parser s [a]
118-
endBy1 p sep = many1 $ do
119-
a <- p
120-
sep
121-
return a
122-
123-
endBy :: forall s a sep. Parser s a -> Parser s sep -> Parser s [a]
124-
endBy p sep = many $ do
125-
a <- p
126-
sep
127-
return a
128-
129-
chainr :: forall s a. Parser s a -> Parser s (a -> a -> a) -> a -> Parser s a
130-
chainr p f a = chainr1 p f <|> return a
131-
132-
chainl :: forall s a. Parser s a -> Parser s (a -> a -> a) -> a -> Parser s a
133-
chainl p f a = chainl1 p f <|> return a
134-
135-
chainl1 :: forall s a. Parser s a -> Parser s (a -> a -> a) -> Parser s a
136-
chainl1 p f = do
137-
a <- p
138-
chainl1' p f a
139-
140-
chainl1' :: forall s a. Parser s a -> Parser s (a -> a -> a) -> a -> Parser s a
141-
chainl1' p f a = (do f' <- f
142-
a' <- p
143-
chainl1' p f (f' a a')) <|> return a
144-
145-
chainr1 :: forall s a. Parser s a -> Parser s (a -> a -> a) -> Parser s a
146-
chainr1 p f = do
147-
a <- p
148-
chainr1' p f a
149-
150-
chainr1' :: forall s a. Parser s a -> Parser s (a -> a -> a) -> a -> Parser s a
151-
chainr1' p f a = (do f' <- f
152-
a' <- chainr1 p f
153-
return $ f' a a') <|> return a
154-
155-
choice :: forall s a. [Parser s a] -> Parser s a
156-
choice [] = fail "Nothing to parse"
157-
choice [x] = x
158-
choice (x:xs) = x <|> choice xs
159-
160-
-- String Parsers
161-
162-
eof :: Parser String {}
163-
eof = Parser $ \s -> case s of
164-
"" -> successResult s false {}
165-
_ -> failureResult s false $ parseError "Expected EOF"
166-
167-
string :: String -> Parser String String
168-
string s = Parser $ \s' -> case indexOfS s' s of
169-
0 -> successResult (substring (lengthS s) (lengthS s') s') true s
170-
_ -> failureResult s' false $ parseError $ "Expected \"" ++ s ++ "\""
171-
172-
char :: Parser String String
173-
char = Parser $ \s -> case s of
174-
"" -> failureResult s false $ parseError "Unexpected EOF"
175-
_ -> successResult (substring 1 (lengthS s) s) true (substr 0 1 s)
176-
177-
-- Expressions
178-
179-
data Assoc = AssocNone | AssocLeft | AssocRight
180-
181-
data Operator s a = Infix (Parser s (a -> a -> a)) Assoc |
182-
Prefix (Parser s (a -> a)) |
183-
Postfix (Parser s (a -> a))
184-
185-
type OperatorTable s a = [[Operator s a]]
186-
187-
type SplitAccum s a = { rassoc :: [Parser s (a -> a -> a)], lassoc :: [Parser s (a -> a -> a)], nassoc :: [Parser s (a -> a -> a)], prefix :: [Parser s (a -> a)], postfix :: [Parser s (a -> a)] }
188-
189-
splitOp :: forall s a. SplitAccum s a -> Operator s a -> SplitAccum s a
190-
splitOp accum (Infix op AssocNone) = accum { nassoc = op:accum.nassoc }
191-
splitOp accum (Infix op AssocLeft) = accum { lassoc = op:accum.lassoc }
192-
splitOp accum (Infix op AssocRight) = accum { rassoc = op:accum.rassoc }
193-
splitOp accum (Prefix op) = accum { prefix = op:accum.prefix }
194-
splitOp accum (Postfix op) = accum { postfix = op:accum.postfix }
195-
196-
buildExprParser :: forall s a. OperatorTable s a -> Parser s a -> Parser s a
197-
buildExprParser operators simpleExpr =
198-
let
199-
makeParser = \term ops ->
200-
let accum = foldr splitOp { rassoc: [], lassoc: [], nassoc: [], prefix: [], postfix: [] } ops in
201-
202-
let rassocOp = choice accum.rassoc in
203-
let lassocOp = choice accum.lassoc in
204-
let nassocOp = choice accum.nassoc in
205-
let prefixOp = choice accum.prefix <?> "" in
206-
let postfixOp = choice accum.postfix <?> "" in
207-
208-
let ambigious = \assoc op -> try $ op >>= \_ -> fail ("ambiguous use of a " ++ assoc ++ " associative operator") in
209-
210-
let ambigiousRight = ambigious "right" rassocOp in
211-
let ambigiousLeft = ambigious "left" lassocOp in
212-
let ambigiousNon = ambigious "non" nassocOp in
213-
214-
let postfixP = postfixOp <|> return id in
215-
216-
let prefixP = prefixOp <|> return id in
217-
218-
let termP = do
219-
pre <- prefixP
220-
x <- term
221-
post <- postfixP
222-
return (post (pre x)) in
223-
224-
let rassocP = \x -> (do
225-
f <- rassocOp
226-
y <- do
227-
z <- termP
228-
rassocP1 z
229-
return (f x y)) <|> ambigiousLeft <|> ambigiousNon in
230-
231-
let rassocP1 = \x -> rassocP x <|> return x in
232-
233-
let lassocP = \x -> (do
234-
f <- lassocOp
235-
y <- termP
236-
lassocP1 (f x y)) <|> ambigiousRight <|> ambigiousNon in
237-
238-
let lassocP1 = \x -> lassocP x <|> return x in
239-
240-
let nassocP = \x -> do
241-
f <- nassocOp
242-
y <- termP
243-
ambigiousRight <|> ambigiousLeft <|> ambigiousNon <|> return (f x y)
24460

245-
in do
246-
x <- termP
247-
rassocP x <|> lassocP x <|> nassocP x <|> return x <?> "operator"
248-
249-
in foldl (makeParser) simpleExpr operators
25061

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
module Text.Parsing.Parser.Combinators where
2+
3+
import Prelude
4+
import Data.Maybe
5+
import Data.Array
6+
import Data.Either
7+
import Text.Parsing.Parser
8+
9+
many :: forall s a. Parser s a -> Parser s [a]
10+
many p = many1 p <|> return []
11+
12+
many1 :: forall s a. Parser s a -> Parser s [a]
13+
many1 p = do a <- p
14+
as <- many p
15+
return (a : as)
16+
17+
(<?>) :: forall s a. Parser s a -> String -> Parser s a
18+
(<?>) p msg = p <|> fail msg
19+
20+
between :: forall s a open close. Parser s open -> Parser s close -> ({} -> Parser s a) -> Parser s a
21+
between open close p = do
22+
open
23+
a <- p {}
24+
close
25+
return a
26+
27+
option :: forall s a. a -> Parser s a -> Parser s a
28+
option a p = p <|> return a
29+
30+
optional :: forall s a. Parser s a -> Parser s {}
31+
optional p = (do p
32+
return {}) <|> return {}
33+
34+
optionMaybe :: forall s a. Parser s a -> Parser s (Maybe a)
35+
optionMaybe p = option Nothing (Just <$> p)
36+
37+
try :: forall s a. Parser s a -> Parser s a
38+
try p = Parser $ \s -> case runParser p s of
39+
ParseResult ({ consumed = true, result = Left err }) -> failureResult s false err
40+
res -> res
41+
42+
sepBy :: forall s a sep. Parser s a -> Parser s sep -> Parser s [a]
43+
sepBy p sep = sepBy1 p sep <|> return []
44+
45+
sepBy1 :: forall s a sep. Parser s a -> Parser s sep -> Parser s [a]
46+
sepBy1 p sep = do
47+
a <- p
48+
as <- many $ do
49+
sep
50+
p
51+
return (a : as)
52+
53+
sepEndBy :: forall s a sep. Parser s a -> Parser s sep -> Parser s [a]
54+
sepEndBy p sep = sepEndBy1 p sep <|> return []
55+
56+
sepEndBy1 :: forall s a sep. Parser s a -> Parser s sep -> Parser s [a]
57+
sepEndBy1 p sep = do
58+
a <- p
59+
(do sep
60+
as <- sepEndBy p sep
61+
return (a : as)) <|> return [a]
62+
63+
endBy1 :: forall s a sep. Parser s a -> Parser s sep -> Parser s [a]
64+
endBy1 p sep = many1 $ do
65+
a <- p
66+
sep
67+
return a
68+
69+
endBy :: forall s a sep. Parser s a -> Parser s sep -> Parser s [a]
70+
endBy p sep = many $ do
71+
a <- p
72+
sep
73+
return a
74+
75+
chainr :: forall s a. Parser s a -> Parser s (a -> a -> a) -> a -> Parser s a
76+
chainr p f a = chainr1 p f <|> return a
77+
78+
chainl :: forall s a. Parser s a -> Parser s (a -> a -> a) -> a -> Parser s a
79+
chainl p f a = chainl1 p f <|> return a
80+
81+
chainl1 :: forall s a. Parser s a -> Parser s (a -> a -> a) -> Parser s a
82+
chainl1 p f = do
83+
a <- p
84+
chainl1' p f a
85+
86+
chainl1' :: forall s a. Parser s a -> Parser s (a -> a -> a) -> a -> Parser s a
87+
chainl1' p f a = (do f' <- f
88+
a' <- p
89+
chainl1' p f (f' a a')) <|> return a
90+
91+
chainr1 :: forall s a. Parser s a -> Parser s (a -> a -> a) -> Parser s a
92+
chainr1 p f = do
93+
a <- p
94+
chainr1' p f a
95+
96+
chainr1' :: forall s a. Parser s a -> Parser s (a -> a -> a) -> a -> Parser s a
97+
chainr1' p f a = (do f' <- f
98+
a' <- chainr1 p f
99+
return $ f' a a') <|> return a
100+
101+
choice :: forall s a. [Parser s a] -> Parser s a
102+
choice [] = fail "Nothing to parse"
103+
choice [x] = x
104+
choice (x:xs) = x <|> choice xs
105+

0 commit comments

Comments
 (0)