diff --git a/improved/ast.py b/improved/ast.py index cbbe675..c5131e4 100644 --- a/improved/ast.py +++ b/improved/ast.py @@ -388,6 +388,42 @@ class IfStatement(Statement): if self.on_false: self.on_false.eval(env) +class ReadStatement(Statement): + def __repr__(self): + return 'ReadStatement()' + + def eval(self, env): + try: + return int(input()) + except ValueError: + return 0 + +class WriteStatement(Statement): + """The AST node for write statements""" + def __init__(self, message): + """ + The initialization method. + + message -- the message that should be printed + """ + self.message = message + + def __repr__(self): + """ + A representation of the node for debug purposes. + + returns -- a String of the form + "WriteStatement(message)" + """ + return 'WriteStatement(%s)' % message + + def eval(self, env): + """ + Evaluates the node. Prints the message. + + returns -- None + """ + return print(self.message.eval(env)) class WhileStatement(Statement): """The AST node for while statements""" @@ -420,3 +456,34 @@ class WhileStatement(Statement): """ while self.condition.eval(env): self.body.eval(env) + +class ForStatement(Statement): + """The AST node for for statements""" + def __init__(self, count, body): + """ + The initialization method. + + count -- the number of times the body should be executed + body -- the statement that is to be executed while + inside the loop + """ + self.count = count + self.body = body + + def __repr__(self): + """ + A representation of the node for debug purposes. + + returns -- a String of the form + "ForStatement(count, body)" + """ + return 'ForStatement(%s, %s)' % (self.count, self.body) + + def eval(self, env): + """ + Evaluates the node. Executes the body block count times. + + env -- the environment in which to evaluate the node + """ + for _ in range(self.count.eval(env)): + self.body.eval(env) diff --git a/improved/parser.py b/improved/parser.py index 7f8634b..775b3d1 100644 --- a/improved/parser.py +++ b/improved/parser.py @@ -117,13 +117,18 @@ def arithmetic_value(): return ((num ^ (lambda i: IntArithmeticExp(i))) | (imp_id ^ (lambda v: VarArithmeticExp(v)))) +def read_statement(): + def internal(parsed): + return ReadStatement() + return keyword('read') ^ internal + def arithmetic_term(): """ Matches an arithmetic term. returns -- a parser matching an arithmetic value or group """ - return arithmetic_value() | arithmetic_group() + return read_statement() | arithmetic_value() | arithmetic_group() def arithmetic_exp(): """ @@ -205,10 +210,44 @@ def while_statement(): + keyword('do') + Lazy(statements) + keyword('end') ^ internal) +def for_statement(): + """ + Builds a parser for for statements. + + returns -- a parser for for statements + """ + def internal(parsed): + ((((_, condition), _), body), _) = parsed + return ForStatement(condition, body) + return (keyword('for') + arithmetic_exp() + + keyword('do') + Lazy(statements) + + keyword('end') ^ internal) + +def write_statement(): + """ + Builds a parser for write statements. + + returns -- a parser for write statements + """ + def internal(parsed): + (_, message) = parsed + return WriteStatement(message) + return keyword('write') + arithmetic_exp() ^ internal + def statement(): - return assign_statement() | if_statement() | while_statement() + """ + Builds a parser for single IMP statements. + + returns -- a parser for single statements in the IMP langauge + """ + return write_statement() | assign_statement() | if_statement() | while_statement() | for_statement() def statements(): + """ + Builds a parser for multiple IMP statements. + + returns -- a parser for multiple statements in the IMP language + """ sep = keyword(';') ^ (lambda x: lambda l, r: CompoundStatement(l, r)) return Exp(statement(), sep) diff --git a/improved/tokenize.py b/improved/tokenize.py index fe60c99..c33911e 100644 --- a/improved/tokenize.py +++ b/improved/tokenize.py @@ -23,6 +23,8 @@ TOKENS = [ (r'>', RESERVED), (r'=', RESERVED), (r'!=', RESERVED), + (r'read', RESERVED), + (r'write', RESERVED), (r'and', RESERVED), (r'or', RESERVED), (r'not', RESERVED), @@ -30,6 +32,7 @@ TOKENS = [ (r'then', RESERVED), (r'else', RESERVED), (r'while', RESERVED), + (r'for', RESERVED), (r'do', RESERVED), (r'end', RESERVED), (r'[0-9]+', INT),