Добрый день столкнулся с написанием интерпретатора для своей ВМ(виртуальной машины) нашел код и немного его осмыслил, понял как работает словарь и парсер, но не совсем понял как работает описание if else for while и других нужных мне циклов, тут уже описан If elseif но я не понимаю. Может кто нибудь либо прокоментить уже готовый If else elseif или написать тоже самое для While с коментариями что бы можно было разобраться. Код | keyword_dic = { 'if': TOKENIZER_IF, 'then': TOKENIZER_THEN, 'else': TOKENIZER_ELSE, 'endif': TOKENIZER_ENDIF, 'while': TOKENIZER_WHILE, 'do': TOKENIZER_DO, 'print': TOKENIZER_PRINT, 'rem': TOKENIZER_REM, '\n': TOKENIZER_CR, '+': TOKENIZER_PLUS, '-': TOKENIZER_MINUS, '*': TOKENIZER_ASTR, '/': TOKENIZER_SLASH, '%': TOKENIZER_MOD, '(': TOKENIZER_LEFTPAREN, ')': TOKENIZER_RIGHTPAREN, '=': TOKENIZER_SET, }
class Tokenizer(object): def __init__(self, progstr): self.prog=progstr self.end_of_prog=len(progstr) self.ptr=0 self.nextptr=0 self.token=self.get_next_token() def get_next_token(self): if self.ptr == self.end_of_prog: return TOKENIZER_ENDOFINPUT if self.prog[self.ptr].isdigit(): i=1 while i<MAX_NUMLEN and self.ptr+i<self.end_of_prog and self.prog[self.ptr+i].isdigit(): i+=1 if i==MAX_NUMLEN: return TOKENIZER_ERROR self.nextptr=self.ptr+i return TOKENIZER_NUMBER token=None for k in keyword_dic.keys(): if self.prog[self.ptr:self.ptr+len(k)]==k: token=keyword_dic[k] self.nextptr=self.ptr+len(k) break if token==TOKENIZER_SET: if self.prog[self.nextptr]=='=': token=TOKENIZER_EQ self.nextptr+=1 if token: return token if self.prog[self.ptr]=='"': self.nextptr=self.ptr+1 while self.prog[self.nextptr]!='"': self.nextptr+=1 if self.nextptr==self.end_of_prog: return TOKENIZER_ERROR self.nextptr+=1 return TOKENIZER_STRING if self.prog[self.ptr]>='a' and self.prog[self.ptr]<='z': self.nextptr=self.ptr+1 return TOKENIZER_VARIABLE return TOKENIZER_ERROR def finished(self): return (self.ptr==self.end_of_prog or self.token==TOKENIZER_ENDOFINPUT) def nextt(self): if self.finished(): return self.ptr=self.nextptr while self.ptr<self.end_of_prog and (self.prog[self.ptr]==' ' or self.prog[self.ptr]=='\t'): self.ptr+=1 self.token=self.get_next_token() if self.token==TOKENIZER_REM: while not (self.prog[self.nextptr]=='\n' or self.finished()): self.nextptr+=1 if self.prog[self.nextptr]=='\n': self.nextptr+=1 self.nextt() def num(self): return int(self.prog[self.ptr:self.nextptr]) def varnum(self): return (ord(self.prog[self.ptr])-ord('a')) class Programm(object): def __init__(self, prog): self.var=[0 for i in range(26)] self.tok=Tokenizer(prog) self.if_stack=[] self.byte_code=[] def accept(self, token): if self.tok.token!=token: print "error" sys.exit(1) self.tok.nextt() def statement(self): #print "token=", self.tok.token if self.tok.token==TOKENIZER_VARIABLE: #print "token setvar" vnum=self.tok.varnum() self.tok.nextt() self.accept(TOKENIZER_SET) self.var[vnum]=self.expr() self.byte_code.append(pop_var) self.byte_code.append(vnum) elif self.tok.token==TOKENIZER_IF: self.if_statement() elif self.tok.token==TOKENIZER_ELSE: self.else_statement() elif self.tok.token==TOKENIZER_ENDIF: self.endif_statement() #elif self.tok.token=TOKENIZER_WHILE: # self.while_statement() # elif self.tok.token=TOKENIZER_DO: # self.do_statement() else: self.tok.nextt() def if_statement(self): #print "token if" self.accept(TOKENIZER_IF) r=self.expr() self.accept(TOKENIZER_THEN) self.byte_code.append(jz) cp=len(self.byte_code) self.byte_code.append(nop) self.if_stack.append(cp) def else_statement(self): #print "token else" self.accept(TOKENIZER_ELSE) self.byte_code.append(jmp) cp=len(self.byte_code) self.byte_code.append(nop) cp1=self.if_stack.pop() self.byte_code[cp1]=cp+1 self.if_stack.append(cp) def endif_statement(self): #print "token endif" self.accept(TOKENIZER_ENDIF) cp1=self.if_stack.pop() cp=len(self.byte_code) self.byte_code[cp1]=cp def expr(self): t1=self.term() op=self.tok.token while (op==TOKENIZER_PLUS or \ op==TOKENIZER_MINUS or \ op==TOKENIZER_AND or \ op==TOKENIZER_OR): self.tok.nextt() t2=self.term() if op==TOKENIZER_PLUS: t1+=t2 self.byte_code.append(plus) elif op==TOKENIZER_MINUS: t1-=t2 self.byte_code.append(minus) elif op==TOKENIZER_AND: t1=t1 and t2 elif op==TOKENIZER_OR: t1=t1 or t2 op=self.tok.token return t1 def term(self): f1=self.factor() op=self.tok.token while (op==TOKENIZER_ASTR or \ op==TOKENIZER_SLASH or \ op==TOKENIZER_MOD): self.tok.nextt() f2=self.factor() if op==TOKENIZER_ASTR: f1*=f2 self.byte_code.append(mult) elif op==TOKENIZER_SLASH: f1/=f2 self.byte_code.append(div) elif op==TOKENIZER_MOD: f1%=f2 op=self.tok.token return f1 def factor(self): token=self.tok.token sign=1 if self.tok.token==TOKENIZER_MINUS: sign=-1 self.tok.nextt() if self.tok.token==TOKENIZER_NUMBER: r=self.tok.num() r*=sign self.tok.nextt() self.byte_code.append(push_num) self.byte_code.append(r) elif self.tok.token==TOKENIZER_LEFTPAREN: self.tok.nextt() r=self.expr() r*=sign if self.tok.token==TOKENIZER_RIGHTPAREN: self.tok.nextt() else: return 1 else: r=self.varfactor() r*=sign if sign==-1: self.byte_code.append(push_num) self.byte_code.append(sign) self.byte_code.append(mult) return r def varfactor(self): varnum=self.tok.varnum() r=self.var[varnum] self.byte_code.append(push_var) self.byte_code.append(varnum) if self.tok.token==TOKENIZER_VARIABLE: self.tok.nextt() return r test_str = "a=(1+2)*1/3" def main(): p=Programm(test_str) while not p.tok.finished(): p.statement() cp=0 end=len(p.byte_code) f = open('testvm.txt', 'w') print "byte code len = ", end while cp<end: if p.byte_code[cp]==push_num: num=p.byte_code[cp+1] print "push_num ", num f.write('PUSH, '+ str(num) + ', ') cp+=2 elif p.byte_code[cp]==push_var: vnum=p.byte_code[cp+1] print "push_var ", chr(ord('a')+vnum) f.write('push_var, ' + str(vnum) + ', ') cp+=2 elif p.byte_code[cp]==pop_var: vnum=p.byte_code[cp+1] print "pop_var ", chr(ord('a')+vnum) f.write('pop_var, ' + str(vnum) + ', ') cp+=2 elif p.byte_code[cp]==plus: print "plus" f.write('ADD, ') cp+=1 elif p.byte_code[cp]==minus: print "minus" f.write('SUB, ') cp+=1 elif p.byte_code[cp]==mult: print "mult" f.write('MULT, ') cp+=1 elif p.byte_code[cp]==div: print "div" f.write('DIV, ') cp+=1 elif p.byte_code[cp]==jmp: ncp=p.byte_code[cp+1] print "jmp ", ncp f.write('JMP, ' + str(ncp) + ', ') cp+=2 elif p.byte_code[cp]==jz: ncp=p.byte_code[cp+1] print "jz ", ncp f.write('JZ, ' + str(ncp) + ', ') cp+=2 return 0
|
так же в самом мейне я описал перевод получиного байт кода в txt файл для теста виртуальной машины. Кто подскажет как это сделать не в быдл варианте а для использование(тоесть передача полученных значение в стек ВМ)
|