This library is a simple regular expression lexer/scanner for the Haskell programming language. It is "interesting" because it is completely dynamic: the lexer may be modified at runtime, and string buffers may be lexed by different lexers at different times.
In addition to providing a lexer/scanner package, it also provides access to a regular expression->DFA compiler as well as a package of DFA utilities to modify and run a string through it...
Here are some documents that describe the project:
Okay, now go download the source... there are snapshots of the source available in the snapshot directory.
There are several things that complicate processing of user input. The first is the backspace character: because Haskell does not buffer IO, backspaces are sent through as raw input and must be stripped by the application. This is not an insurmountable problem, as it is taken care of with a single function.
The second is the parsing stage of the input. Although they are no substitute for a full-blown parser, Haskell's pattern matching rules are very powerful for handling user input.
The third issue is how to handle errors. This is taken care of with two different techniques: a general error handler and a specific error handler to produce user-friendly error messages. The general technique just uses a pattern matching rule that always matches, and prints the standard "unrecognized input" message. The context specific error handler is used to catch common input errors and gently assist the user.
A user transaction with the program is illustrated below, with user input bolded:
Main> go Input (or help)>help Supported commands: quit, help, load "filename" Input (or help)>What do I do? Invalid input: What do I do? Input (or help)>l The load command must be followed by a filename! Input (or help)>load "filename" Loading "filename" as you requested Input (or help)>okay, quit me Invalid input: okay, quit me Input (or help)>quit Main>...and here is the source code for the program:
import Lexer
-- stripBS processes the backspace characters in a string...
stripBS (x:'\b':xs) = stripBS xs
stripBS (x:xs) = x:stripBS xs
stripBS [] = []
go = do putStr "Input (or help)>"
input <- getLine
result <- processInput (stripBS input)
if (result) then
return ()
else
go
data TokType = TokIgnore | TokHelp | TokQuit | TokError | TokLoad | TokString
deriving (Show, Eq) -- Make it showable, and =='able
tokLexer =
compileLexer [ ("[ \n\t]+", TokIgnore), -- Ignore whitespace
("l(oad)?", TokLoad), -- Match load
("h(elp)?", TokHelp), -- Match help
("q(uit)?", TokQuit), -- Match quit
("\"[^\"]*\"", TokString)
] TokError
-- processInput - Convert string into a list of tokens, remove ignored tokens, then pattern
-- match the result.
--
processInput = processTokens . filter ((/=TokIgnore).snd) . lexIntoList tokLexer
-- Pattern match the input tokens...
--
processTokens [(_, TokQuit)] = return True
processTokens [(_, TokHelp)] = do putStr ("Supported commands: quit, help, load \"filename\"\n")
return False
processTokens [(_, TokLoad),(v, TokString)] = do putStr ("Loading " ++ v ++ " as you requested\n")
return False
processTokens [(_, TokLoad)] = do putStr ("The load command must be followed by a filename!\n")
return False
processTokens x = do (putStr . (++) "Invalid input: " . concat . map fst) x
putStr "\n"
return False