İPUCU

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

Seçenekler

Python ile Interpreter Yapımı - Tokenizer - ihan3t

ihan3t - ait Kullanıcı Resmi (Avatar)
Üye
Üyelik tarihi:
02/2012
Mesajlar:
5.005
Konular:
255
Teşekkür (Etti):
291
Teşekkür (Aldı):
1831
Ticaret:
(0) %
08-08-2017 21:32
#1
Python ile Interpreter Yapımı - Tokenizer - ihan3t
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)
Co-Admin Yrd.
Üyelik tarihi:
12/2013
Mesajlar:
8.449
Konular:
1446
Teşekkür (Etti):
3792
Teşekkür (Aldı):
2423
Ticaret:
(0) %
08-08-2017 22:01
#2
eline sağlık harika anlatım
ihan3t - ait Kullanıcı Resmi (Avatar)
Üye
Üyelik tarihi:
02/2012
Mesajlar:
5.005
Konular:
255
Teşekkür (Etti):
291
Teşekkür (Aldı):
1831
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 Forumdan Uzaklaştırıldı
Üyelik tarihi:
06/2013
Nereden:
Jüpiter
Mesajlar:
6.942
Konular:
372
Teşekkür (Etti):
1145
Teşekkür (Aldı):
2470
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)
Üye
Üyelik tarihi:
03/2017
Mesajlar:
462
Konular:
23
Teşekkür (Etti):
37
Teşekkür (Aldı):
139
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 Forumdan Uzaklaştırıldı
Üyelik tarihi:
01/2016
Nereden:
777
Mesajlar:
1.158
Konular:
48
Teşekkür (Etti):
169
Teşekkür (Aldı):
156
Ticaret:
(0) %
08-08-2017 23:55
#6
Eline sağlık üstad.
osm4nl1evl4d1 - ait Kullanıcı Resmi (Avatar)
Tamamen Forumdan Uzaklaştırıldı
Üyelik tarihi:
03/2017
Nereden:
T Ü R K
Mesajlar:
4.256
Konular:
194
Teşekkür (Etti):
791
Teşekkür (Aldı):
1005
Ticaret:
(0) %
09-08-2017 00:01
#7
elinize sağlık cevabımı aldım
DeSTuRSuZz_ - ait Kullanıcı Resmi (Avatar)
Üye
Üyelik tarihi:
12/2015
Nereden:
Kocaeli
Yaş:
9
Mesajlar:
3.293
Konular:
331
Teşekkür (Etti):
783
Teşekkür (Aldı):
912
Ticaret:
(0) %
09-08-2017 00:12
#8
Eline Sağlık Ümstat
---------------------
Çakallık Yapanı Kurt Boğar!
'Taipan - ait Kullanıcı Resmi (Avatar)
Forumdan Uzaklaştırıldı
Üyelik tarihi:
06/2015
Mesajlar:
3.876
Konular:
87
Teşekkür (Etti):
935
Teşekkür (Aldı):
1359
Ticaret:
(0) %
09-08-2017 00:12
#9
Çok güzel ihracatlar yapıyorsun eline sağlık
siberdrone15 - ait Kullanıcı Resmi (Avatar)
Üye
Üyelik tarihi:
08/2016
Yaş:
100
Mesajlar:
4.418
Konular:
521
Teşekkür (Etti):
1790
Teşekkür (Aldı):
763
Ticaret:
(0) %
09-08-2017 00:17
#10
Eline sağlık

Bookmarks


« Önceki Konu | Sonraki Konu »
Seçenekler

Yetkileriniz
Sizin Yeni Konu Acma Yetkiniz var yok
You may not post replies
Sizin eklenti yükleme yetkiniz yok
You may not edit your posts

BB code is Açık
Smileler Açık
[IMG] Kodları Açık
HTML-Kodları Kapalı
Trackbacks are Kapalı
Pingbacks are Kapalı
Refbacks are Kapalı