antlrc-0.0.1: src/Text/Antlrc/Lexer.chs
-- Copyright (c)2010-2011, Mark Wright. All rights reserved.
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE TypeSynonymInstances #-}
module Text.Antlrc.Lexer where
#include "antlr3lexer.h"
import C2HS
import Foreign.C.Types
import Foreign.Storable
import Ptr
import Foreign.Ptr
import System.IO.Unsafe
import Foreign.C
import Control.Monad
import Control.Applicative ((<$>))
{#context lib="antlr3c"#}
-- | Lexer token struct.
{#pointer *ANTLR3_COMMON_TOKEN as CommonToken newtype#}
-- | Lexer input stream struct.
{#pointer *ANTLR3_INPUT_STREAM as InputStream newtype#}
-- | Lexer struct.
{#pointer *ANTLR3_LEXER as Lexer newtype#}
-- | Cast from a pointer to an input stream to an input stream.
toInputStream :: Ptr InputStream -> InputStream
toInputStream = InputStream . castPtr
-- | Cast from a pointer to a token to a token.
toCommonToken :: Ptr CommonToken -> CommonToken
toCommonToken = CommonToken . castPtr
-- | Cast from a token to a pointer to a token.
fromCommonToken :: CommonToken -> Ptr b
fromCommonToken (CommonToken x) = castPtr x
-- The C function definitions are in lexerc.c
#c
ANTLR3_COMMON_TOKEN *LT(ANTLR3_INPUT_STREAM *input, int lti);
#endc
-- | Lookahead in the input stream at the token at the specified
-- positive offset, where:
--
-- > LT input 1
--
-- is the current token. Or a negative offset may be specified, where:
--
-- > LT input (-1)
--
-- is the previous token.
--
-- > foreign export ccall isUnsignedInt :: Ptr InputStream -> IO Bool
-- > isUnsignedInt input =
-- > do token1 <- lT input 1 >>= tokenGetType
-- > if token1 /= UNSIGNED
-- > then return False
-- > else
-- > do
-- > token2 <- lT input 2 >>= tokenGetType
-- > return ((token2 /= CHAR) && (token2 /= SHORT) && (token2 /= LONG))
--
{#fun LT as lT
{ toInputStream `Ptr (InputStream)',
`Int' } -> `Ptr (CommonToken)' fromCommonToken#}
-- | Pointer to an ANTLR string.
{#pointer *ANTLR3_STRING as AntlrString newtype#}
-- | Cast from an ANTLR string to a pointer to an ANTLR string.
fromAntlrString :: AntlrString -> Ptr b
fromAntlrString (AntlrString x) = castPtr x
#c
ANTLR3_STRING *tokenGetAntlrString(ANTLR3_COMMON_TOKEN *token);
#endc
-- | Obtain the token name ANTLR string for the specified token.
--
-- > tokenGetAntlrString token
--
-- For identifier tokens, the token string is interesting. For
-- other tokens such as operator tokens, the token string is
-- uninteresting, and may not be present, the token identifier enum
-- should be used instead.
{#fun tokenGetAntlrString
{ toCommonToken `Ptr (CommonToken)' } -> `Ptr (AntlrString)' fromAntlrString#}
-- | Convert an ANTLR string to a Maybe String.
fromAntlrStringToMaybeString :: AntlrString -> IO (Maybe String)
fromAntlrStringToMaybeString (AntlrString x) =
if x == Ptr.nullPtr
then return Nothing
else
{#get ANTLR3_STRING->chars#} x >>= \c ->
{#get ANTLR3_STRING->len#} x >>= \l ->
peekCStringLen ((castPtr c), (fromIntegral l)) >>= \s ->
return (Just s)
-- | Obtain the token Maybe String for the specified token.
-- For identifier tokens, the token string is interesting. For
-- other tokens such as operator tokens, the token string is
-- uninteresting, and may not be present, the token identifier enum
-- should be used instead.
tokenGetTextMaybe :: Ptr (CommonToken) -> IO (Maybe String)
tokenGetTextMaybe c =
tokenGetAntlrString c >>= \s ->
fromAntlrStringToMaybeString (AntlrString s)
-- | Convert from an ANTLR string to a String.
-- Note: the peekCStringLen function does not say what will happen if the
-- C pointer is 0.
fromAntlrStringToString :: AntlrString -> IO String
fromAntlrStringToString (AntlrString x) =
{#get ANTLR3_STRING->chars#} x >>= \c ->
{#get ANTLR3_STRING->len#} x >>= \l ->
peekCStringLen ((castPtr c), (fromIntegral l)) >>= \s ->
return s
-- | Obtain the token String for the specified token.
-- Note: the peekCStringLen function does not say what will happen if the
-- C pointer is 0.
--
-- > foreign export ccall saIntV :: Ptr CommonToken -> IO (StablePtr TermInfo)
-- > saIntV token =
-- > do
-- > -- read the IntV integer value from the token text into n
-- > t <- tokenGetText token
-- > n <- readIO t
-- > -- obtain the source code line and charPosition from the token
-- > l <- tokenGetLine token
-- > c <- tokenGetCharPositionInLine token
-- > -- return the term, which is TmZero, or TmSucc TmZero, or TmSucc (TmSucc (...TmSucc TmZero))
-- > newStablePtr (intV (Info l c) n)
--
tokenGetText :: Ptr (CommonToken) -> IO String
tokenGetText c =
tokenGetAntlrString c >>= \s ->
fromAntlrStringToString (AntlrString s)
-- | Obtain the token identifier for the specified token.
--
-- > foreign export ccall isInt :: Ptr InputStream -> IO Bool
-- > isInt input =
-- > do
-- > token1 <- lT input 1 >>= tokenGetType
-- > return (token1 == INT)
--
tokenGetType :: (Enum e) => Ptr (CommonToken) -> IO e
tokenGetType token = {#get ANTLR3_COMMON_TOKEN->type#} token >>= return . cToEnum
-- | Obtain the character position in the source code line of where the token
-- was read, for non-imaginary tokens.
--
-- > foreign export ccall saTrue :: Ptr CommonToken -> IO (StablePtr TermInfo)
-- > saTrue token =
-- > do
-- > -- obtain the source code line and charPosition from the token
-- > l <- tokenGetLine token
-- > c <- tokenGetCharPositionInLine token
-- > -- return the TmTrue term
-- > newStablePtr (TmTrue (Info l c))
--
tokenGetCharPositionInLine :: Ptr (CommonToken) -> IO Int
tokenGetCharPositionInLine token = {#get ANTLR3_COMMON_TOKEN->charPosition#} token >>= return . cIntConv
-- | Obtain the the source code line of where the token was read, for non-imaginary tokens.
--
-- > foreign export ccall saFalse :: Ptr CommonToken -> IO (StablePtr TermInfo)
-- > saFalse token =
-- > do
-- > -- obtain the source code line and charPosition from the token
-- > l <- tokenGetLine token
-- > c <- tokenGetCharPositionInLine token
-- > -- return the TmFalse term
-- > newStablePtr (TmFalse (Info l c))
--
tokenGetLine :: Ptr (CommonToken) -> IO Int
tokenGetLine token = {#get ANTLR3_COMMON_TOKEN->line#} token >>= return . cIntConv