def __init__(self): ''' Constructor ''' self._name = "" self._body = StatementParse() self._context = dict()
class Program(object): ''' Program contains the state of a Bug Language program loaded from text. ''' def __init__(self): ''' Constructor ''' self._name = "" self._body = StatementParse() self._context = dict() def set_name(self, name): ''' Sets the name of the program. ''' self._name = name def set_body(self, body): ''' Sets the body statement of the program. ''' self._body = body def get_name(self): ''' Gets the name of the program. ''' return self._name def get_body(self): ''' Gets the body statement of the program. ''' return self._body def add_to_context(self, name, statement): ''' Adds an instruction statement to the program context. ''' self._context[name] = statement def is_in_context(self, name): ''' Returns whether the instruction name is in the program context. ''' return name in self._context def get_context(self): ''' Returns the keys (names) of the instruction in the program context. ''' return self._context.keys() def get_from_context(self, name): ''' Returns the instruction statement corresponding to the given name. ''' return self._context[name] def context_length(self): ''' Returns the length of the program context. ''' return len(self._context) def pretty_print(self): ''' Returns a pretty string version of the program. ''' pretty = "PROGRAM " + self._name + " IS\n\n" for instr in self._context: pretty += "INSTRUCTION " + instr + " IS\n" pretty += self._context[instr].pretty_print(5) pretty += "END " + instr + "\n\n" pretty += "BEGIN\n" + \ self._body.pretty_print(5) + \ "END " + self._name return pretty def __str__(self): ''' Calls the pretty print method of the program. ''' return self.pretty_print()
def parse(self, instream, tokenizer): ''' Parse the text from the instream into a Program object ''' # Expect PROGRAM ttext, ttype = tokenizer.get_next_non_whitespace(instream) if ttype == Constants._types.KEYWORD and ttext == "PROGRAM": debug("PROGRAM", False) else: exit("Expected PROGRAM to begin the program (But was:" + \ ttext + ")") # Expect program name progname, ttype = tokenizer.get_next_non_whitespace(instream) if ttype == Constants._types.IDENTIFIER: debug(progname, False) else: exit("Expected identifier program name after PROGRAM (But was:" + \ progname + ")") self.set_name(progname) # Expect IS ttext, ttype = tokenizer.get_next_non_whitespace(instream) if ttype == Constants._types.KEYWORD and ttext == "IS": debug("IS") else: exit("Expected IS after program name (But was:" + ttext + ")") ttext, ttype = tokenizer.get_next_non_whitespace(instream) # Loop as long as we continue seeing instructions while (ttype == Constants._types.KEYWORD and ttext == "INSTRUCTION"): debug(ttext, False) # Expect instruction name name, ttype = tokenizer.get_next_non_whitespace(instream) if ttype == Constants._types.IDENTIFIER: debug(name, False) else: exit("Expected identifier instruction name after " + \ "INSTRUCTION (But was:" + name + ")") # Expect IS ttext, ttype = tokenizer.get_next_non_whitespace(instream) if ttype == Constants._types.KEYWORD and ttext == "IS": debug(ttext) else: exit("Expected IS after instruction name (But was" + \ ttext + ")") # Parse the statement block making up the instruction ttext, ttype = tokenizer.get_next_non_whitespace(instream) instr = StatementParse() ttext, ttype = instr.parse_block(instream, tokenizer, ttext, ttype) self.add_to_context(name, instr) # Verify we had an END to the instruction if ttype == Constants._types.KEYWORD and ttext == "END": debug("END", False) else: exit("Expected END to complete the instruction (But was:" + \ ttext + ")") # Verify matching instruction name after END ttext, ttype = tokenizer.get_next_non_whitespace(instream) if ttype == Constants._types.IDENTIFIER and ttext == name: debug(ttext) else: exit("Expected matching instruction name ('" + name + \ "') after END (But was:" + ttext + ")") ttext, ttype = tokenizer.get_next_non_whitespace(instream) # Next token should be BEGIN if ttype == Constants._types.KEYWORD and ttext == "BEGIN": debug(ttext) else: exit("Expected BEGIN to initialize the beginning of the " + \ "program (But was:" + ttext + ")") # Parse the statement block making up the body ttext, ttype = tokenizer.get_next_non_whitespace(instream) instr = StatementParse() ttext, ttype = instr.parse_block(instream, tokenizer, ttext, ttype) self.set_body(instr) # Verify we had an END to the body if ttype == Constants._types.KEYWORD and ttext == "END": debug(ttext, False) else: exit("Expected END to complete the body (But was:" + ttext + ")") # Verify matching program name after END ttext, ttype = tokenizer.get_next_non_whitespace(instream) if ttype == Constants._types.IDENTIFIER and ttext == progname: debug(ttext) else: exit("Expected matching instruction name ('" + progname + \ "') after END (But was:" + ttext + ")")
''' Created on Sep 21, 2011 @author: calvin ''' if __name__ == '__main__': from StatementParse import StatementParse from Tokenizer import Tokenizer t = Tokenizer() stmt = StatementParse() f = open("../testinputs/statement.bl") ttext, ttype = t.get_next_non_whitespace(f) stmt.parse(f, t, ttext, ttype) print "\n\n" + str(stmt)