在python

时间:2018-05-12 21:44:10

标签: python parsing

我希望有人可以帮助我实现小语言解析器。我试图实现小语言的语法(附图)grammar of tiny language,但我对某些功能有一些问题;这是simple_exp,exp,factor,term。这些函数我已经基于语法在其中实现了一些代码,但它不断输出output errors错误。这里是解析器的代码,我把它放在一个列表中,这样我就可以控制它里面的元素了

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))

1 个答案:

答案 0 :(得分:0)

您的问题是您的代码中有多个位置,您传递的数字为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时,其中一个人第一次尝试1或类似时,它会提出您所询问的异常:

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

我不知道哪个拼写错误导致你的特定问题,但这并不重要;你显然需要修复所有这些。

而且,正如Rory Daulton在第一篇评论中所建议的那样,这正是为什么l是一个可怕的变量名称。如果您的变量被称为tokenslst或几乎任何其他变量,您可以立即告诉1是一个错误,但因为它是l,它看起来几乎与1相同{1}},即使有人向你指出问题,你也看不到问题。

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