首页 > 解决方案 > 在 python 中实现微型语言解析器时的问题

问题描述

我希望是否有人可以帮助我实现微型语言解析器。我试图实现小语言的语法(附照片)小语言语法,但我在某些功能上遇到了一些问题;它们是simple_exp,exp,factor,term。这些函数我已经根据语法在其中实现了一些代码,但它一直输出输出错误错误。这是解析器的代码,我把它放在一个列表中,这样我就可以控制里面的元素

import scanner3


def program(l):
    if len(l) > 1:
        if l[len(l) - 1].value is ";":
            print("ERROR.. semi colon at last line")
            return False

        return stmt_seq(l)

    else:
        print("minimum num of expressions is not met")
        return False


def stmt_seq(l):
    if stmt(l):
        if l[0].value is ";":
            l.remove(l[0])
            return stmt(l)
    else:
        print("hiiio")
        return False


def stmt(l):
    if if_stmt(l):
        print("hi1")
        return True
    elif repeat_stmt(l):
        print("hi2")
        return True
    elif assign_stmt(l):
        print("hi3")
        return True
    elif read_stmt(l):
        print("hi4")
        return True
    elif write_stmt(l):
        print("hi5")
        return True
    else:
        return False


def if_stmt(l):
    if l[0].value == "IF":
        l.remove(l[0])
        exp(l)
        if l[0].value == "THEN":
            l.remove(l[0])
            stmt_seq(l)
            if l[0].value is "END":
                l.remove(l[0])
                return True
            elif l[0].value is "ELSE":
                l.remove(l[0])
                stmt_seq(l)
                if l[0].value is "END":
                    l.remove(l[0])
                    return True
                else:
                    return False
        else:
            return False
    else:
        return False


def repeat_stmt(l):
    if l[0].value is not "REPEAT":
        return False
    else:
        l.remove(l[0])
        return True


def assign_stmt(l):
    if l[0].type == 'var' and len(l) > 1:
        if l[1].value == ":=":
            l.remove(l[0])
            l.remove(l[1])
            # return exp(l)
            return True

        return False


def read_stmt(l):
    if l[0].value == 'READ' and len(l) > 1:
        if l[1].type is "var":
            l.remove(l[0])
            l.remove(l[1])
            return True
        else:
            print("ERROR is in read in line " + str(l[0].line_no))
            return False

    else:
        return False


def write_stmt(l):
    if l[0].value == "WRITE":
        l.remove(l[0])
        # return exp(l)
        return True
    return False


def exp(l):
    # for wa7da in list(tokens.queue):
    #     print(wa7da.value, ", ", wa7da.type, "  in line ", wa7da.line_no)
    # print("________")
    if simple_exp(l):
        if comparison_op(l)and simple_exp(l):
            return True
    return False


def comparison_op(l):
    print("compaaaaare "+l[0].value)
    if l[0].value is "<" or l[0].value is ">" or l[0].value is "=":
        l.remove(l[0])
        return True
    else:
        print("ERROR is in comparison in line " + str(l[0].line_no))
        return False


def simple_exp(l):
    if l[0].value is "+" or l[0].value is "-":
        return term(1)
        return True
    else:
        return False

    # return term(l)
    # if term(l):
    #     if add_op(l):
    #         return term(l)
    #     return True
    # else:
    #     return False


def add_op(l):
    if l[0].value is "+" or l[0].value is "-":
        l.remove(l[0])
        return True
    else:
        print("ERROR is in add in line "+str(l[0].line_no))
        return False


def term(l):
    if l[0].value is "*" or l[0].value is "/":
        mul_op(1)
        return True
    return factor(l)
    # if factor(l):
    #     if mul_op(l):
    #         return factor(l)
    #     return True
    # else:
    #     return False


def mul_op(l):
    if l[0].value is "*" or l[0].value is "/":
        l.remove(l[0])
        return True
    else:
        print("ERROR is in mul in line "+str(l[0].line_no))
        return False


def factor(l):
    print(l[0].value)
    if l[0].value == "(":
        l.remove(l[0])
        exp(l)
        if l[0].value == ")":
            l.remove(l[0])
            return True

    elif l[0].type == "num":
        l.remove(l[0])
        return True
    elif l[0].type == "var":
        l.remove(l[0])
        return True
    else:
        print("ERROr is in factor in line "+str(l[0].line_no))
        return False


# #####main
tokens = scanner3.tagheez("res.txt").tokenz
for wa7da in tokens:
    print(wa7da.value, ", ", wa7da.type, "  in line ", wa7da.line_no)

print(program(tokens))

标签: pythonparsing

解决方案


您的问题是您的代码中有多个位置传递数字1而不是令牌列表l。例如:

def simple_exp(l):
    if l[0].value is "+" or l[0].value is "-":
        return term(1)

… 和:

def term(l):
    if l[0].value is "*" or l[0].value is "/":
        mul_op(1)

您的所有函数都希望获得一个标记列表l,而不是数字。他们中的一个人第一次尝试做l[0].value或类似的时候l是 number 1,它会准确地引发你所询问的异常:

TypeError: 'int' object has no attribute '__getitem__'

我不知道这些错字中的哪一个是导致您的特定问题的错字,但这没关系;你显然需要修复所有这些。

而且,正如 Rory Daulton 在第一条评论中所建议的那样,这正是l变量名糟糕的原因。如果您的变量被调用tokenslst几乎其他任何东西,您可以立即判断这1是一个错误,但因为它l看起来几乎与 相同1,所以即使在向您指出问题后您也看不到问题。

当然,您的代码中还有其他错误(例如,l.remove(l[0])随后l.remove(l[1])将删除第一个和第三个元素,而不是前两个元素,并且在更深层次上,您term根本不是在检查一个术语,它只是在检查a mul_op),但这是阻止你的那个。


推荐阅读