Построение лексического анализатора, индекс строки вне диапазона во время цикла, - PullRequest
1 голос
/ 18 октября 2019

Вступление: Я учусь делать свой собственный язык и делаю шаги, необходимые для этого. Я пытался внедрить Lexical Analyzer, но получаю сообщение об ошибке, хотя моя логика верна. Я хочу, чтобы Программа не читала комментарий.

Проблема: Я получаю сообщение об ошибке «Строковый индекс выходит за пределы диапазона», когда я пытаюсь перебрать слова и искать «\ n 'в строке комментария.

Код Python:

comment = ['//', '/*', '*/']
keyw = ["main", "void"]
br = ['(', ')', '{', '}']
lineCount = 1
temp = ''
flag = False
f = open('Program.C', 'r')
Program = f.read()
#print(Program)

for c in range(len(Program)):
    if Program[c] == ' ':
        continue
    if Program[c] == '\n':
        lineCount = lineCount + 1
        continue
    if Program[c] == '/':
        c = c + 1
        if Program[c] == '/':
            c = c + 1
            while Program[c] != '\n':
                c = c +1
    if Program[c] in br:
        print(lineCount, "Brackets", Program[c])
    else:
        temp = temp + Program[c]
        print(temp)
        if temp in keyw:
            print(lineCount, "Keyword", temp)
            temp = ''
    print(Program[c])

Вывод:

while Program[c] != '\n':
IndexError: string index out of range
 S
S
 Sa
a
 Saa
a
 Saad
d
Process finished with exit code 1

Пример входного файла:

// Saad
// Bhai

1 Ответ

1 голос
/ 19 октября 2019

Помимо ответа на ваш настоящий вопрос, я также хотел бы дать вам несколько советов по улучшению вашего кода Python.

Ваш актуальный вопрос: Ваша вторая строка не заканчивается на \n

Ответом на вашу реальную проблему является то, что ваш файл не заканчивается новой строкой \n.

Хотя это естественное предположение, что каждая строка делает, может быть одно исключение: последняя строка вашего файла. При разборе второй строки вашего файла ваш цикл while продолжает поиск символа \n, но не находит его, поскольку ваш файл просто заканчивается после i.

Это можно подтвердить с помощьюраспечатка всех прочитанных символов:

>>> f = open('Program.C')
>>> print(list(f.read()))
['/', '/', ' ', 'S', 'a', 'a', 'd', '\n', '/', '/', ' ', 'B', 'h', 'a', 'i']
                                    ^^^^                                    ^^^^
                               endline here                         but not here!

Таким образом, вместо того, чтобы найти символ \n, который ищет ваш цикл while, ваша переменная c увеличивается до величины, превышающей длину ввода вашего файла, вызывая IndexError: string index out of range, с которым вы столкнулись.

Простым решением было бы изменить цикл while на

while c < len(Program) and Program[c] != '\n':

Улучшение вашего Python

Соглашения об именах

Имена, начинающиеся с заглавной буквы, обычно зарезервированы для классов, поэтому Program должно быть program. Также обычно избегают использования CamelCase, поэтому lineCount становится line_count

Открытие файлов в Python: with open(file) as f:

Когда вы open создаете файл самостоятельно в Python, вам также следует close Это. Поскольку это раздражает, у Python есть with -статист, который автоматически закрывает его, как только вы оставляете петли

with open(filename) as f:
    # file I/O

# file itself no longer needed

for в Python

Любой тип последовательности в Pythonимеет встроенную поддержку итераций. Вместо ручной индексации вы можете напрямую получить доступ к нужному элементу. Сравните с my_list = [1, 4, 9]:

for i in range(len(my_list)):
    print(my_list[i])

с

for item in my_list:
    print(item)

Если вам все еще нужен индекс, вы можете использовать enumerate:

for i, item in enumerate(my_list):
    print(i, item)

Итерацииповерх файлов

Помимо чтения файла и итерации по каждому символу в строке, Python также поддерживает итерацию по файлам построчно:

with open(filename) as file:
    # making use of enumerate()
    for line_num, line in enumerate(file, start=1):
        print(line_num, line)

Моя версия

Это то, что я бы сделал из кода, который вы опубликовали, хотя, если вы углубитесь в синтаксический анализ, это может быть не лучшим решением в будущем (вероятно, не будет на самом деле). Это может быть полезной ссылкой как более «питонная» версия вашего размещенного кода.

with open('program.C', 'r') as file:
    for line_count, line in enumerate(file, start=1):
        line = line.lstrip(' ')

        if line.startswith('//'):
            continue

        for character in line.rstrip('/n'):
            if character in br:
                print(line_count, "Brackers", character)
            else:
                temp += character
                print(temp)
                if temp in keywords:
                    print(line_count, "Keyword", temp)
                    temp = ''
...