blob: 2fbbde08525458418f19581b79a05f9646612ede [file]
-- |
-- Module : Minigent.Syntax.Lexer
-- Copyright : (c) Data61 2018-2019
-- Commonwealth Science and Research Organisation (CSIRO)
-- ABN 41 687 119 230
-- License : BSD3
--
-- Contains the lexer for the concrete syntax of Minigent.
--
-- It expects to be imported qualified, as the keyword tokens clash with expression constructors.
module Minigent.Syntax.Lexer
( Token (..)
, Bracket (..)
, Keyword (..)
, lexer
) where
import Minigent.Syntax (Op (..))
import Minigent.Syntax.Utils
import Data.Char
import Data.List (span)
data Bracket = Paren | Brace | Square
deriving (Show, Eq)
data Keyword = Case | Of | If | Then | Else | Take | Put | Let | In | End | Rec
deriving (Show, Eq)
data Token
= LowerIdent String -- ^ @[a-z][a-zA-Z0-9]*@
| UpperIdent String -- ^ @[A-Z][a-zA-Z0-9]*@
| Numeric Integer -- ^ @[0-9]+@
| Open Bracket -- ^ @( or [ or {@
| Close Bracket -- ^ @) or ] or }@
| Keyword Keyword
| Operator Op
| Bang -- ^ @!@
| Colon -- ^ @:@
| Comma -- ^ @,@
| Bar -- ^ @|@
| Arrow -- ^ @->@
| Hash -- ^ @#@
| Equals -- ^ @=@
| Dot -- ^ @.@
| Semi -- ^ @;@
| Unknown Char -- ^ For errors
deriving (Show, Eq)
toToken "case" = Keyword Case
toToken "of" = Keyword Of
toToken "if" = Keyword If
toToken "then" = Keyword Then
toToken "end" = Keyword End
toToken "else" = Keyword Else
toToken "take" = Keyword Take
toToken "put" = Keyword Put
toToken "let" = Keyword Let
toToken "in" = Keyword In
toToken "rec" = Keyword Rec
toToken (x:xs) | isLower x = LowerIdent (x:xs)
| otherwise = UpperIdent (x:xs)
-- | An error in the lexer will produce 'Unknown' tokens.
lexer :: String -> [Token]
lexer [] = []
lexer (x:xs) | isSpace x = lexer xs
lexer (x:xs) | isLetter x = let
(word, rest) = span isAlphaNum (x:xs)
in toToken word : lexer rest
lexer (x:xs) | isDigit x = let
(number, rest) = span isDigit (x:xs)
in Numeric (read number) : lexer rest
lexer (x:y:xs) | Just o <- lookup [x,y] operators
= Operator o : lexer xs
lexer ('-':'>':xs) = Arrow : lexer xs
lexer (x:xs) | Just o <- lookup [x] operators
= Operator o : lexer xs
lexer ('(':xs) = Open Paren : lexer xs
lexer (')':xs) = Close Paren : lexer xs
lexer ('[':xs) = Open Square : lexer xs
lexer (']':xs) = Close Square : lexer xs
lexer ('{':xs) = Open Brace : lexer xs
lexer ('}':xs) = Close Brace : lexer xs
lexer ('=':xs) = Equals : lexer xs
lexer ('!':xs) = Bang : lexer xs
lexer (';':xs) = Semi : lexer xs
lexer (':':xs) = Colon : lexer xs
lexer ('.':xs) = Dot : lexer xs
lexer ('#':xs) = Hash : lexer xs
lexer (',':xs) = Comma : lexer xs
lexer ('|':xs) = Bar : lexer xs
lexer (c:xs) = Unknown c : lexer xs