tools/pas2c/PascalBasics.hs
author Wuzzy <Wuzzy2@mail.ru>
Thu, 26 Oct 2017 22:49:39 +0200
changeset 12784 1f8a62d1609d
parent 10120 b7f632c12784
permissions -rw-r--r--
ACF5: Fix final animation being stuck when the cyborg's way to the right is blocked Fixed with the new maxMoveTime parameter in AnimMove. If cyborg didn't reach its destination in 7000ms, the move anim is skipped and the sequence just continues.

{-# LANGUAGE FlexibleContexts, NoMonomorphismRestriction #-}
module PascalBasics where

import Text.Parsec.Combinator
import Text.Parsec.Char
import Text.Parsec.Prim
import Text.Parsec.Token
import Text.Parsec.Language
import Data.Char
import Control.Monad
import Data.Functor.Identity

char' :: Char -> Parsec String u ()
char' = void . char

string' :: String -> Parsec String u ()
string' = void . string

builtin :: [String]
builtin = ["succ", "pred", "low", "high", "ord", "inc", "dec", "exit", "break", "continue", "length", "copy"]

pascalLanguageDef :: GenLanguageDef String u Identity
pascalLanguageDef
    = emptyDef
    { commentStart   = "(*"
    , commentEnd     = "*)"
    , commentLine    = "//"
    , nestedComments = False
    , identStart     = letter <|> oneOf "_"
    , identLetter    = alphaNum <|> oneOf "_"
    , opLetter       = letter
    , reservedNames  = [
            "begin", "end", "program", "unit", "interface"
            , "implementation", "and", "or", "xor", "shl"
            , "shr", "while", "do", "repeat", "until", "case", "of"
            , "type", "var", "const", "out", "array", "packed"
            , "procedure", "function", "with", "for", "to"
            , "downto", "div", "mod", "record", "set", "nil"
            , "cdecl", "external", "if", "then", "else"
            ] -- ++ builtin
    , caseSensitive  = False
    }

preprocessorSwitch :: Stream String Identity Char => Parsec String u String
preprocessorSwitch = do
    try $ string' "{$"
    s <- manyTill (noneOf "\n") $ char '}'
    return s

caseInsensitiveString :: Stream String Identity Char => String -> Parsec String u String
caseInsensitiveString s = do
    mapM_ (\a -> satisfy (\b -> toUpper a == toUpper b)) s <?> s
    return s

pas :: GenTokenParser String u Identity
pas = patch $ makeTokenParser pascalLanguageDef
    where
    patch tp = tp {stringLiteral = stringL}

comment :: Stream String Identity Char => Parsec String u String
comment = choice [
        char '{' >> notFollowedBy (char '$') >> manyTill anyChar (try $ char '}')
        , (try $ string "(*") >> manyTill anyChar (try $ string "*)")
        , (try $ string "//") >> manyTill anyChar (try newline)
        ]

comments :: Parsec String u ()
comments = do
    spaces
    skipMany $ do
        void $ preprocessorSwitch <|> comment
        spaces

stringL :: Parsec String u String
stringL = do
    char' '\''
    s <- (many $ noneOf "'")
    char' '\''
    ss <- many $ do
        char' '\''
        s' <- (many $ noneOf "'")
        char' '\''
        return $ '\'' : s'
    comments
    return $ concat (s:ss)