Question: Use Python to finish an parser for the mini-command language in the Lecture Notes 1, extended with if-else commands, then it will be able to

Use Python to finish an parser for the mini-command language in the Lecture Notes 1, extended with if-else commands, then it will be able to parse a sample program looks like this:

=================================================== x = 2; while x : print x end; if (x + 1) : print x else print (x-9) end ===================================================

Here is the execution of this program:

python run.py Type program; OK to do it on multiple lines; terminate with ! as the first symbol on a line by itself: x = 2; while x : print x end; if (x + 1) : print x else print (x-9) end ! scanned program: ['x', '=', '2', ';', 'while', 'x', ':', 'print', 'x', 'end', ';', 'if', '(', 'x', '+', '1', ')', ':', 'print', 'x', 'else', 'print', '(', 'x', '-', '9', ')', 'end'] parsed program: [[['=', 'x', '2'], ['while', 'x', [['print', 'x']]], ['if', ['+', 'x', '1'], [['print', 'x']], [['print', ['-', 'x', '9']]]]]] press Enter key to finish

The program is parsed into its tree.

Here the grammar of the language we implement:

===================================================

PROGRAM ::= COMMANDLIST

COMMANDLIST ::= COMMAND | COMMAND ; COMMANDLIST

COMMAND ::= VAR = EXPRESSSION

| print EXPRESSION

| while EXPRESSION : COMMANDLIST end

| if EXPRESSION : COMMANDLIST else COMMANDLIST end

EXPRESSION ::= NUMERAL | VAR | ( EXPRESSION OPERATOR EXPRESSION ) OPERATOR is + or -

NUMERAL is a sequence of digits from the set, {0,1,2,...,9}

VAR is a string of lower-case letters, not a keyword ===================================================

A scanner essentially same as the one in Lecture Note 1 to build parse trees for this grammar has been provided, you job is to modify the parser so that it will parse if-else as well with grammar defined above.

Abstract syntax tree (operator tree) format

The parser will construct the list-represented tree for a program. The syntax of trees is this:

===================================================

PTREE ::= [ CLIST ]

CLIST ::= [ CTREE+ ]

where CTREE+ means one or more CTREEs

CTREE ::= ["=", VAR, ETREE] | ["print", ETREE] | ["while", ETREE, CLIST] | ["if", ETREE, CLIST, CLIST]

ETREE ::= NUMERAL | VAR | [OP, ETREE, ETREE]

where OP is either "+" or "-" ===================================================

Notice how the trees match the grammar constructions. Since the trees are nested lists, it is easy to disassemble them and compute on their parts.

Please complete TODO portion please and thank you very much...

"""A module of functions that reformat an input program into an operator tree. Call parse() to run the parser. PROGRAM ::= COMMANDLIST COMMANDLIST ::= COMMAND | COMMAND ; COMMANDLIST COMMAND ::= VAR = EXPRESSSION | print EXPRESSION | while EXPRESSION : COMMANDLIST end | if EXPRESSION : COMMANDLIST else COMMANDLIST end EXPRESSION ::= NUMERAL | VAR | ( EXPRESSION OPERATOR EXPRESSION ) OPERATOR is + or - NUMERAL is a sequence of digits from the set, {0,1,2,...,9} VAR is a string of lower-case letters, not a keyword The output operator trees are nested lists: PTREE ::= [ CLIST ] CLIST ::= [ CTREE+ ] where CTREE+ means one or more CTREEs CTREE ::= ["=", VAR, ETREE] | ["print", ETREE] | ["while", ETREE, CLIST] | ["if", ETREE, CTREE, CTREE] | ["call", VAR] ETREE ::= NUMERAL | VAR | [OP, ETREE, ETREE] where OP is either "+" or "-" """ ### data structures for parser: wordlist = [] # holds the remaining unread words nextword = "" # holds the first unread word # global invariant: nextword + wordlist == all remaining unread words EOF = "!" # a word that marks the end of the input words def getNextword(): """moves the front word in wordlist to nextword. If wordlist is empty, sets nextword = EOF """ global nextword, wordlist if wordlist == []: nextword = EOF else: nextword = wordlist[0] wordlist = wordlist[1:] ##### def error(message): """prints an error message and halts the parse""" print("parse error: " + message) print(nextword, wordlist) raise Exception def isVar(word): """checks whether word is a legal variable name""" # TODO # modify the KEYWORDS to include "if", "else" KEYWORDS = ("print", "while", "end", "if", "else") ans = (word.isalpha() and not (word in KEYWORDS)) return ans def parseEXPR(): """builds an ETREE from the words in nextword + wordlist, where EXPR ::= NUMERAL | VAR | ( EXPR OP EXPR ) OP is "+" or "-" and ETREE ::= NUMERAL | VAR | [OP, ETREE, ETREE] Also, maintains the global invariant (on wordlist and nextword) """ if nextword.isdigit(): # a NUMERAL ? ans = nextword getNextword() elif isVar(nextword): # a VARIABLE ? ans = nextword getNextword() elif nextword == "(": # ( EXPR op EXPR ) ? getNextword() tree1 = parseEXPR() op = nextword if op == "+" or op == "-": getNextword() tree2 = parseEXPR() if nextword == ")": ans = [op, tree1, tree2] getNextword() else: error("missing )") else: error("missing operator") else: error("illegal symbol to start an expression") return ans def parseCOMMAND(): """builds a CTREE from the words in nextword + wordlist, where COMMAND ::= VAR = EXPRESSSION | print VAR | while EXPRESSION : COMMANDLIST end | if EXPRESSION : COMMANDLIST else COMMANDLIST end and CTREE ::= ["=", VAR, ETREE] | ["print", VAR] | ["while", ETREE, CLIST] | ["if", ETREE, CTREE, CTREE] Also, maintains the global invariant (on wordlist and nextword) """ if isVar(nextword): # VARIABLE = EXPRESSION ? v = nextword getNextword() if nextword == "=": getNextword() exprtree = parseEXPR() ans = ["=", v, exprtree] else: error("missing =") elif nextword == "print": # print VARIABLE ? getNextword() exprtree = parseEXPR() ans = ["print", exprtree] elif nextword == "while": # while EXPRESSION : COMMANDLIST end ? getNextword() exprtree = parseEXPR() if nextword == ":": getNextword() else: error("missing :") cmdlisttree = parseCMDLIST() if nextword == "end": ans = ["while", exprtree, cmdlisttree] getNextword() else: error("missing end")  # TODO  # complete this part of the code here # elif nextword == "if": # if EXPRESSION : COMMANDLIST else COMMANDLIST end # getNextword() # exprtree = parseEXPR() # if nextword == ":" : # getNextword() # else : # #error(..) # clisttree1 = parseCMDLIST() # # check next word is "else" or not # # if it is, then get next word # # call parseCMDLIST() to get the tree for the else part statements # # otherwise report syntax error missing "else" # # check next word is "end" or not # # if it is: # # ans = ["if", exprtree, clisttree1, clisttree2] # # call get next word # # otherwise report error missing "end" else: # error -- bad command error("bad word to start a command") return ans def parseCMDLIST(): """builds a CLIST from the words in nextword + wordlist, where COMMANDLIST ::= COMMAND | COMMAND ; COMMANDLIST and CLIST ::= [ CTREE+ ] Also, maintains the global invariant (on wordlist and nextword) """ ans = [parseCOMMAND()] # parse first command while nextword == ";": # collect any other COMMANDS getNextword() ans.append(parseCOMMAND()) return ans def parsePROGRAM(): """builds a PTREE from nextword + wordlist, where PROGRAM ::= COMMANDLIST and PTREE ::= [ CLIST ] """ cmds = parseCMDLIST() ans = [cmds] return ans def parse(words): """reads the input program, initializes the nextword and wordlist, and builds an operator tree precondition: words is a list of strings, the words in the program postcondition: returns an operator tree for wordlist """ global wordlist # we will reset this global variable wordlist = words getNextword() # assert: global invariant for nextword and wordlist holds true here tree = parsePROGRAM() # assert: tree holds the entire operator tree for text # print "The parsed program is:" # print(tree) # print if nextword != EOF: error("there are extra words") return tree 

Step by Step Solution

There are 3 Steps involved in it

1 Expert Approved Answer
Step: 1 Unlock blur-text-image
Question Has Been Solved by an Expert!

Get step-by-step solutions from verified subject matter experts

Step: 2 Unlock
Step: 3 Unlock

Students Have Also Explored These Related Databases Questions!