gdritter repos earthling / master src / Earthling / Lexer.x
master

Tree @master (Download .tar.gz)

Lexer.x @masterraw · history · blame

{
{-# LANGUAGE TemplateHaskell #-}

module Earthling.Lexer where

import           AlexTools
import qualified Data.Char as Char
import           Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Read as T

}

$digit  = [0-9]
$letter = [A-Za-z]
$upper  = [A-Z]
$lower  = [a-z]
$op     = [\!\#\$\%\&\*\+\/\<\=\>\?\\\^\|\-\~]

@keyword = "@" [$lower] [$upper $lower _]+
@ident   = [$lower $op] [$upper $lower $digit $op _]*
@constr  = $upper [$upper $lower $digit $op _]*
@stackvar = "'" [$lower $op] [$upper $lower $digit $op _]*
@integer = [$digit]+
@double  = [$digit]+ \. [$digit]+

:-

<0> {

$white+ ;

"--" .* ;

"{-" ( ([^\-] | \n)* ("-"[^\}])? )* "-}" ;

"("  { structure SLParen }
")"  { structure SRParen }
"["  { structure SLBrac }
"]"  { structure SRBrac }
"{"  { structure SLCurl }
"}"  { structure SRCurl }
"."  { structure SDot }
"->" { structure SArrow }

@keyword  { doToken ret       TokKeyword }
@ident    { doToken ret       TokIdent }
@constr   { doToken ret       TokConstr }
@stackvar { doToken ret       TokStackVar }
@integer  { doToken T.decimal TokInt }
@double   { doToken T.double  TokDouble }

}

{

data Tok
  = TokKeyword  Text
  | TokIdent    Text
  | TokConstr   Text
  | TokInt      Integer
  | TokDouble   Double
  | TokStackVar Text
  | TokStructure Structure
    deriving (Eq, Show)

data Structure
  = SLParen
  | SRParen
  | SLBrac
  | SRBrac
  | SLCurl
  | SRCurl
  | SDot
  | SArrow
    deriving (Eq, Show)

structure :: Structure -> Action () [Lexeme Tok]
structure s = lexeme (TokStructure s)

ret :: T.Reader Text
ret t = return (t, mempty)

doToken :: (T.Reader a) -> (a -> Tok) -> Action () [Lexeme Tok]
doToken reader f = do
  t <- matchText
  case reader t of
    Right (res, _) -> lexeme (f res)
    Left err       -> error err

lexer :: Text -> [Lexeme Tok]
lexer str = $makeLexer simpleLexer input
  where input = (initialInput str) { inputPos = start }
        start = SourcePos 0 0 0

alexGetByte = makeAlexGetByte $ \ c ->
  if Char.isAscii c
     then toEnum (fromEnum c)
     else 0x1
}