packages feed

pretty-ghci-0.1.0.0: src/Text/PrettyPrint/GHCi/Value/Lexer.x

{
module Text.PrettyPrint.GHCi.Value.Lexer (
  lexTokens,
  Token(..),
) where

import Data.Char     ( generalCategory, GeneralCategory(..) )
}

%wrapper "basic"

$binit     = 0-1
$octit     = 0-7
$decdigit  = 0-9
$hexit     = [$decdigit A-F a-f]

-- Number stuff
@numspc       = _*
@decimal      = $decdigit(@numspc $decdigit)*
@binary       = $binit(@numspc $binit)*
@octal        = $octit(@numspc $octit)*
@hexadecimal  = $hexit(@numspc $hexit)*
@exponent     = @numspc [eE] [\-\+]? @decimal
@bin_exponent = @numspc [pP] [\-\+]? @decimal

@floating_point = @numspc @decimal \. @decimal @exponent? | @numspc @decimal @exponent
@hex_floating_point = ( @numspc @hexadecimal \. @hexadecimal @bin_exponent? 
                      | @numspc @hexadecimal @bin_exponent
                      )

@magic_hash  = ( \# | \#\# )?
@number_prim = ( @decimal
               | 0[bB] @numspc @binary
               | 0[oO] @numspc @octal
               | 0[xX] @numspc @hexadecimal
               | @floating_point
               | 0[xX] @numspc @hex_floating_point
               )
@number      = [\-]? @number_prim @magic_hash

-- Characters and strings literal
@char_escape = \\ ( [abfnrtv\\"']
                  | \^ [@-_]
                  | x $hexit+
                  | o $octit+
                  |   $decdigit+
                  | NUL | SOH | STX | ETX | EOT | ENQ | ACK | BEL | BS  | HT
                  | LF  | VT  | FF  | CR  | SO  | SI  | DLE | DC1 | DC2 | DC3
                  | DC4 | NAK | SYN | ETB | CAN | EM | SUB | ESC  | FS  | GS
                  | RS  | US  | SP  | DEL
                  )

@character    = \' (~ [\\ \'] | \\ \' | @char_escape)  \'
@string       = \" (~ [\\ \"] | \\ \" | @char_escape)* \"

-- Symbol or operator (everything else)

$sym_op_char  = ~[ $white \[ \] \( \) \{ \} \, \" \' \= ]
@sym_op       = ($sym_op_char # $decdigit) $sym_op_char*

tokens :-

    $white+        { WhiteTok }
    
    "("            { const OpenParen }
    ")"            { const CloseParen }
    
    "["            { const OpenBracket }
    "]"            { const CloseBracket }
    
    "{"            { const OpenBrace }
    "}"            { const CloseBrace }
    
    ","            { const Comma }
    "="            { const Equal }
   
    @decimal       { NumberTok }
    @number        { NumberTok }
    @character     { CharacterTok }
    @string        { StringTok }
    
    @sym_op        { operatorOrSymbol }

{

-- | Turn a 'String' into a list of 'Token'. This may error out for
-- particularly bad inputs (ex: unclosed string).
lexTokens :: String -> [Token]
lexTokens = alexScanTokens

-- | Our somewhat simplified version of GHC Haskell tokens 
data Token
  = WhiteTok      String
  | NumberTok     String
  | StringTok     String
  | CharacterTok  String
  | OperatorTok   String
  | IdentifierTok String  -- ^ we're overly liberal with what can be an
                          -- identifier (so as to accomodate custom 'Show'
                          -- instances)
  | OpenParen
  | CloseParen
  | OpenBracket
  | CloseBracket
  | OpenBrace
  | CloseBrace
  | Comma
  | Equal
  deriving (Eq, Show)

-- | Classify a string as either an operator or an identifier 
operatorOrSymbol :: String -> Token
operatorOrSymbol str
  | all isOperatorLike str = OperatorTok str
  | otherwise              = IdentifierTok str

-- | Characters in these categories can be part of operators
isOperatorLike :: Char -> Bool
isOperatorLike '_' = False
isOperatorLike c = generalCategory c `elem` [ ConnectorPunctuation
                                            , DashPunctuation
                                            , OtherPunctuation
                                            , MathSymbol
                                            , CurrencySymbol
                                            , ModifierSymbol
                                            , OtherSymbol ]

}