summaryrefslogtreecommitdiff
path: root/src/GF/Data/Parsers.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/GF/Data/Parsers.hs')
-rw-r--r--src/GF/Data/Parsers.hs143
1 files changed, 143 insertions, 0 deletions
diff --git a/src/GF/Data/Parsers.hs b/src/GF/Data/Parsers.hs
new file mode 100644
index 000000000..165d0f4e7
--- /dev/null
+++ b/src/GF/Data/Parsers.hs
@@ -0,0 +1,143 @@
+module Parsers where
+
+import Operations
+import Char
+
+
+infixr 2 |||, +||
+infixr 3 ***
+infixr 5 .>.
+infixr 5 ...
+infixr 5 ....
+infixr 5 +..
+infixr 5 ..+
+infixr 6 |>
+infixr 3 <<<
+
+-- some parser combinators a` la Wadler and Hutton
+-- no longer used in many places in GF
+
+type Parser a b = [a] -> [(b,[a])]
+
+parseResults :: Parser a b -> [a] -> [b]
+parseResults p s = [x | (x,r) <- p s, null r]
+
+parseResultErr :: Parser a b -> [a] -> Err b
+parseResultErr p s = case parseResults p s of
+ [x] -> return x
+ [] -> Bad "no parse"
+ _ -> Bad "ambiguous"
+
+(...) :: Parser a b -> Parser a c -> Parser a (b,c)
+(p ... q) s = [((x,y),r) | (x,t) <- p s, (y,r) <- q t]
+
+(.>.) :: Parser a b -> (b -> Parser a c) -> Parser a c
+(p .>. f) s = [(c,r) | (x,t) <- p s, (c,r) <- f x t]
+
+(|||) :: Parser a b -> Parser a b -> Parser a b
+(p ||| q) s = p s ++ q s
+
+(+||) :: Parser a b -> Parser a b -> Parser a b
+p1 +|| p2 = take 1 . (p1 ||| p2)
+
+literal :: (Eq a) => a -> Parser a a
+literal x (c:cs) = [(x,cs) | x == c]
+literal _ _ = []
+
+(***) :: Parser a b -> (b -> c) -> Parser a c
+(p *** f) s = [(f x,r) | (x,r) <- p s]
+
+succeed :: b -> Parser a b
+succeed v s = [(v,s)]
+
+fails :: Parser a b
+fails s = []
+
+(+..) :: Parser a b -> Parser a c -> Parser a c
+p1 +.. p2 = p1 ... p2 *** snd
+
+(..+) :: Parser a b -> Parser a c -> Parser a b
+p1 ..+ p2 = p1 ... p2 *** fst
+
+(<<<) :: Parser a b -> c -> Parser a c -- return
+p <<< v = p *** (\x -> v)
+
+(|>) :: Parser a b -> (b -> Bool) -> Parser a b
+p |> b = p .>. (\x -> if b x then succeed x else fails)
+
+many :: Parser a b -> Parser a [b]
+many p = (p ... many p *** uncurry (:)) +|| succeed []
+
+some :: Parser a b -> Parser a [b]
+some p = (p ... many p) *** uncurry (:)
+
+longestOfMany :: Parser a b -> Parser a [b]
+longestOfMany p = p .>. (\x -> longestOfMany p *** (x:)) +|| succeed []
+
+closure :: (b -> Parser a b) -> (b -> Parser a b)
+closure p v = p v .>. closure p ||| succeed v
+
+pJunk :: Parser Char String
+pJunk = longestOfMany (satisfy (\x -> elem x "\n\t "))
+
+pJ :: Parser Char a -> Parser Char a
+pJ p = pJunk +.. p ..+ pJunk
+
+pTList :: String -> Parser Char a -> Parser Char [a]
+pTList t p = p .... many (jL t +.. p) *** (\ (x,y) -> x:y) -- mod. AR 5/1/1999
+
+pTJList :: String -> String -> Parser Char a -> Parser Char [a]
+pTJList t1 t2 p = p .... many (literals t1 +.. jL t2 +.. p) *** (uncurry (:))
+
+pElem :: [String] -> Parser Char String
+pElem l = foldr (+||) fails (map literals l)
+
+(....) :: Parser Char b -> Parser Char c -> Parser Char (b,c)
+p1 .... p2 = p1 ... pJunk +.. p2
+
+item :: Parser a a
+item (c:cs) = [(c,cs)]
+item [] = []
+
+satisfy :: (a -> Bool) -> Parser a a
+satisfy b = item |> b
+
+literals :: (Eq a,Show a) => [a] -> Parser a [a]
+literals l = case l of
+ [] -> succeed []
+ a:l -> literal a ... literals l *** (\ (x,y) -> x:y)
+
+lits :: (Eq a,Show a) => [a] -> Parser a [a]
+lits ts = literals ts
+
+jL :: String -> Parser Char String
+jL = pJ . lits
+
+pParenth p = literal '(' +.. pJunk +.. p ..+ pJunk ..+ literal ')'
+pCommaList p = pTList "," (pJ p) -- p,...,p
+pOptCommaList p = pCommaList p ||| succeed [] -- the same or nothing
+pArgList p = pParenth (pCommaList p) ||| succeed [] -- (p,...,p), poss. empty
+pArgList2 p = pParenth (p ... jL "," +.. pCommaList p) *** uncurry (:) -- min.2 args
+
+longestOfSome p = (p ... longestOfMany p) *** (\ (x,y) -> x:y)
+
+pIdent = pLetter ... longestOfMany pAlphaPlusChar *** uncurry (:)
+ where alphaPlusChar c = isAlphaNum c || c=='_' || c=='\''
+
+pLetter = satisfy (`elem` (['A'..'Z'] ++ ['a'..'z'] ++
+ ['À' .. 'Û'] ++ ['à' .. 'û'])) -- no such in Char
+pDigit = satisfy isDigit
+pLetters = longestOfSome pLetter
+pAlphanum = pDigit ||| pLetter
+pAlphaPlusChar = pAlphanum ||| satisfy (`elem` "_'")
+
+pQuotedString = literal '"' +.. pEndQuoted where
+ pEndQuoted =
+ literal '"' *** (const [])
+ +|| (literal '\\' +.. item .>. \ c -> pEndQuoted *** (c:))
+ +|| item .>. \ c -> pEndQuoted *** (c:)
+
+pIntc :: Parser Char Int
+pIntc = some (satisfy numb) *** read
+ where numb x = elem x ['0'..'9']
+