packages feed

happy-arbitrary-0.0.1: src/Language/Happy/Lexer.x

{
{-# LANGUAGE DeriveFunctor      #-}
{-# LANGUAGE DeriveGeneric      #-}
{-# LANGUAGE DeriveTraversable  #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE StrictData         #-}
{-# OPTIONS_GHC -Wno-unused-imports #-}
module Language.Happy.Lexer
    ( Alex
    , AlexPosn (..)
    , alexError
    , alexScanTokens
    , alexMonadScan
    , Lexeme (..)
    , lexemeClass
    , lexemePosn
    , lexemeText
    , lexemeLine
    , runAlex
    ) where

import           Data.Aeson            (FromJSON, ToJSON)
import qualified Data.ByteString       as BS
import qualified Data.ByteString.Lazy  as LBS
import           Data.Text             (Text)
import qualified Data.Text             as Text
import qualified Data.Text.Encoding    as Text
import           GHC.Generics          (Generic)
import           Language.Happy.Tokens (LexemeClass (..))
}

%wrapper "monad-bytestring"

tokens :-
<0>		"{"					{ begin hs }

<hs>		[^\{\}]+				{ mkL LitCode }
<hs>		"}"					{ begin 0 }
<hs>		"{-"					{ begin hsCmt }
<hsCmt>		"-}"					{ begin hs }
<hs,hsCmt>	(.|\n)					;

<0>		"%errorhandlertype"			{ mkL KwErrorhandlertype }
<0>		"%error"				{ mkL KwError }
<0>		"%expect"				{ mkL KwExpect }
<0>		"%left"					{ mkL KwLeft }
<0>		"%lexer"				{ mkL KwLexer }
<0>		"%monad"				{ mkL KwMonad }
<0>		"%name"					{ mkL KwName }
<0>		"%right"				{ mkL KwRight }
<0>		"%token"				{ mkL KwToken }
<0>		"%tokentype"				{ mkL KwTokentype }

<0>		"%%"					{ mkL PctPercentPercent }
<0>		"::"					{ mkL PctColonColon }
<0>		":"					{ mkL PctColon }
<0>		"|"					{ mkL PctPipe }

<0>		"--"\n					;
<0>		"-- ".*					;
<0>		[\ \t\n]+				;
<0>		$white					{ mkE ErrorToken }
<0>		'(\\|[^'])*'				{ mkL LitString }
<0>		[A-Za-z][A-Za-z0-9_]*			{ mkL IdName }
<0>		[0-9]+					{ mkL LitInteger }

-- Error handling.
<0>		.					{ mkL ErrorToken }

{
deriving instance Generic AlexPosn
instance FromJSON AlexPosn
instance ToJSON AlexPosn

data Lexeme text = L AlexPosn LexemeClass text
    deriving (Eq, Show, Generic, Functor, Foldable, Traversable)

instance FromJSON text => FromJSON (Lexeme text)
instance ToJSON text => ToJSON (Lexeme text)

mkL :: LexemeClass -> AlexInput -> Int64 -> Alex (Lexeme Text)
mkL c (p, _, str, _) len = pure $ L p c (piece str)
  where piece = Text.decodeUtf8 . LBS.toStrict . LBS.take len

mkE :: LexemeClass -> AlexInput -> Int64 -> Alex (Lexeme Text)
mkE c (p, _, str, _) len = alexError $ ": " <> show (L p c (piece str))
  where piece = Text.decodeUtf8 . LBS.toStrict . LBS.take len

lexemePosn :: Lexeme text -> AlexPosn
lexemePosn (L p _ _) = p

lexemeClass :: Lexeme text -> LexemeClass
lexemeClass (L _ c _) = c

lexemeText :: Lexeme text -> text
lexemeText (L _ _ s) = s

lexemeLine :: Lexeme text -> Int
lexemeLine (L (AlexPn _ l _) _ _) = l

alexEOF :: Alex (Lexeme Text)
alexEOF = return (L (AlexPn 0 0 0) Eof Text.empty)

alexScanTokens :: LBS.ByteString -> Either String [Lexeme Text]
alexScanTokens str =
    runAlex str $ loop []
  where
    loop toks = do
        tok@(L _ cl _) <- alexMonadScan
        if cl == Eof
            then return $ reverse toks
            else loop $! (tok:toks)
}