All pastes #1608570 Raw Edit

Parser

public python v1 · immutable
#1608570 ·published 2009-10-10 00:34 UTC
rendered paste body
class ParseError(Exception):    """Report an error parsing the document."""        def __init__(self, data):    	"""Initialize a new exception with data about the error."""        self.data = data            def __str__(self):    	"""Return the error data as a string."""        return str(self.data)def parse(lines):    """Take a 148ML document as input, and return a parsed version represented    as a list of nested lists."""        print lines    # Fill here!    import stack        #Variable new_lines is assigned as lines without "\n"    new_lines = lines.replace("\n", "")    #Variable lst_lines is assigned as a list of new_lines split at ">"    lst_lines = new_lines.split(">")        #Variables tag_stack & tag_checker are assigned empty stacks. An empty list    #is added to tag_stack.    tag_stack = stack.Stack()    tag_stack.push([])    tag_checker = stack.Stack()        #For every line in the list of lines:    for line in lst_lines:	line = line.strip() #Take white space off the front and end of the line.		#If the line is an empty string, then it changes to " ".	if line == "":	    line = " "		#If line is made of letters:	if line.isalpha():	    #The current line is appended to the topmost object in tag_stack	    current_tag = tag_stack.pop()	    current_tag.append(line)	    tag_stack.push(current_tag)	#Otherwise if a space is in line or the first character is a letter:	elif " " in line or line[0].isalpha():	    if " " in line: #If line has a space:		#Variable temp_line is assigned a list of line split at " ".		temp_line = line.split(" ")	    else:		#Variable temp_line is assigned a list of line split with "<".		i = line.find("<")		temp_line = [line[:i], line[i:]]	    #For every piece of the line:	    for piece in temp_line:		#If the piece is not an empty string:		if piece != "":		    #If the piece is made of letters:		    if piece.isalpha():			#The piece is added to the topmost object in tag_stack.			current_tag = tag_stack.pop()			current_tag.append(piece)			tag_stack.push(current_tag)			#Otherwise if the first two characters are "</":		    elif piece[0:2] == "</":			current_tag = tag_stack.pop()			bit = "<" + piece[2:] + ">"			#If the tag text is non alphabetic, raise an exception.			if not piece[2:].isalpha():			    raise ParseError("Tag is non alphabetical.")			#Otherwise if current_tag isn't empty & first tag is			#the opening tag for piece:			elif current_tag != [] and current_tag[0] == bit:			    #End tag gets added to current tag then is added			    #to the lower layer. Otherwise raise exception.			    current_tag.append(piece + ">")			    new_tag = tag_stack.pop()			    new_tag.append(current_tag)			    tag_stack.push(new_tag)			    tag_checker.pop()			else:			    raise ParseError("Tag not balanced.")		    #Otherwise if the first character is "<":		    elif piece[0] == "<":			#If the rest of the piece is made of letters:			if piece[1:].isalpha():			    #Piece tag is added to tag_Stack & tag_checker			    #otherwise raise exception.			    tag_stack.push([piece + ">"])			    tag_checker.push(piece + ">")			else:			    raise ParseError("Tag is non alphabetical.")		    #Otherwise raise exception.		    elif not piece.isalpha() and not piece.isspace():			raise ParseError("Word is non alphabetical.")	#Otherwise:	else:	    #If the first two characters of the line are "</":	    if line[0:2] == "</":		current_tag = tag_stack.pop()		bit = "<" + line[2:] + ">"		#If the rest of the line is non alphabetic raise an exception.		if not line[2:].isalpha():		    raise ParseError("Tag is non alphabetical.")		#Otherwise if the end tag matches the current opening tag:		elif current_tag != [] and current_tag[0] == bit:		    #End tag is added & then the whole tag line is added to		    #the proceeding tag line.		    current_tag.append(line + ">")		    new_tag = tag_stack.pop()		    new_tag.append(current_tag)		    tag_stack.push(new_tag)		    tag_checker.pop()		#Otherwise if no open tag or end tag doesn't match open tag:		#raise exception.		elif current_tag == [] or current_tag[0] != bit:		    raise ParseError("Tag not balanced.")	    #Otherwise if the first character is "<":	    elif line[0] == "<":		#If the tag is made of letters:		if line[1:].isalpha():		    #Open tag is added to tag_stack & tag_checker otherwise		    #raise exception.		    tag_stack.push([line + ">"])		    tag_checker.push(line + ">")		else:		    raise ParseError("Tag is non alphabetical.")	    #Otherwise if the line is non alphabetic & not a space:	    #raise exception.	    elif not line.isalpha() and not piece.isspace():		raise ParseError("Word is non alphabetical.")    #Variable result is assigned the remaining tag line    result = tag_stack.pop()    #If there's still an open tag: raise exception. Otherwise return result.    if not tag_checker.empty():	raise ParseError("Tags not balanced.")    else:	return result	            if __name__ == '__main__':    # The second example from the assignment description    doc = '<html>\n\    <head><title>Example\n</title></head>\n\    <body>quiet<CAPSLOCK>  LOUD       </CAPSLOCK> quiet</body>\n\    </html>'        print parse(doc)