THT DUYURU

chat
Python Artificial Intelligence’da en çok kullanılan dildir ve gerekli dökümanların paylaşım alanlar burada paylaşılmaktadır.

ugursuz reklam
takipci
Seçenekler

Python ile Interpreter Yapımı - Tokenizer - ihan3t

ihan3t - ait Kullanıcı Resmi (Avatar)
Geliştirici
Üyelik tarihi:
02/2012
Mesajlar:
5.017
Konular:
256
Teşekkür (Etti):
302
Teşekkür (Aldı):
1927
Ticaret:
(0) %
26
33416
08-08-2017 21:32
#1
Merhabalar, http://www.turkhackteam.org/off-topi...ma-ihan3t.html konusunda sorduğum sorunun cevabının bir kısmını yazmaya karar verdim.

Sorduğum soruda istediğim şey bir tokenizer (lexer) ve bir adet parser yazılmasıydı, fakat birçoğu soruyu anlamadı/çarpıttı ve istenilen cevap ortaya maalesef çıkmadı.

Bir programlama dilini kullanarak yazdığımız kod aslında belirli kurallara uyarak bir araya getirdiğimiz karakterler kümesidir.

Tokenizer, bu karakterler kümesini dilin kurallarını kullanarak interpreterın anlayacağı hale getirir.

Şimdi basit matematiksel ifadelerimizi tokenize etme işlemini yapacağız.

Yapacağımız iş,

(9*3)-1+8*5+(1-3)

şeklinde verilen bir ifadeyi tokenlara ayırmak olacak.

Tokenizer adında bir classımız olsun. Tokenlara ayırmak için verilen expression ımızı teker teker okuyup belirli bir kurala göre tokenize edeceğiz. Kuralımız ise şu, eğer matematiksel bir ifadeye rastlarsa (dört işlem sembolü veya parantez) token olarak ekle, eğer bir sayıya rastlarsa sayı devam ettiği sürece alıp bunu token olarak ekle.

Classımızın 3 adet fieldı var. Birincisi tokenize edeceğimiz expression, diğeri şuanda okuduğumuz char diğeri expressiondaki mevcut pozisyonumuz (kaçıncı karakteri okuduğumuz) sonuncusu ise operation tiplerimizi tutan dictionary tipindeki değişkenimiz. (bu değişken yerine TokenTypes gibi bir enum da tutulabilirdi, farklı şekillerde yapılabilirdi, token tiplerimiz az olduğu için ve kod yazarken kolaylık olsun diye ben dictionary seçtim)

Tokenlarımızı temsil eden classımız :

Kod:
class Token():
    type = ''
    text = ''

    def __init__(self, text, type):
        self.type = type
        self.text = text
Kod:
class Tokenizer():
    expression = ''
    currentChar = ''
    currentCharPosition = 0
Tokenize etme işlemi sırasında bir char ın operation olup olmadığına karar vereceğimiz ve eğer operation ise hangi operation olduğunu söyleyen metodu ekleyelim :

Kod:
class Tokenizer():
    expression = ''
    currentChar = ''
    currentCharPosition = 0

    opTypes = {
        '+' : 'ADD',
        '-' : 'SUBTRACT',
        '*' : 'MULTIPLY',
        '/' : 'DIVIDE',
        '(' : 'LEFT_PAREN',
        ')' : 'RIGHT_PAREN'
    }

    def isOp(self, chr):
        opList = ['+', '-', '*', '/', '(', ')']
        return True if chr in opList else False

    def findOpType(self, chr):
        return self.opTypes[chr]
Şimdi gelelim tokenize metodumuza. Asıl işi burada yapıyor olacağız.

Kod:
    def tokenize(self, resource):
        tokens = []
        token = ''
        state = 'DEFAULT'

        index = 0
        while index < len(resource):
            chr = resource[index]
            index += 1

            if state == 'DEFAULT':
                if self.isOp(chr):
                    opType = self.findOpType(chr)
                    tokens.append(Token(chr, opType))
                elif chr.isdigit():
                    token += chr
                    state = 'NUMBER'
                continue

            if state == 'NUMBER':
                if chr.isdigit():
                    token += chr
                else:
                    tokens.append(Token(token, 'NUMBER'))
                    token = ''
                    state = 'DEFAULT'
                    index -= 1
                continue

        return tokens
- Burada expressionımızdan bir karakter okuyoruz
- Başlangıçta "default" adında bir durumdayız
- Durumumuz default ise okuduğumuz karakterin operation mı yoksa sayı tipinde mi olduğuna bakıyoruz
- Eğer operation tipindeyse, hangi operation olduğunu bulup token listemize ekliyoruz
- Eğer sayı tipindeyse sayıyı token değişkenimize ekleyip, state değişkenini "number" yapıyoruz ve sayının sonuna kadar okumaya devam ediyoruz
- Sayı bitip tekrar bir operation geldiğinde state imizi tekrar değiştiriyoruz ve token oluşturma işlemine devam ediyoruz

Programı bir bütün haline getirelim :

Kod:
class Tokenizer():
    expression = ''
    currentChar = ''
    currentCharPosition = 0

    opTypes = {
        '+' : 'ADD',
        '-' : 'SUBTRACT',
        '*' : 'MULTIPLY',
        '/' : 'DIVIDE',
        '(' : 'LEFT_PAREN',
        ')' : 'RIGHT_PAREN'
    }

    def isOp(self, chr):
        opList = ['+', '-', '*', '/', '(', ')']
        return True if chr in opList else False

    def findOpType(self, chr):
        return self.opTypes[chr]

    def tokenize(self, resource):
        tokens = []
        token = ''
        state = 'DEFAULT'

        index = 0
        while index < len(resource):
            chr = resource[index]
            index += 1

            if state == 'DEFAULT':
                if self.isOp(chr):
                    opType = self.findOpType(chr)
                    tokens.append(Token(chr, opType))
                elif chr.isdigit():
                    token += chr
                    state = 'NUMBER'
                continue

            if state == 'NUMBER':
                if chr.isdigit():
                    token += chr
                else:
                    tokens.append(Token(token, 'NUMBER'))
                    token = ''
                    state = 'DEFAULT'
                    index -= 1
                continue

        return tokens

def main():
    tokenizer = Tokenizer()
    expression = "( 9 *3 )-1+8*5+(1-3)"

    tokens = tokenizer.tokenize(expression)

    for token in tokens:
        if token.type == 'NUMBER':
            print '{} ({})'.format(token.type, token.text)
        else:
            print token.type
Kodumuzu çalıştırdığımızda bize şöyle bir çıktı veriyor :

Kod:
LEFT_PAREN
NUMBER (9)
MULTIPLY
NUMBER (3)
RIGHT_PAREN
SUBTRACT
NUMBER (1)
ADD
NUMBER (8)
MULTIPLY
NUMBER (5)
ADD
LEFT_PAREN
NUMBER (1)
SUBTRACT
NUMBER (3)
RIGHT_PAREN
Tokenize edilmiş sonucumuz. Bu çok simple bir tokenizer. Bir expressionı tokenize ettikten sonra, mantığı anlayıp daha derin bilgiler edindiğinizde aslında bir programlama dili syntaxı oluşturmaya başlıyorsunuz.

Parse etme sürecini de öğrenince aslında çalışan bir programlama diliniz oluyor.

Tabii ki bu tasarlamayı yapmak için context free grammer kavramını, terminal ve non terminal değişkenleri bilmek gerekiyor.

Verdiğim örneklerden yola çıkıp kendinizi geliştirerek programlama dili keywordlerini tokenize eden bir tokenizer yazabilirsiniz artık.

Tokenize etme aşamasında çok farklı teknikler kullanılabilir, matematik dilini baz aldığımız için bu şekilde karakter bazında okuma işlemi bizim için yeterli.

Yeterli ilgi olursa parse etme işlemini ileriki zamanlarda fırsat bulursam anlatabilirim.

Herkese iyi forumlar, ihan3t.

---------------------
Computer Engineer.

Senior Software Engineer.
kenzai - ait Kullanıcı Resmi (Avatar)
Özel Üye
Üyelik tarihi:
12/2010
Nereden:
Trondheim
Mesajlar:
8.562
Konular:
1471
Teşekkür (Etti):
3844
Teşekkür (Aldı):
2741
Ticaret:
(0) %
08-08-2017 22:01
#2
eline sağlık harika anlatım
ihan3t - ait Kullanıcı Resmi (Avatar)
Geliştirici
Üyelik tarihi:
02/2012
Mesajlar:
5.017
Konular:
256
Teşekkür (Etti):
302
Teşekkür (Aldı):
1927
Ticaret:
(0) %
08-08-2017 22:38
#3
Teşekkürler. Böyle konular kimse bakmadan aşağılarda kaybolurken top 15 teki troll konuların yukarda olması çok ilginç.
---------------------
Computer Engineer.

Senior Software Engineer.
AJEXA - ait Kullanıcı Resmi (Avatar)
Tamamen Askıya Alındı
Üyelik tarihi:
06/2013
Nereden:
Jüpiter
Mesajlar:
6.914
Konular:
369
Teşekkür (Etti):
1124
Teşekkür (Aldı):
2377
Ticaret:
(0) %
08-08-2017 22:42
#4
Alıntı:
ihan3t´isimli üyeden Alıntı Mesajı göster
Teşekkürler. Böyle konular kimse bakmadan aşağılarda kaybolurken top 15 teki troll konuların yukarda olması çok ilginç.
Maalesef öyle üstad.
Eline sağlık, bi şe anlamasam da konu üstte kalsın . Anlayacak birileri illaki vardır
Phoique 7 - ait Kullanıcı Resmi (Avatar)
Yeni Üye
Üyelik tarihi:
03/2017
Nereden:
Manisa
Mesajlar:
493
Konular:
23
Teşekkür (Etti):
49
Teşekkür (Aldı):
149
Ticaret:
(0) %
08-08-2017 23:49
#5
Elinize sağlık merak ettiğim ve çözümünü bir zamanlar aradığım konuydu. Çok karışık görünüyor. Aslında kodlar çok düzenli yazılmış ama yeni başlayan biri için şahsen benim için anlamakta biraz zorluk çekmedim değil
---------------------
JavaScript Developer
CyberNeeG - ait Kullanıcı Resmi (Avatar)
Tamamen Askıya Alındı
Üyelik tarihi:
01/2016
Nereden:
777
Mesajlar:
1.157
Konular:
48
Teşekkür (Etti):
163
Teşekkür (Aldı):
158
Ticaret:
(0) %
08-08-2017 23:55
#6
Eline sağlık üstad.
osm4nl1evl4d1 - ait Kullanıcı Resmi (Avatar)
Hevesli Üye
Üyelik tarihi:
03/2017
Nereden:
T Ü R K
Mesajlar:
4.761
Konular:
200
Teşekkür (Etti):
1123
Teşekkür (Aldı):
1313
Ticaret:
(0) %
09-08-2017 00:01
#7
elinize sağlık cevabımı aldım
DeSTuRSuZz_ - ait Kullanıcı Resmi (Avatar)
Yazılımcı
Üyelik tarihi:
12/2015
Nereden:
Kocaeli
Yaş:
9
Mesajlar:
3.583
Konular:
346
Teşekkür (Etti):
807
Teşekkür (Aldı):
1073
Ticaret:
(0) %
09-08-2017 00:12
#8
Eline Sağlık Ümstat
---------------------
I can check your fortune telling with python
'Taipan - ait Kullanıcı Resmi (Avatar)
İstihbaratçı
Üyelik tarihi:
06/2015
Mesajlar:
3.854
Konular:
87
Teşekkür (Etti):
903
Teşekkür (Aldı):
1398
Ticaret:
(0) %
09-08-2017 00:12
#9
Çok güzel ihracatlar yapıyorsun eline sağlık
---------------------
Man In The Middle

#Kalbimizdesin Solo-Türk


siberdrone15 - ait Kullanıcı Resmi (Avatar)
Hevesli Üye
Üyelik tarihi:
08/2016
Mesajlar:
4.440
Konular:
526
Teşekkür (Etti):
1785
Teşekkür (Aldı):
781
Ticaret:
(0) %
09-08-2017 00:17
#10
Eline sağlık
Garfes Teşekkür etti.

Bookmarks


« Önceki Konu | Sonraki Konu »
Seçenekler