Last active
August 29, 2015 14:19
-
-
Save nelsonni/361e64eca8de2578c9ce to your computer and use it in GitHub Desktop.
CS381 Homework #2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Hugh McDonald (mcdonalh) | |
-- Faith Steltzer (steltzef) | |
-- Nick Nelson (nelsonni) | |
-- | |
-- CS 381: Homework 2 | |
-- 4.23.15 | |
module HW2 where | |
import Prelude hiding (Num) | |
import Data.List | |
-- Grammar for MiniLogo: | |
-- | |
-- num ::= (any natural number) | |
-- var ::= (any variable name) | |
-- macro ::= (any macro name) | |
-- prog ::= epsilon | cmd ; prog sequence of commands | |
-- mode ::= `down` | `up` pen status | |
-- expr ::= var variable reference | |
-- | num literal number | |
-- | expr `+` expr addition expression | |
-- cmd ::= `pen` mode change pen mode | |
-- | move `(` expr, expr `)` move pen to a new position | |
-- | define macro `(` var* `)` { prog } define a macro | |
-- | call macro `(` expr* `)` invoke a macro | |
-- 1. Define the abstract syntax of MiniLogo as a set of Haskell data types. | |
type Num = Int | |
type Var = String | |
type Macro = String | |
type Prog = [Cmd] | |
data Mode = Down | |
| Up | |
deriving (Eq,Show) | |
data Expr = Ref Var | |
| Lit Num | |
| Add Expr Expr | |
deriving (Eq,Show) | |
data Cmd = Pen Mode | |
| Move Expr Expr | |
| Define Macro [Var] Prog | |
| Call Macro [Expr] | |
deriving (Eq,Show) | |
-- 2. Define a MiniLogo macro `line (x1,y1,x2,y2)` that (starting from anywhere on the canvas) | |
-- draws a line segment from (x1,y1) to (x2,y2). | |
-- | |
-- define line (x1,y1,x2,y2) { | |
-- pen up; move (x1,y1); | |
-- pen down; move (x2,y2); | |
-- } | |
line :: Cmd | |
line = Define "line" | |
["x1", "y1", "x2", "y2"] | |
[Pen Up, Move (Ref "x1") (Ref "y1"), Pen Down, Move (Ref "x2") (Ref "y2")] | |
-- 3. Using the `line` macro you just defined to define a new MiniLogo macro `nix (x,y,w,h)` | |
-- that draws a big "X" of width `w` and height `h`, starting from position `(x,y)`. | |
-- | |
-- define nix (x,y,w,h) { | |
-- line (x,y,x+w,y+h); | |
-- line (x,y+h,x+w,y); | |
-- } | |
nix :: Cmd | |
nix = Define "nix" | |
["x", "y", "w", "h"] | |
[ Call "line" [(Ref "x"), (Ref "y"), (Add (Ref "x") (Ref "w")), (Add (Ref "y") (Ref "h"))] | |
, Call "line" [(Ref "x"), (Add (Ref "y") (Ref "h")), (Add (Ref "x") (Ref "w")), (Ref "y")] ] | |
-- 4. Define a Haskell function `steps :: Int -> Prog` that constructs a MiniLogo program that | |
-- draws a staircase of `n` steps starting from `(0,0)`. | |
steps :: Int -> Prog | |
steps 0 = [Pen Up, Move (Lit 0) (Lit 0), Pen Down] | |
steps n = steps (pred n) ++ [Move (Lit (pred n)) (Lit n)] ++ [Move (Lit n) (Lit n)] | |
-- 5. Define a Haskell function `macros :: Prog -> [Macro]` that returns a list of the names | |
-- of all of the macros that are defined anywhere in a given MiniLogo program. | |
macros :: Prog -> [Macro] | |
macros [] = [] | |
macros (x:xs) = if (ismacros x) == True then extractmacros x : macros xs else macros xs | |
extractmacros :: Cmd -> Macro | |
extractmacros (Define m v p) = m | |
ismacros :: Cmd -> Bool | |
ismacros (Define m v p) = True | |
ismacros _ = False | |
-- 6. Define a Haskell function `pretty :: Prog -> String` that pretty-prints a MiniLogo program. | |
pretty :: Prog -> String | |
pretty [] = [] | |
pretty (x:xs) = prettyCmd x ++ pretty xs | |
prettyCmd :: Cmd -> String | |
prettyCmd (Define x y z) = "define " ++ x ++ " (" ++ prettyVar y ++ ") {\n" ++ pretty z ++ "}\n" | |
prettyCmd (Call x y) = "call " ++ x ++ " (" ++ concat (intersperse "," (map prettyExpr y)) ++ ");\n" | |
prettyCmd (Pen Down) = "pen down;\n" | |
prettyCmd (Pen Up) = "pen up;\n" | |
prettyCmd (Move x y) = "move (" ++ prettyExpr x ++ "," ++ prettyExpr y ++ ");\n" | |
prettyExpr :: Expr -> String | |
prettyExpr (Ref x) = x | |
prettyExpr (Lit x) = show x | |
prettyExpr (Add x y) = (prettyExpr x) ++ "+" ++ (prettyExpr y) | |
prettyVar :: [Var] -> String | |
prettyVar [] = [] | |
prettyVar [x] = x | |
prettyVar (x:xs) = x ++ ", " ++ prettyVar xs |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment