这是我当前的 Python 解释器,它使用解析规则来获取输入,然后打印出表达式。解释器工作正常,但我想对我当前的语法规则进行某些更改并将其添加到新的语法规则中。到目前为止,我只能得到一些我想要的语法更改。
这是我想从我当前的语法中做出的改变:
# <stmt-list> ::= empty | <stmt> <stmt-list>
to
# <stmt_list> ::= <stmt> | <stmt> <stmt_list>
# <factor> ::= id | intnum | ( <expr> )
to
# <base> ::= (<expr>) | id | number
<stmt> ::= id = <expr> ; | print <expr>;
to
<stmt> ::= id = <expr> ; | iprint <expr> ; | rprint <expr> ;
另外我不确定如何在我的解释器中实现下面的新语法规则,我想我可能已经有了它们?
<prog> ::= <decl_list> <stmt_list>
<decl-list> ::= <decl> | <decl> <decl_list>
<decl> ::= <type> <id_list> ;
<type> ::= int | real
<id_list> ::= id | id {, <id_list>}
这是我当前语法的当前代码:
import sys
global varTable
varTable = {}
def main():
global itProgram, nextToken, nextChar, nextLex, flagEof, strStmt
nextToken = ""
nextChar = ""
flagEof = False
strStmt = ""
try:
fileProgram = open(sys.argv[1], "rt")
except IndexError:
print "Missing input file!"
return
except IOError:
print "Could not open \'" + sys.argv[1] + "\'!"
return
strProgram = fileProgram.read()
itProgram = iter(strProgram)
if strProgram == "":
nextChar = ""
else:
nextChar = itProgram.next()
#while not flagEof:
funcLex()
stmtList()
def funcLex():
global itProgram, nextToken, nextLex, nextChar, flagEof, strStmt
nextToken = ""
nextLex = ""
isFloat = False
try:
while nextChar.isspace():
nextChar = itProgram.next()
except StopIteration:
nextChar = ""
funcLex()
return
try:
if nextChar == "(":
nextToken = "LPARA"
nextLex = nextChar
nextChar = itProgram.next()
elif nextChar == ")":
nextToken = "RPARA"
nextLex = nextChar
nextChar = itProgram.next()
elif nextChar == "+":
nextToken = "ADD"
nextLex = nextChar
nextChar = itProgram.next()
elif nextChar == "-":
nextToken = "SUB"
nextLex = nextChar
nextChar = itProgram.next()
elif nextChar == "*":
nextToken = "MULT"
nextLex = nextChar
nextChar = itProgram.next()
elif nextChar == "/":
nextToken = "DIV"
nextLex = nextChar
nextChar = itProgram.next()
elif nextChar == "=":
nextToken = "ASSIGN"
nextLex = nextChar
nextChar = itProgram.next()
elif nextChar == ";":
nextToken = "SEMI"
nextLex = nextChar
nextChar = itProgram.next()
elif nextChar.isalpha():
nextLex = nextChar
nextChar = itProgram.next()
while nextChar.isalnum():
nextLex += nextChar
nextChar = itProgram.next()
if nextLex == "print":
nextToken = "PRINT"
else:
nextToken = "ID"
elif nextChar.isalnum():
nextLex = nextChar
nextChar = itProgram.next()
while nextChar.isalnum() or nextChar == ".":
if nextChar == ".":
isFloat = True
nextLex += nextChar
nextChar = itProgram.next()
if isFloat:
nextToken = "FLOAT"
else:
nextToken = "INT"
elif nextChar == "":
nextLex = nextChar
nextToken = "EMPTY"
flagEof = True
else:
nextToken = "UNKNOWN"
#print "Syntax error!"
except StopIteration:
nextChar = ""
strStmt = strStmt + nextLex + " "
if nextToken == "SEMI":
print strStmt
strStmt = ""
# <stmt-list> ::= empty | <stmt> <stmt-list>
def stmtList():
global nextToken
if nextToken == "EMPTY":
print ">>> Empty .tiny file."
else:
while nextToken != "EMPTY":
stmt()
# <stmt> ::= id = <expr> ; |
# print <expr> ;
def stmt():
global nextToken, nextLex
if nextToken == "ID":
varName = nextLex
funcLex()
if nextToken == "ASSIGN":
funcLex()
result = expr()
if result[1] != "UNKNOWN":
lookupVarTable(varName, result[0], result[1])
else:
printError("undefined variable.")
elif nextToken == "PRINT":
funcLex()
result = expr()
if result[1] != "UNKNOWN" and nextToken == "SEMI":
print ">>> " + str(result[0])
elif result[1] == "UNKNOWN":
printError("undefined variable.")
else:
printError("<stmt> syntax error.")
return
if nextToken == "SEMI":
funcLex()
else:
printError("<stmt> missing ';'")
# <expr> ::= <term> { + <term> | - <term> }
def expr():
global nextToken, nextLex
lResult = term()
while nextToken == "ADD" or nextToken == "SUB":
operator = nextToken
funcLex()
rResult = term()
#Variable is not defined
if lResult[1] == "UNKNOWN" or rResult[1] == "UNKNOWN":
printError("Undefined variable!")
if lResult[1] != rResult[1]: #type mismatch
printError("Type mismatch!")
elif operator == "ADD":
lResult = (lResult[0]+rResult[0], lResult[1])
else:
lResult = (lResult[0]-rResult[0], lResult[1])
return lResult
# <term> ::= <factor> { * <factor> | / <factor> }
def term():
global nextToken, nextLex
lResult = factor()
while nextToken == "MULT" or nextToken == "DIV":
operator = nextToken
funcLex()
rResult = factor()
#Variable is not defined
if lResult[1] == "UNKNOWN" or rResult[1] == "UNKNOWN":
printError("Undefined variable!")
if lResult[1] != rResult[1]: #type mismatch
printError("Type mismatch!")
elif operator == "MULT":
lResult = (lResult[0]*rResult[0], lResult[1])
else:
lResult = (lResult[0]/rResult[0], lResult[1])
return lResult
# <factor> ::= id | intnum | ( <expr> )
def factor():
global nextToken, nextLex
if nextToken == "ID":
result = lookupVarTable(nextLex, 0, "UNKNOWN")
funcLex()
elif nextToken == "INT":
result = (int(nextLex), "INT")
funcLex()
elif nextToken == "FLOAT":
result = (float(nextLex), "FLOAT")
funcLex()
elif nextToken == "LPARA":
funcLex()
result = expr()
if nextToken == "RPARA":
funcLex()
else:
printError("<factor>")
return result
def printError(strMessage):
global strStmt
if strStmt != "":
print strStmt
print ">>> Error: " + strMessage
exit()
def lookupVarTable(varName, varValue, varType):
#if varName not in varTable:
# varValue == "UNKNOWN"
if varType != "UNKNOWN":
varTable[varName] = (varValue, varType)
return varTable[varName]
elif varName in varTable:
return varTable[varName]
else:
return (varValue, varType)
if __name__ == "__main__":
main()