Upgrade is finished. Everything should be working now.

Commit 7a19bf92 authored by Tadej Borovšak's avatar Tadej Borovšak
Browse files

Finish hw

parent bd9a889d
...@@ -4,17 +4,33 @@ import Imp_AbsSyntax ...@@ -4,17 +4,33 @@ import Imp_AbsSyntax
import Imp_State import Imp_State
evalAExp :: State -> AExp -> Integer evalAExp :: State -> AExp -> Integer
evalAExp _ (Num n) = n
evalAExp s (Loc l) = valof s l
evalAExp s (AOp (opName, e1, e2)) = op v1 v2
where v1 = evalAExp s e1
v2 = evalAExp s e2
op = case opName of
"+" -> (+)
"-" -> (-)
"*" -> (*)
_ -> error $ "Runtime error: unknow arithmetic op - " ++ opName
evalBExp :: State -> BExp -> Bool evalBExp :: State -> BExp -> Bool
evalBExp _ (Boolean b) = b
evalBExp s (BOp (opName, e1, e2)) = op v1 v2
where v1 = evalAExp s e1
v2 = evalAExp s e2
op = case opName of
"==" -> (==)
"<" -> (<)
_ -> error $ "Runtime error: unknown boolean op - " ++ opName
evalCom :: State -> Com -> State evalCom :: State -> Com -> State
evalCom s (Assign (l, e)) = update s l $ evalAExp s e
-- evalCom s (Cond (e, c1, c2)) = evalCom s $ if evalBExp s e then c1 else c2
-- [[DEFINE EVALUATION FUNCTIONS FOR: evalCom s (Seq (c1, c2)) = evalCom (evalCom s c1) c2
-- evalCom s Skip = s
-- * ARITHMETIC EXPRESSIONS evalCom s loop@(While (e, c)) =
-- * BOOLEAN EXPRESSIONS if evalBExp s e
-- * COMMANDS then evalCom (evalCom s c) loop
-- else s
-- WITH THE TYPES SPECIFIED ABOVE]]
--
...@@ -11,7 +11,6 @@ import Imp_Evaluator ...@@ -11,7 +11,6 @@ import Imp_Evaluator
runImp filename s = do runImp filename s = do
progtext <- readFile filename progtext <- readFile filename
let lexed = imp_lex progtext print $ run progtext s
parsed = imp_parse lexed
s' = evalCom s parsed run progtext s = evalCom s $ imp_parse $ imp_lex progtext
in print s'
-- vim: set syntax=alex autoindent -- vim: set syntax=alex autoindent ts=4 sts=4 sw=4 expandtab :
{module Imp_Lex where } {
module Imp_Lex
( Token(..)
, AlexPosn(AlexPn)
, pos
, imp_lex
) where
}
%wrapper "posn"
%wrapper "basic" $digit = [0-9]
$alpha = [A-Za-z]
-- character classes @number = $digit+
@ident = [$alpha _] [$alpha $digit _]*
@keywords = if | then | else | while | do | skip
@operations = \+ | \- | \* | \=\= | \<
@booleans = True | False
$digit = [0-9] tokens :-
$alpha = [A-Za-z]
:- $white+ ; -- whitespace
$white+ ; -- whitespace \( { \p _ -> LPAREN p } -- scope start
\( | \) {\s -> SCOPE s} -- scope \) { \p _ -> RPAREN p } -- scope end
\; {\s -> DELIM} -- command delimiter \; { \p _ -> DELIM p } -- command delimiter
\+ | \- | \* {\s -> OP s} -- arithmetic ops \:\= { \p _ -> ASSIGN p } -- assignment
\=\= | \< {\s -> OP s} -- boolean ops @operations { \p s -> BINOP p s } -- binary operations
\:\= {\s -> ASSIGN} -- assignment @keywords { \p s -> KEYWORD p s } -- keywords
if | then | else {\s -> KEYWORD s} -- if command @number { \p s -> NUM p $ read s } -- integer literals
while | do {\s -> KEYWORD s} -- while command @booleans { \p s -> BOOL p $ read s } -- Boolean literals
skip {\s -> KEYWORD s} -- skip command @ident { \p s -> LOC p s } -- locations (variables)
True | False {\s -> BOOL $ read s} -- boolean literals
$digit+ {\s -> NUM $ read s} -- numbers . { \p s -> INVALID p s } -- invalid char
$alpha [$alpha $digit \_]* {\s -> LOC s} -- locations
{ {
-- The Token type - the action for each lexical class has type String -> Token -- The Token type - the action for each lexical class has type String -> Token
data Token = SCOPE String data Token = LPAREN AlexPosn
| DELIM | RPAREN AlexPosn
| OP String | DELIM AlexPosn
| ASSIGN | ASSIGN AlexPosn
| KEYWORD String | BINOP AlexPosn String
| BOOL Bool | KEYWORD AlexPosn String
| NUM Integer | NUM AlexPosn Integer
| LOC String | BOOL AlexPosn Bool
| INVALID | LOC AlexPosn String
| INVALID AlexPosn String
deriving Show deriving Show
-- Position accessor
pos :: Token -> AlexPosn
pos (LPAREN p ) = p
pos (RPAREN p ) = p
pos (DELIM p ) = p
pos (ASSIGN p ) = p
pos (BINOP p _) = p
pos (KEYWORD p _) = p
pos (NUM p _) = p
pos (BOOL p _) = p
pos (LOC p _) = p
pos (INVALID p _) = p
-- Exported lexer
imp_lex = alexScanTokens imp_lex = alexScanTokens
} }
-- vim: set syntax=happy -- vim: set syntax=happy autoindent ts=4 sts=4 sw=4 :
{
module Imp_Parse (imp_parse) where
{module Imp_Parse where
import Imp_Lex import Imp_Lex
import Imp_AbsSyntax import Imp_AbsSyntax
} }
-- the parser implements a function %name imp_parse Prog
--
-- imp_parse :: [Token] -> Com
--
-- that converts a list of tokens to the abstract syntax tree of a command
%name imp_parse Com
%tokentype { Token } %tokentype { Token }
%error { parseError } %error { parseError }
%token -- tokens
%token '(' { LPAREN _ }
--declaration of terminal symbols ')' { RPAREN _ }
';' { DELIM _ }
assign { ASSIGN _ }
'+' { BINOP _ "+" }
'-' { BINOP _ "-" }
'*' { BINOP _ "*" }
'<' { BINOP _ "<" }
'~' { BINOP _ "==" }
if { KEYWORD _ "if" }
then { KEYWORD _ "then" }
else { KEYWORD _ "else" }
while { KEYWORD _ "while" }
do { KEYWORD _ "do" }
skip { KEYWORD _ "skip" }
num { NUM _ $$ }
bool { BOOL _ $$ }
loc { LOC _ $$ }
--
-- [[DECLARE YOUR TERMINAL SYMBOLS HERE]]
--
-- precedence and associativity declarations, lowest precedence first -- precedence and associativity declarations, lowest precedence first
-- -- these are needed to break shift/reduce conflict in while/if statements
-- [[MAKE PRECEDENCE AND ASSOCIATIVITY DECLARATIONS HERE]] %nonassoc do then else
-- %right ';'
%nonassoc assign
%nonassoc '~' '<'
%left '+' '-'
%left '*'
%% %%
-- the grammar Prog : {- empty -} { Skip }
| Command { $1 }
Command : skip { Skip }
| loc assign AExpr { Assign ($1, $3) }
| if BExpr then Command else Command { Cond ($2, $4, $6) }
| while BExpr do Command { While ($2, $4) }
| Command ';' Command { Seq ($1, $3) }
| '(' Command ')' { $2 }
AExpr : loc { Loc $1 }
| num { Num $1 }
| AExpr '+' AExpr { AOp ("+", $1, $3) }
| AExpr '-' AExpr { AOp ("-", $1, $3) }
| AExpr '*' AExpr { AOp ("*", $1, $3) }
-- BExpr : bool { Boolean $1 }
-- [[DEFINE YOUR GRAMMAR AND ITS ACTIONS HERE]] | AExpr '<' AExpr { BOp ("<", $1, $3) }
-- | AExpr '~' AExpr { BOp ("==", $1, $3) }
{ {
parseError :: [Token] -> a parseError :: [Token] -> a
parseError _ = error "Imp parse error" parseError ts = error ("Parse error at " ++ location ++ "\n")
where
location = case ts of
[] -> "end of file"
(t:_) -> "line " ++ show l ++ ", column " ++ show c
where AlexPn _ l c = pos t
} }
Y := 1 ; while 0 < X do Y := Y * X ; X := X - 1 X := 6 ; Y := 1 ; while 0 < X do Y := Y * X ; X := X - 1
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment