tools/PascalPreprocessor.hs
author nemo
Tue, 06 Nov 2012 08:38:37 -0500
changeset 7980 7f8df51553a7
parent 7762 d2fd8040534f
child 7957 497ec84e0c21
child 8138 cfb228baa598
permissions -rw-r--r--
Remove duplicate files from voices (add a fallback check in uSound). Add JustYouWait as an alternate to IllGetYou. Note that IllGetYou being called every turn seems awkward. IMO they probably should be reserved for significant enemy action. Maybe played by team of heavily damaged or killed hog.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
6412
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
     1
module PascalPreprocessor where
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
     2
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
     3
import Text.Parsec
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
     4
import Control.Monad.IO.Class
6414
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
     5
import Control.Monad
6412
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
     6
import System.IO
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
     7
import qualified Data.Map as Map
6414
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
     8
import Data.Char
6412
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
     9
6413
6714531e7bd2 Preprocessor strips comments
unc0rr
parents: 6412
diff changeset
    10
6714531e7bd2 Preprocessor strips comments
unc0rr
parents: 6412
diff changeset
    11
-- comments are removed
6714531e7bd2 Preprocessor strips comments
unc0rr
parents: 6412
diff changeset
    12
comment = choice [
6714531e7bd2 Preprocessor strips comments
unc0rr
parents: 6412
diff changeset
    13
        char '{' >> notFollowedBy (char '$') >> manyTill anyChar (try $ char '}') >> return ""
6714531e7bd2 Preprocessor strips comments
unc0rr
parents: 6412
diff changeset
    14
        , (try $ string "(*") >> manyTill anyChar (try $ string "*)") >> return ""
6714531e7bd2 Preprocessor strips comments
unc0rr
parents: 6412
diff changeset
    15
        , (try $ string "//") >> manyTill anyChar (try newline) >> return "\n"
6714531e7bd2 Preprocessor strips comments
unc0rr
parents: 6412
diff changeset
    16
        ]
6714531e7bd2 Preprocessor strips comments
unc0rr
parents: 6412
diff changeset
    17
7038
d853e4385241 Some more definitions and slight fixes
unc0rr
parents: 6964
diff changeset
    18
initDefines = Map.fromList [
d853e4385241 Some more definitions and slight fixes
unc0rr
parents: 6964
diff changeset
    19
    ("FPC", "")
d853e4385241 Some more definitions and slight fixes
unc0rr
parents: 6964
diff changeset
    20
    , ("PAS2C", "")
7429
fcf13e40d6b6 Changes to pas2c - unreviewed apart from cursory glance and compile test.
xymeng
parents: 7315
diff changeset
    21
    , ("ENDIAN_LITTLE", "")
fcf13e40d6b6 Changes to pas2c - unreviewed apart from cursory glance and compile test.
xymeng
parents: 7315
diff changeset
    22
    , ("S3D_DISABLED", "")
7038
d853e4385241 Some more definitions and slight fixes
unc0rr
parents: 6964
diff changeset
    23
    ]
7315
59b5b19e6604 Remove trailing spaces
unc0rr
parents: 7067
diff changeset
    24
6412
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    25
preprocess :: String -> IO String
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    26
preprocess fn = do
6425
1ef4192aa80d - Parse unions, sets, function type, packed arrays and some more imporvements to the parser. Now it parses uVariable, uConsts and even SDLh.pas
unc0rr
parents: 6414
diff changeset
    27
    r <- runParserT (preprocessFile fn) (initDefines, [True]) "" ""
6412
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    28
    case r of
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    29
         (Left a) -> do
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    30
             hPutStrLn stderr (show a)
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    31
             return ""
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    32
         (Right a) -> return a
7315
59b5b19e6604 Remove trailing spaces
unc0rr
parents: 7067
diff changeset
    33
6412
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    34
    where
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    35
    preprocessFile fn = do
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    36
        f <- liftIO (readFile fn)
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    37
        setInput f
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    38
        preprocessor
7315
59b5b19e6604 Remove trailing spaces
unc0rr
parents: 7067
diff changeset
    39
6414
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    40
    preprocessor, codeBlock, switch :: ParsecT String (Map.Map String String, [Bool]) IO String
7315
59b5b19e6604 Remove trailing spaces
unc0rr
parents: 7067
diff changeset
    41
6414
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    42
    preprocessor = chainr codeBlock (return (++)) ""
7315
59b5b19e6604 Remove trailing spaces
unc0rr
parents: 7067
diff changeset
    43
6414
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    44
    codeBlock = do
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    45
        s <- choice [
6412
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    46
            switch
6413
6714531e7bd2 Preprocessor strips comments
unc0rr
parents: 6412
diff changeset
    47
            , comment
6414
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    48
            , char '\'' >> many (noneOf "'\n") >>= \s -> char '\'' >> return ('\'' : s ++ "'")
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    49
            , identifier >>= replace
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    50
            , noneOf "{" >>= \a -> return [a]
6412
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    51
            ]
6414
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    52
        (_, ok) <- getState
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    53
        return $ if and ok then s else ""
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    54
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    55
    --otherChar c = c `notElem` "{/('_" && not (isAlphaNum c)
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    56
    identifier = do
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    57
        c <- letter <|> oneOf "_"
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    58
        s <- many (alphaNum <|> oneOf "_")
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    59
        return $ c:s
7315
59b5b19e6604 Remove trailing spaces
unc0rr
parents: 7067
diff changeset
    60
6412
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    61
    switch = do
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    62
        try $ string "{$"
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    63
        s <- choice [
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    64
            include
6414
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    65
            , ifdef
6453
11c578d30bd3 Countless imporvements to the parser and countless help to the parser in sources.
unc0rr
parents: 6425
diff changeset
    66
            , if'
6414
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    67
            , elseSwitch
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    68
            , endIf
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    69
            , define
6412
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    70
            , unknown
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    71
            ]
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    72
        return s
7315
59b5b19e6604 Remove trailing spaces
unc0rr
parents: 7067
diff changeset
    73
6412
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    74
    include = do
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    75
        try $ string "INCLUDE"
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    76
        spaces
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    77
        (char '"')
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    78
        fn <- many1 $ noneOf "\"\n"
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    79
        char '"'
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    80
        spaces
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    81
        char '}'
6964
6dde80ae7049 Raise exception when .inc file isn't found
unc0rr
parents: 6891
diff changeset
    82
        f <- liftIO (readFile fn `catch` error ("File not found: " ++ fn))
6412
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    83
        c <- getInput
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    84
        setInput $ f ++ c
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    85
        return ""
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
    86
6414
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    87
    ifdef = do
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    88
        s <- try (string "IFDEF") <|> try (string "IFNDEF")
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    89
        let f = if s == "IFNDEF" then not else id
7315
59b5b19e6604 Remove trailing spaces
unc0rr
parents: 7067
diff changeset
    90
6414
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    91
        spaces
6425
1ef4192aa80d - Parse unions, sets, function type, packed arrays and some more imporvements to the parser. Now it parses uVariable, uConsts and even SDLh.pas
unc0rr
parents: 6414
diff changeset
    92
        d <- identifier
6414
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    93
        spaces
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    94
        char '}'
7315
59b5b19e6604 Remove trailing spaces
unc0rr
parents: 7067
diff changeset
    95
6414
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    96
        updateState $ \(m, b) ->
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    97
            (m, (f $ d `Map.member` m) : b)
7315
59b5b19e6604 Remove trailing spaces
unc0rr
parents: 7067
diff changeset
    98
6414
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
    99
        return ""
6453
11c578d30bd3 Countless imporvements to the parser and countless help to the parser in sources.
unc0rr
parents: 6425
diff changeset
   100
11c578d30bd3 Countless imporvements to the parser and countless help to the parser in sources.
unc0rr
parents: 6425
diff changeset
   101
    if' = do
11c578d30bd3 Countless imporvements to the parser and countless help to the parser in sources.
unc0rr
parents: 6425
diff changeset
   102
        s <- try (string "IF" >> notFollowedBy alphaNum)
7315
59b5b19e6604 Remove trailing spaces
unc0rr
parents: 7067
diff changeset
   103
6453
11c578d30bd3 Countless imporvements to the parser and countless help to the parser in sources.
unc0rr
parents: 6425
diff changeset
   104
        manyTill anyChar (char '}')
11c578d30bd3 Countless imporvements to the parser and countless help to the parser in sources.
unc0rr
parents: 6425
diff changeset
   105
        --char '}'
7315
59b5b19e6604 Remove trailing spaces
unc0rr
parents: 7067
diff changeset
   106
6453
11c578d30bd3 Countless imporvements to the parser and countless help to the parser in sources.
unc0rr
parents: 6425
diff changeset
   107
        updateState $ \(m, b) ->
11c578d30bd3 Countless imporvements to the parser and countless help to the parser in sources.
unc0rr
parents: 6425
diff changeset
   108
            (m, False : b)
7315
59b5b19e6604 Remove trailing spaces
unc0rr
parents: 7067
diff changeset
   109
6453
11c578d30bd3 Countless imporvements to the parser and countless help to the parser in sources.
unc0rr
parents: 6425
diff changeset
   110
        return ""
11c578d30bd3 Countless imporvements to the parser and countless help to the parser in sources.
unc0rr
parents: 6425
diff changeset
   111
6414
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
   112
    elseSwitch = do
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
   113
        try $ string "ELSE}"
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
   114
        updateState $ \(m, b:bs) -> (m, (not b):bs)
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
   115
        return ""
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
   116
    endIf = do
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
   117
        try $ string "ENDIF}"
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
   118
        updateState $ \(m, b:bs) -> (m, bs)
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
   119
        return ""
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
   120
    define = do
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
   121
        try $ string "DEFINE"
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
   122
        spaces
7315
59b5b19e6604 Remove trailing spaces
unc0rr
parents: 7067
diff changeset
   123
        i <- identifier
7762
d2fd8040534f Better error handling
unc0rr
parents: 7429
diff changeset
   124
        d <- ((string ":=" >> return ()) <|> spaces) >> many (noneOf "}")
6414
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
   125
        char '}'
7067
f98ec3aecf4e A solution to char vs string problem: mark single-letter strings with _S macro
unc0rr
parents: 7059
diff changeset
   126
        updateState $ \(m, b) -> (if (and b) && (head i /= '_') then Map.insert i d m else m, b)
6414
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
   127
        return ""
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
   128
    replace s = do
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
   129
        (m, _) <- getState
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
   130
        return $ Map.findWithDefault s s m
7315
59b5b19e6604 Remove trailing spaces
unc0rr
parents: 7067
diff changeset
   131
6412
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
   132
    unknown = do
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
   133
        fn <- many1 $ noneOf "}\n"
4b9a59116535 - Split PascalParser into modules
unc0rr
parents:
diff changeset
   134
        char '}'
6414
8474b7fa84d6 Finish preprocessor. Now it correctly handles $IFDEF, $IFNDEF, $ELSE, $ENDIF and $DEFINE.
unc0rr
parents: 6413
diff changeset
   135
        return $ "{$" ++ fn ++ "}"