Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Интерпретатор кода на Python 
:(
    Опции темы
mrprim
Дата 29.6.2016, 15:38 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 7.6.2016

Репутация: нет
Всего: нет



Добрый день столкнулся с написанием интерпретатора для своей ВМ(виртуальной машины) нашел код и немного его осмыслил, понял как работает словарь и парсер, но не совсем понял как работает описание 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 файл для теста виртуальной машины. Кто подскажет как это сделать не в быдл варианте а для использование(тоесть передача полученных значение в стек ВМ)

PM MAIL   Вверх
mrprim
Дата 1.7.2016, 10:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 7.6.2016

Репутация: нет
Всего: нет



ап
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Python: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1147 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.