introduction to parsing from the internal exceptions we use unusuallythe error message contains an escaped str format(field name--the caller is expected to use this to insert the filenamesomething we cannot do here because we are only given the file' textnot the filename or file object at the end we return the root blockwhich should have children (and their childrenrepresenting the parsed blocks def parse(data)while data pos len(data text)if not data advance_up_to("[]/")break if data text[data pos="["data brackets + parse_block(dataelif data text[data pos="/"parse_new_row(dataelif data text[data pos="]"data brackets - data advance_by( elseraise lexerror("expecting '['']'or '/'"but got '{ }'format(data text[data pos])if data bracketsraise lexerror("ran out of text when expecting '{ }'format(']if data brackets else '[')this function is the heart of the recursive descent parser it iterates over the text looking for the start or end of block or new row marker if it reaches the start of block it increments the brackets count and calls parse_block()if it reaches new row marker it calls parse_new_row()and if it reaches the end of block it decrements the brackets count and advances to the next character if any other character is encountered it is an error and is reported accordingly similarlywhen all the data has been parsedif the brackets count is not zero the function reports the error def parse_block(data)data advance_by( nextblock data text find("["data posendofblock data text find("]"data posif nextblock =- or endofblock nextblockparse_block_data(dataendofblockelseblock parse_block_data(datanextblock