проблемы при реализации крошечного парсера языка в python - PullRequest
0 голосов
/ 13 мая 2018

Я надеялся, что кто-нибудь сможет мне помочь в реализации крошечного парсера языка. я пытался реализовать грамматику крошечного языка (прилагается фотография) grammar of tiny language, но у меня есть некоторые проблемы с некоторыми функциями; которые просты, например, 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 голосов
/ 13 мая 2018

Ваша проблема в том, что в вашем коде есть несколько мест, где вы передаете число 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__'

Я не знаю, какой из этих опечаток вызвал вашу конкретную проблему, но это не имеет значения; вам, очевидно, нужно исправить все из них.

И, как предположил Рори Даултон в первом комментарии, именно поэтому l является ужасным именем переменной. Если бы ваша переменная называлась tokens или lst или почти что-нибудь еще, вы могли бы сразу сказать, что 1 была ошибкой, но, поскольку она l, которая выглядит почти идентично 1, вы не можете видеть проблема даже после того, как она была указана вам.

Конечно, у вас есть и другие ошибки в вашем коде (например, l.remove(l[0]), за которым следует l.remove(l[1]), удалит первый и третий элементы, а не первые два, и, на более глубоком уровне, ваш term isn ' вообще не проверяю термин, это просто проверяет mul_op), но именно он блокирует вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...