Я должен перевести лексический анализатор кода в Sebesda's Concpets of Programming Languages (глава 4, раздел 2) на python. Вот что у меня есть до сих пор:
# Character classes #
LETTER = 0
DIGIT = 1
UNKNOWN = 99
# Token Codes #
INT_LIT = 10
IDENT = 11
ASSIGN_OP = 20
ADD_OP= 21
SUB_OP = 22
MULT_OP = 23
DIV_OP = 24
LEFT_PAREN = 25
RIGHT_PAREN = 26
charClass = ''
lexeme = ''
lexLen = 0
token = ''
nextToken = ''
### lookup - function to lookup operators and parentheses ###
### and return the token ###
def lookup(ch):
def left_paren():
addChar()
globals()['nextToken'] = LEFT_PAREN
def right_paren():
addChar()
globals()['nextToken'] = RIGHT_PAREN
def add():
addChar()
globals()['nextToken'] = ADD_OP
def subtract():
addChar()
globals()['nextToken'] = SUB_OP
def multiply():
addChar()
globals()['nextToken'] = MULT_OP
def divide():
addChar()
globals()['nextToken'] = DIV_OP
options = {')': right_paren, '(': left_paren, '+': add,
'-': subtract, '*': multiply , '/': divide}
if ch in options.keys():
options[ch]()
else:
addChar()
### addchar- a function to add next char to lexeme ###
def addChar():
#lexeme = globals()['lexeme']
if(len(globals()['lexeme']) <=98):
globals()['lexeme'] += nextChar
else:
print("Error. Lexeme is too long")
### getChar- a function to get the next Character of input and determine its character class ###
def getChar():
globals()['nextChar'] = globals()['contents'][0]
if nextChar.isalpha():
globals()['charClass'] = LETTER
elif nextChar.isdigit():
globals()['charClass'] = DIGIT
else:
globals()['charClass'] = UNKNOWN
globals()['contents'] = globals()['contents'][1:]
## getNonBlank() - function to call getChar() until it returns a non whitespace character ##
def getNonBlank():
while nextChar.isspace():
getChar()
## lex- simple lexical analyzer for arithmetic functions ##
def lex():
globals()['lexLen'] = 0
getNonBlank()
def letterfunc():
globals()['lexeme'] = ''
addChar()
getChar()
while(globals()['charClass'] == LETTER or globals()['charClass'] == DIGIT):
addChar()
getChar()
globals()['nextToken'] = IDENT
def digitfunc():
globals()['lexeme'] = ''
addChar()
getChar()
while(globals()['charClass'] == DIGIT):
addChar()
getChar()
globals()['nextToken'] = INT_LIT
def unknownfunc():
globals()['lexeme'] = ''
lookup(nextChar)
getChar()
lexDict = {LETTER: letterfunc, DIGIT: digitfunc, UNKNOWN: unknownfunc}
if charClass in lexDict.keys():
lexDict[charClass]()
print('The next token is: '+ str(globals()['nextToken']) + ' The next lexeme is: ' + globals()['lexeme'])
with open('input.txt') as input:
contents = input.read()
getChar()
lex()
while contents:
lex()
Я использую строку sum + 1 / 33
в качестве примера входной строки. Насколько я понимаю, первый вызов getChar() на верхнем уровне устанавливает characterClass в LETTER и contents
в um + 1 / 33
.
Затем программа входит в цикл while и вызывает lex()
. lex()
, в свою очередь, накапливает сумму слов в lexeme
. Когда цикл while внутри letterfunc
встречает первый символ пробела, он прерывается, выходя из lex()
Поскольку contents
не пусто, программа снова проходит цикл while на верхнем уровне. На этот раз вызов getNonBlank()
внутри lex()
«выбрасывает пробелы в contents
и повторяется тот же процесс, что и раньше.
Где я встречаю ошибку, так это в последней лексеме. Мне сказали, что globals()['contents'][0]
находится вне диапазона, когда звонит getChar()
. Я не ожидаю, что будет сложно найти ошибку, но я пытался отследить ее вручную и, похоже, не смог обнаружить проблему. Любая помощь будет принята с благодарностью.