-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathCPreProcess.hs
More file actions
148 lines (117 loc) · 4.06 KB
/
Copy pathCPreProcess.hs
File metadata and controls
148 lines (117 loc) · 4.06 KB
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
module CPreProcess(preProcessFile) where
import Array
import IO
import Monad
import CPPLex
preProcessFile s x = do fh <- openFile x ReadMode
c <- hGetContents fh
ppLineStart s c
ppLineStart s i | tok == (PPpunctuator "#") = ppDirective s rest
| otherwise = ppMacroExpand s (tok,rest)
where (tok,rest) = cppLex i
ppDirective s i
| tok == (PPidentifier "include") = ppInclude s rest
| tok == (PPidentifier "define") = ppDefine s rest
| tok == (PPidentifier "pragma") = ppPragma s i
| tok == (PPidentifier "ifdef") = ppIfdef s i
| tok == (PPidentifier "ifndef") = ppIfndef s i
| tok == (PPidentifier "if") = ppIf s i
| otherwise = do x <- ppMacroExpand s (tok,rest)
return (PPpunctuator "#":x)
where (tok,rest) = cppLex i
ppMacroExpand s (tok,[]) = return (tok:[])
ppMacroExpand s (tok,rest)
| tok == PPnewline = do x <- ppLineStart s rest
return (PPnewline:x)
| isFMacro tok = ppExpandFIdentifier s (tok,rest)
| isMacro tok = ppExpandIdentifier s (tok,rest)
| otherwise = do y <- ppMacroExpand s (tok',rest')
return (tok:y)
where (tok',rest') = cppLex rest
isMacro (PPidentifier t) = getMacro s (NoArg t) /= Nothing
isMacro _ = False
isFMacro _ = False
ppExpandIdentifier s (PPidentifier tok,rest)
= do y <- ppMacroExpand s (tok',rest')
return (toks++y)
where (tok',rest') = cppLex rest
(Just macEx) = getMacro s (NoArg tok)
toks = macroReplace macEx [] -- (getParen (tok',rest'))
{-
ppExpandFIdentifier s t@(PPidentifier tok, rest)
| length parenExpr == 0 = ppExpandIdentifer s t
| otherwise = do y <- ppMacroExpand s (tok'',rest'')
return (toks++y)
where (tok',rest') = cppLex rest
parenExpr = getParenExpr s (tok',rest')
-}
ppExpandFIdentifier = f 0 []
where f _ _ = ppExpandIdentifier
{- XXX XAX elric: this is borked!
ppExpandFIdentifier = f 0 []
where f 0 s (PPpunctuator ")", rest) = do y <- ppMacroExpand s (tok',rest')
return (toks++y)
(tok',rest') = cppLex rest
(Just macEx) = getMacro s (NoArg tok)
toks = macroReplace macEx []
-}
ppInclude s i = do x <- preProcessFile s incFile
y <- ppLineStart s rest
return (x ++ y)
where (PPheadername _ incFile,rest) = ppIncludeParse i
ppIncludeParse i | (length inc) == 1 = head inc
| otherwise = error "failed to parse include"
where tmp = takeWhile ((/=PPnewline).fst) (thread cppLexHeader i)
inc = getHName tmp
getHName = filter (isPPheadername . fst)
isPPheadername (PPheadername _ _) = True
isPPheadername _ = False
ppPragma s i = ppMacroExpand s (PPpunctuator "#", i)
ppIfdef s i = ppMacroExpand s (PPpunctuator "#", i)
ppIfndef s i = ppMacroExpand s (PPpunctuator "#", i)
ppIf s i = ppMacroExpand s (PPpunctuator "#", i)
ppDefine s i = ppLineStart news rest
where (news,rest) = pMacro s i
{-
Okay, let's do the silly replacement code. This will obviously
have to be rewritten... We will store the macros as a list of
key-value pairs. So, here we index in a `Macro' to a `MacroExpansion'.
The Macro represents the only unique macro definitions.
-}
pMacro s i = (defnM toks:s, rest)
where tmp = takeWhile ((/=PPnewline).fst) (thread cppLex i)
toks = map fst tmp
rest = snd $ last tmp
defnM i = (NoArg ident, ME 0 (map Right rlist))
where tmp = dropWhile ppIsSpace i
ident' = head tmp
rlist = dropWhile ppIsSpace (tail tmp)
(PPidentifier ident) = ident'
ppIsIdentifier (PPidentifier _) = True
ppIsIdentifier _ = False
ppIsSpace (PPspace _) = True
ppIsSpace _ = False
data Macro = NoArg String
| Args String
deriving (Eq, Show)
data MacroExpansion = ME Int [Either Int PPTokenT]
deriving (Eq, Show)
getMacro s macro = lookup macro s
putMacro s macro expansion = (macro,expansion):s
macroReplace (ME x toks) args = do tok <- toks
return (replace tok args)
replace (Left x) args = (args++repeat (PPspace " ")) !! x
replace (Right x) _ = x
{-
what we want is:
(toks,rest) = cppLex s
(toks',rest') = cppLex rest
(toks'',rest'') = cppLex rest'
.
.
.
so, let's see...
-}
thread :: (s->(a,s)) -> s -> [(a,s)]
thread f s = (one,two):thread f two
where (one,two) = f s