-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathAuthor.hs
104 lines (75 loc) · 2.79 KB
/
Author.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
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
module Main where
import System( getArgs )
import Char
import IO (readFile)
import List (nubBy, partition, intersperse)
import Funeral.ParseLib
data Exp = App Id Exp
| Num Integer -- 1
| Str String -- "string" or 'string' or `string`
| Att Id Exp -- key=value
| Lis [Exp] -- [ e1 e2 e3 ]
| Com String -- -- comment
instance Show Exp where
show (App id e) = id ++ " {" ++ show e ++ "}"
show (Num n) = show n
show (Str s) = show s
show (Att id e) = id ++ "=" ++ show e
show (Lis es) = concat ( intersperse ";" (map show es) )
show (Com s) = show $ "<!-- " ++ s ++ " -->"
type Id = String
symbol :: Parser Char
symbol = satisfy (`elem` "!%&|*+-/:<>?@^_~.#")
digit :: Parser Char
digit = satisfy isDigit
letter :: Parser Char
letter = satisfy isAlpha
padding :: Parser Char
padding = satisfy (`elem` "\n\r \t")
token :: Parser a -> Parser a
token p = p <| ignoredChars
where
ignoredChars = maybeSome $ satisfy (`elem` " \t;,")
keyword :: String -> Parser String
keyword = token . string
parseId :: Parser String
parseId = token $ pure (:) <*> (symbol <|> letter) <*> maybeSome (symbol <|> digit <|> letter)
parsePad :: Parser Exp
parsePad = token $ pure Str <*> atLeastOne padding
parseStr :: Parser Exp
parseStr = pure Str <*> s
where
s = token ( char '`' |> maybeSome ( satisfy (/= '`') ) <| char '`' )
<|> token ( char '"' |> maybeSome ( satisfy (/= '"') ) <| char '"' )
<|> token ( char '\'' |> maybeSome ( satisfy (/= '\'') ) <| char '\'' )
parseNum :: Parser Exp
parseNum = pure Num <*> n
where
n = token $ pure (read) <*> atLeastOne digit
parseApp :: Parser Exp
parseApp = pure App <*> parseId <| maybeSome parsePad <*> parseExpr
parseList :: Parser Exp
parseList = pure Lis <*> keyword "[" |> maybeSome parseExpr <| keyword "]"
parseAtt :: Parser Exp
parseAtt = pure Att <*> parseId <| keyword "=" <*> parseExpr -- <| maybeSome parsePad
--parseRef :: Parser Exp
--parseRef = pure Ref <*> string "$" |> ( parseId <|> keyword "0" <|> keyword "1" )
parseComment :: Parser Exp
parseComment = token $ pure Com <*> keyword "--" |> ( maybeSome $ anyCharExcept "\n\r" ) <| ( maybeSome $ satisfy (`elem` "\n\r") )
parseExpr :: Parser Exp
parseExpr = parseComment <|> parsePad <|> parseApp <|> parseStr <|> parseNum <|> parseAtt <|> parseList
parse :: String -> Exp
parse s = case junk of
"" -> Lis exps
otherwise -> error ("Parse error in '" ++ take 30 junk ++ "...'\n")
where
(junk, exps) = head $ maybeSome parseExpr s
main :: IO ()
main = do
args <- getArgs
sources <- mapM readFile args
let tree = parse $ concat sources
-- let lib = buildLibrary tree
-- let tree' = stripDefs tree
putStrLn "require 'author.formlib'\n"
putStrLn $ show tree