Кодировать программу с использованием только рекурсивных списков очень сложно и утомительно. Такая тяжелая работа должна выполняться компьютерами. Первая задача, которую мы должны преодолеть, заключается в том, что мы каким-то образом превращаем читаемый код программы в структуру, которая может быть легко обработана интерпретатором. Символы, слова и значения должны быть разделены на небольшие значимые структуры, которые называются токенами. В этом посте мы преобразуем это:
a=1;
к этому:
[["name","a"], ["eq",], ["number",1], ["semi",";"]]
[«Имя», «А»] – это токен, как [Тип, значение]. В настоящее время нам не нужно создавать класс токенов ради простоты.
Предупреждение: приведенный ниже код не проверяется на случаи краев. Он был написан, чтобы достичь результата как можно скорее, вместо того, чтобы тратить время на попытку быть идиоматическим. Давай попробуем:
# We need a generator function that yields items of strings or lists: def gen(xs): for x in xs: yield x def tokenize(xs): isalpha=lambda x: (x>="a" and x<="z") or (x>="A" and x<="Z") or x=="_" reserved="function,set,get,print,return,if,else,for,while,break,continue".split(",") symbols={"(":"lparen",")":"rparen","{":"lcurly","}":"rcurly",",":"comma",";":"semi", :"equal"} g=gen(xs) i=next(g) tokens=[] buf="" try: while True: # Skip whitespace; while i in " \r\n\t": i=next(g); # Token starts with alphas ; if isalpha(i): # and continues with alphanumeric while isalpha(i) or i in "0123456789": buf+=i i=next(g) if buf in reserved: tokens.append( [buf,buf] ) else: tokens.append( ["name",buf] ) buf="" # We found a string; if i in "\"'": delimiter=i i=next(g) while i!=delimiter: buf+=i i=next(g) # Skip delimiter; i=next(g) tokens.append( ["string",buf] ) buf="" # We found a symbol; if i in "(){};=,": tokens.append( [symbols[i],i] ) i=next(g) # We found a number; if i in "+-0123456789": while i in "+-0123456789.e": buf+=i i=next(g) if "e" in buf or "." in buf: tokens.append( ["number",float(buf)] ) else: tokens.append( ["number",int(buf)] ) buf="" except StopIteration: pass return tokens # test it; print(tokenize("if (gt(a,b)) return a; else return b;"))
выход:
[['if', 'if'], ['lparen', '('], ['name', 'gt'], ['lparen', '('], ['name', 'a'], ['comma', ','], ['name', 'b'], ['rparen', ')'], ['rparen', ')'], ['return', 'return'], ['name', 'a'], ['semi', ';'], ['else', 'else'], ['return', 'return'], ['name', 'b'], ['semi', ';']]
Это работает: p
В следующем посте мы напишем класс анализатора, который преобразует; » к ‘[“set”, “a”, 1]’
Оригинал: “https://dev.to/smadev/lets-build-a-simple-interpreter-from-scratch-in-python-pt-10-tokenizer-1d1c”