-2

これは、構文解析規則を使用して入力を取得し、式を出力する現在の 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()
4

1 に答える 1