-- -- file: Cmd.lhs -- -- created: 22/11/96 by Andrew Rock. -- -- purpose: This module defines and parses entre commands. -- > module Cmd (Cmd (Quit, Expression, Laat, Help, Typo, Bind, Print, Read, > Blank, Silent, Eval, Fewer, WF), > cmdP, readCommand, helpStr, > entreHeading, entreHelpful, entrePrompt, entreGoodbye) where > import Parser > import Lexer > import Expr ===================================== Data type used to store user commands ===================================== > data Cmd = Quit -- quit entre > | Help -- print list of commands > | Print -- print all bindings > | Expression Expr -- evaluate Expr > | Laat Expr -- evaluate Expr Line at a time > | Fewer Expr -- evaluate Expr printing fewer steps > | WF Expr -- fewer & line at a time > | Bind String Expr -- bind String to Expr > | Read String -- read script in file named String > | Silent Expr -- silently evaluate Expr > | Eval String Expr -- bind String to evaluated Expr > | Blank -- only whitespace or comments > | Typo Pos Msg -- lex or parse error at Pos with Msg ======================== Parser for user commands ======================== cmd ::= :q | :? | :p | :r "filename" | name {argname} = expr | :w expr | :s expr | :f expr | (:wf | :fw) expr | name := expr | expr | blank > cmdP :: Parser Cmd > cmdP = (nofail . total) ( > literalP "symbol" ":" *> literalP "name" "q" #> Quit > <|> literalP "symbol" ":" *> literalP "symbol" "?" #> Help > <|> literalP "symbol" ":" *> literalP "name" "p" #> Print > <|> literalP "symbol" ":" *> literalP "name" "r" > *> nofail' "filename in quotes (\") expected" (tagP "string") > @> (\(_,f,_) -> Read f) > <|> nameP <*> (many nameP) <*> literalP "symbol" "=" > *> nofail' "expression expected" exprP > @> (\ (Name n, (args, e)) -> Bind n (makeFunction args e)) > <|> literalP "symbol" ":" *> literalP "name" "w" *> > nofail' "expression expected" exprP @> (\e -> Laat e) > <|> literalP "symbol" ":" *> literalP "name" "f" *> > nofail' "expression expected" exprP @> (\e -> Fewer e) > <|> literalP "symbol" ":" *> (literalP "name" "wf" <|> > literalP "name" "fw") *> > nofail' "expression expected" exprP @> (\e -> WF e) > <|> literalP "symbol" ":" *> literalP "name" "s" *> > nofail' "expression expected" exprP @> (\e -> Silent e) > <|> nameP <*> literalP "symbol" ":=" > *> nofail' "expression expected" exprP > @> (\(Name n,e) -> Eval n e) > <|> exprP @> (\ e -> Expression e) > <|> succeedA Blank > ) This is a wrapper around the above parser that handles the pre-lexical and lexical stages as well and returns any error inf as a Typo. > readCommand :: String -> Cmd > readCommand input > = case lexerL (preLex input) of > Error pos msg -> Typo pos msg > OK (ls,_) -> case cmdP ls of > Error pos' msg' -> Typo pos' msg' > OK (cmd,_) -> cmd ========================================== This is the text printed in response to :? ========================================== > helpStr :: String > helpStr > = "Commands:\n" ++ > " :q Quit ENTRE.\n" ++ > " :? Print this message.\n" ++ > " expression Evaluate this expression.\n" ++ > " :s expression Silently evaluate expression.\n" ++ > " :w expression Walk the expression, one step at a time.\n" ++ > " :f expression Evaluate the expression, printing fewer\ > \ steps.\n" ++ > " :wf expression Evaluate the expression, using :w and :f\n" ++ > " name = expression Bind name to expression.\n" ++ > " name := expression Bind name to evaluated expression.\n" ++ > " f x y ... = expr Define function.\n" ++ > " :p Print all bindings.\n" ++ > " :r \"filename\" Read commands from file.\n" ============== Other Messages ============== A welcome message: > entreHeading :: String > entreHeading > = "Welcome to ENTRE (Explicit Naive Term Rewriting Engine).\n\ > \90% sugar free!\n" A helpful message for starters: > entreHelpful :: String > entreHelpful = "Type \":?\" for help.\n" Command line prompt: > entrePrompt :: String > entrePrompt = "entre? " Clean-up msg. > entreGoodbye :: String > entreGoodbye = "Goodbye.\n"