elif stripped startswith("<")parser state opentag(elseparser state textnode(return stripped the strip(call removes whitespace from the string then the parser determines if the next item is an opening or closing tagor string of text depending on which possibility occursit sets the parser to particular stateand then tells it to parse the remainder of the string the opentag state is similar to the firsttag stateexcept that it adds the newly created node to the previous current_node object' children and sets it as the new current_node it places the processor back in the childnode state before continuingclass opentagdef process(selfremaining_stringparser)i_start_tag remaining_string find('<'i_end_tag remaining_string find('>'tag_name remaining_string[i_start_tag+ :i_end_tagnode node(tag_nameparser current_nodeparser current_node children append(nodeparser current_node node parser state childnode(return remaining_string[i_end_tag+ :the closetag state basically does the oppositeit sets the parser' current_node back to the parent node so any further children in the outside tag can be added to itclass closetagdef process(selfremaining_stringparser)i_start_tag remaining_string find('<'i_end_tag remaining_string find('>'assert remaining_string[i_start_tag+ ="/tag_name remaining_string[i_start_tag+ :i_end_tagassert tag_name =parser current_node tag_name parser current_node parser current_node parent parser state childnode(return remaining_string[i_end_tag+ :strip(the two assert statements help ensure that the parse strings are consistent the if statement at the end of the method ensures that the processor terminates when it is finished if the parent of node is noneit means that we are working on the root node