Terminalde sadece aritmetik işlemler yapan değil, aynı zamanda karmaşık mantıksal ifadeleri çözebilen güçlü bir hesap makinesi mi arıyorsunuz? Axion ile bu güçlü aracı sıfırdan nasıl inşa edeceğinizi öğrenin! Bu makale, adım adım rehberlik ve gerçek dünya senaryolarıyla sizi bu heyecan verici projeye davet ediyor. Geleneksel hesap makinelerinin sınırlarını aşarak, daha akıllı ve etkileşimli bir deneyim yaşamak için okumaya devam edin.
Gündelik iş akışlarımızda sıkça başvurduğumuz terminal hesap makineleri, genellikle basit aritmetik işlemlerle sınırlıdır. Toplama, çıkarma, çarpma ve bölme gibi temel fonksiyonlar elbette önemlidir; ancak çoğu zaman yetersiz kalır. Gerçek dünyadaki problem çözme senaryoları, sadece sayılarla değil, aynı zamanda mantıksal koşullarla, değişkenlerle ve karmaşık ifade zincirleriyle de uğraşmayı gerektirir. “Eğer bir ürünün stoğu belirli bir seviyenin altındaysa VE talep yüksekse, sipariş ver” gibi kararları bir terminal hesap makinesine nasıl emanet edebiliriz?
İşte tam da bu noktada, Axion gibi “mantık işleten” bir terminal hesap makinesine ihtiyaç duyuyoruz. Axion, klasik sayısal hesaplamaların ötesine geçerek, programlama dillerine özgü mantıksal yapıları, değişken tanımlamalarını ve hatta basit fonksiyon çağrılarını terminal ortamına taşımayı hedefler. Bu sayede kullanıcılar, sadece 2 + 2 gibi basit işlemleri yapmakla kalmaz, aynı zamanda IF (x > 10 AND y < 5) THEN print("Koşul Sağlandı") ELSE print("Koşul Sağlanmadı") gibi ifadeleri doğrudan komut satırında değerlendirebilirler. Bu, terminal deneyimini zenginleştiren ve özellikle geliştiriciler, veri analistleri veya sistem yöneticileri için inanılmaz derecede pratik bir araç haline gelir. Peki, böyle bir aracı nasıl hayata geçirebiliriz? Bu makale, Axion'ın temel bileşenlerini adım adım açıklayacak ve kendi mantık işleten hesap makinenizi inşa etmeniz için gerekli tüm bilgileri sunacaktır. Hazırsanız, sayıların ve mantığın dünyasını birleştiren bu heyecan verici yolculuğa başlayalım.
Axion Nedir ve Geleneksel Hesap Makinelerinden Farkı Nelerdir?
Axion, adını "aksiyom" kelimesinden alarak, temel prensiplere dayalı ve mantık odaklı bir yaklaşımla tasarlanmış bir terminal hesap makinesi projesidir. Geleneksel terminal hesap makineleri genellikle tek seferlik, doğrudan yorumlanan matematiksel ifadeler üzerinde çalışırken, Axion çok daha fazlasını vaat eder. Axion'ı anlamak için, bir programlama dilinin nasıl çalıştığının temel prensiplerine bakmamız gerekir: Lexer, Parser, Soyut Sözdizimi Ağacı (AST) ve Yorumlayıcı (Interpreter). Axion, bu bileşenleri kullanarak, yalnızca aritmetik işlemleri değil, aynı zamanda koşullu ifadeler, mantıksal operatörler, değişken atamaları ve hatta kullanıcı tanımlı fonksiyonlar gibi daha gelişmiş yapıları da işleyebilir.
Peki, geleneksel bir hesap makinesi ile Axion arasındaki temel farklar nelerdir? İşte bir karşılaştırma:
| Özellik | Geleneksel Terminal Hesap Makinesi | Axion (Mantık İşleten Hesap Makinesi) |
|---|---|---|
| İşlem Tipi | Temel aritmetik (toplama, çıkarma, çarpma, bölme, mod alma) | Aritmetik işlemler, mantıksal operatörler (AND, OR, NOT), karşılaştırma operatörleri (>, <, ==), koşullu ifadeler (IF/THEN/ELSE), değişken atama, basit fonksiyon çağrıları. |
| İfade Karmaşıklığı | Basit tek satırlık ifadeler (ör: 5 * (3 + 2)) |
Çok satırlı, iç içe geçmiş, mantıksal akışı olan karmaşık ifadeler. |
| Bellek/Değişken Desteği | Genellikle sınırlı veya hiç yok (bazen "ans" gibi son sonuç değişkenleri) | Kullanıcı tanımlı değişkenler, kapsam yönetimi. |
| Programatik Akış Kontrolü | Yok | IF/THEN/ELSE gibi koşullu dallanma. |
| Uygulama Alanı | Hızlı matematiksel hesaplamalar | Hızlı kararlar, basit otomasyon betikleri, veri koşullarını test etme, karmaşık formüllerin anında değerlendirilmesi. |
Bu karşılaştırma da gösterdiği üzere, Axion sadece bir sayı işlemcisi olmaktan çok, mini bir programlama ortamı işlevi görür. Bu, kullanıcıların daha önce programlama dili yazmak zorunda kalacakları birçok senaryoyu doğrudan terminalde, hızlı ve etkili bir şekilde çözmelerini sağlar. Bu yetenek, Axion'ı özellikle geliştirme, test etme veya sistem yönetimi gibi alanlarda paha biçilmez bir araç haline getirir. Şimdi, Axion'ın bu gelişmiş yeteneklerini nasıl kazandığına, yani kalbinde yatan temel bileşenlere daha yakından bakalım.
Axion'ın Kalbi: Lexer ve Parser Nasıl Çalışır?
Herhangi bir programlama dili veya Axion gibi mantık işleten bir araç, kullanıcının girdiği metin tabanlı komutları anlayabilmek için iki temel adımdan geçer: tokenlaştırma (lexing) ve ayrıştırma (parsing). Bu iki adım, girilen karmaşık ifadelerin bilgisayar tarafından işlenebilir bir yapıya dönüştürülmesini sağlar. Bu süreci, bir insan dilini anlamaya benzetebiliriz: önce kelimeleri tanırız (lexer), sonra bu kelimelerin cümle içindeki gramer kurallarına göre anlamlı bir yapı oluşturup oluşturmadığına bakarız (parser).
Tokenlaştırma Sanatı: Lexer Nedir ve Nasıl Oluşturulur?
Lexer, diğer adıyla "tarayıcı" veya "tokenlaştırıcı", Axion'a girdi olarak verilen ham metni (örneğin, IF (x > 10) THEN y = 5 ELSE y = 0) alıp, bunu anlamlı parçacıklara, yani "token"lara ayırır. Her bir token, dilin en küçük anlamlı birimidir. Örneğin, IF bir anahtar kelime token'ı, x bir tanımlayıcı token'ı, > bir operatör token'ı, 10 bir sayı token'ı, = bir atama operatörü token'ı ve ; bir ifade sonlandırma token'ı olabilir. Lexer'ın görevi, boşlukları ve yorum satırlarını (eğer varsa) göz ardı ederek, bu token'ları doğru tip ve değerle belirlemektir. Bu işlem genellikle düzenli ifadeler (regular expressions) veya durum makineleri (state machines) kullanılarak yapılır.
Bir Lexer oluştururken dikkat etmemiz gereken bazı temel token tipleri şunlardır:
- Anahtar Kelimeler:
IF,THEN,ELSE,AND,OR,NOTgibi dile özgü kelimeler. - Tanımlayıcılar: Değişken isimleri (
x,sayi,urun_kodu). - Literaller: Sayılar (
10,3.14), metinler ("Merhaba"), boolean değerler (TRUE,FALSE). - Operatörler: Aritmetik (
+,-,*,/), karşılaştırma (>,<,==,!=), atama (=). - Ayraçlar: Parantezler (
(,)), küme parantezleri ({,}), virgüller (,).
Basit bir Python (veya JavaScript) benzeri Lexer örneği şöyle görünebilir:
class Token:
def __init__(self, type, value=None):
self.type = type
self.value = value
def __repr__(self):
return f"Token({self.type}, {self.value})"
class Lexer:
def __init__(self, text):
self.text = text
self.pos = 0
self.current_char = self.text[self.pos] if self.text else None
def advance(self):
self.pos += 1
self.current_char = self.text[self.pos] if self.pos < len(self.text) else None
def skip_whitespace(self):
while self.current_char is not None and self.current_char.isspace():
self.advance()
def integer(self):
result = ''
while self.current_char is not None and self.current_char.isdigit():
result += self.current_char
self.advance()
return int(result)
def _id(self): # Tanımlayıcılar ve Anahtar Kelimeler
result = ''
while self.current_char is not None and (self.current_char.isalnum() or self.current_char == '_'):
result += self.current_char
self.advance()
KEYWORDS = {'IF': 'IF', 'THEN': 'THEN', 'ELSE': 'ELSE', 'AND': 'AND', 'OR': 'OR', 'NOT': 'NOT'}
token_type = KEYWORDS.get(result.upper(), 'ID')
return Token(token_type, result)
def get_next_token(self):
while self.current_char is not None:
if self.current_char.isspace():
self.skip_whitespace()
continue
if self.current_char.isdigit():
return Token('NUMBER', self.integer())
if self.current_char.isalpha() or self.current_char == '_':
return self._id()
if self.current_char == '+': return Token('PLUS', self.current_char)
if self.current_char == '-': return Token('MINUS', self.current_char)
# ... diğer operatörler ve ayraçlar
self.advance() # Son olarak karakteri atlayalım
return Token('EOF', None) # End of File
# Kullanım örneği:
# lexer = Lexer("IF (sayi > 10) THEN sonuc = 5")
# tokens = []
# while True:
# token = lexer.get_next_token()
# if token.type == 'EOF':
# break
# tokens.append(token)
# print(tokens)
Sözdizimini Anlamak: Parser ve Soyut Sözdizimi Ağacı (AST) İnşası
Lexer'dan gelen token dizisi, dilbilgisi kurallarına göre anlamlı bir yapı oluşturmak için Parser'a (ayrıştırıcıya) gönderilir. Parser'ın ana görevi, token dizisini alıp bir Soyut Sözdizimi Ağacı (AST - Abstract Syntax Tree) oluşturmaktır. AST, kodun hiyerarşik ve anlamsal yapısını temsil eden bir veri yapısıdır. Bu ağaç, ifadenin nasıl yorumlanacağını ve hangi sırayla işleneceğini açıkça gösterir. Örneğin, 2 + 3 * 4 gibi bir ifade, çarpma işleminin toplama işleminden önce yapılması gerektiğini gösteren bir AST'ye dönüştürülür.
Parser oluştururken genellikle Recursive Descent (Özyinelemeli İniş) veya Pratt Parser gibi teknikler kullanılır. Bu teknikler, operatör önceliği (çarpma ve bölme toplama ve çıkarmadan önce gelir) ve parantezlerin kullanımı gibi dilbilgisi kurallarını uygulamak için önemlidir. Her bir dilbilgisi kuralı (örneğin, bir ifade, bir terim, bir faktör) için ayrı bir fonksiyon tanımlanır ve bu fonksiyonlar birbirlerini çağırarak AST'yi adım adım inşa eder.
Örneğin, IF (koşul) THEN ifade1 ELSE ifade2 gibi bir ifade için AST'nin kökü bir "IfStatement" düğümü olabilir. Bu düğümün üç çocuğu olurdu: "Condition" düğümü (içinde koşul ifadesinin AST'si), "ThenBranch" düğümü (içinde ifade1'in AST'si) ve "ElseBranch" düğümü (içinde ifade2'nin AST'si). Bu yapı, yorumlayıcının (interpreter) kodu adım adım takip etmesini ve doğru mantığı uygulamasını kolaylaştırır.
Basit bir parser iskeleti, tokenları tüketen ve AST düğümleri üreten fonksiyonlardan oluşur:
class ASTNode:
pass
class NumberNode(ASTNode):
def __init__(self, token):
self.token = token
self.value = token.value
class BinaryOpNode(ASTNode):
def __init__(self, left, op, right):
self.left = left
self.op = op
self.right = right
class VarAssignNode(ASTNode):
def __init__(self, var_name, value):
self.var_name = var_name
self.value = value
class IfStatementNode(ASTNode):
def __init__(self, condition, then_branch, else_branch=None):
self.condition = condition
self.then_branch = then_branch
self.else_branch = else_branch
class Parser:
def __init__(self, lexer):
self.lexer = lexer
self.current_token = self.lexer.get_next_token()
def eat(self, token_type):
if self.current_token.type == token_type:
self.current_token = self.lexer.get_next_token()
else:
raise Exception(f"Sözdizimi Hatası: Beklenmeyen token {self.current_token.type}")
def factor(self): # Sayılar veya parantezli ifadeler
token = self.current_token
if token.type == 'NUMBER':
self.eat('NUMBER')
return NumberNode(token)
elif token.type == 'LPAREN': # (
self.eat('LPAREN')
node = self.expr()
self.eat('RPAREN') # )
return node
elif token.type == 'ID': # Değişken veya fonksiyon
name = token.value
self.eat('ID')
return VarNode(name) # Varsayalım basitçe bir değişken düğümü döndürüyoruz
def term(self): # Çarpma / Bölme işlemleri
node = self.factor()
while self.current_token.type in ('MUL', 'DIV'):
token = self.current_token
if token.type == 'MUL': self.eat('MUL')
elif token.type == 'DIV': self.eat('DIV')
node = BinaryOpNode(node, token, self.factor())
return node
def expr(self): # Toplama / Çıkarma işlemleri
node = self.term()
while self.current_token.type in ('PLUS', 'MINUS'):
token = self.current_token
if token.type == 'PLUS': self.eat('PLUS')
elif token.type == 'MINUS': self.eat('MINUS')
node = BinaryOpNode(node, token, self.term())
return node
def assignment(self): # Değişken ataması (örn: x = 5)
var_node = self.current_token
self.eat('ID')
self.eat('ASSIGN') # '=' operatörü için ASSIGN token'ı
value_node = self.expr()
return VarAssignNode(var_node.value, value_node)
def if_statement(self):
self.eat('IF')
self.eat('LPAREN')
condition = self.expr() # Koşul ifadesi (örn: x > 10)
self.eat('RPAREN')
self.eat('THEN')
then_branch = self.expr() # THEN sonrası ifade
else_branch = None
if self.current_token.type == 'ELSE':
self.eat('ELSE')
else_branch = self.expr() # ELSE sonrası ifade
return IfStatementNode(condition, then_branch, else_branch)
def parse(self): # Ana parse fonksiyonu
# Burada ifadelere göre uygun parse fonksiyonunu çağırırız.
# Basitçe bir ifade döndürelim:
if self.current_token.type == 'IF':
return self.if_statement()
elif self.current_token.type == 'ID' and self.lexer.text[self.lexer.pos] == '=': # Bir sonraki karakter '=' ise atama
return self.assignment()
else:
return self.expr()
Lexer ve Parser, Axion'ın beynini oluşturur. Bu iki bileşen sayesinde Axion, sadece karakter dizileri olarak gördüğü girdiyi, üzerinde mantıksal işlemler yapabileceği anlamlı ve yapılandırılmış bir ağaca dönüştürür. Bu ağaç, bir sonraki aşama olan Yorumlayıcı tarafından işlenerek gerçek değerler ve sonuçlar üretilecektir. Bu yapıyı anlamak, kendi mantık işleten hesap makinenizi inşa etmenin temelini oluşturur.
Mantığı Hayata Geçirme: Axion'da Bir Yorumlayıcı (Interpreter) Nasıl Yaratılır?
Lexer ve Parser, kullanıcıdan gelen girdiyi anlamlı tokenlara ve ardından bir Soyut Sözdizimi Ağacı'na (AST) dönüştürdü. Şimdi sırada bu AST'yi "çalıştırma", yani ifadenin mantığını değerlendirme ve bir sonuç üretme zamanı var. Bu görev, Yorumlayıcı'ya (Interpreter) aittir. Yorumlayıcı, AST'nin düğümleri arasında dolaşır, her bir düğümün temsil ettiği işlemi gerçekleştirir ve nihai bir değer veya etki (örneğin bir değişkenin değerini değiştirmek) üretir. Axion'ın "mantık işleten" kısmı tam da burada devreye girer.
Yorumlayıcı, AST'nin her bir düğüm tipini nasıl işleyeceğini bilir. Örneğin:
- Sayı Düğümleri (NumberNode): Sadece düğümdeki sayı değerini döndürür.
- İkili İşlem Düğümleri (BinaryOpNode): Sol ve sağ çocuk düğümlerini özyinelemeli olarak değerlendirir, ardından operatöre (
+,-,*,/,>,<,==,AND,ORvb.) göre işlemi yapar ve sonucu döndürür. Bu, operatör önceliğinin Parser tarafından zaten çözülmüş olmasının avantajıdır. - Değişken Atama Düğümleri (VarAssignNode): Değişkenin adını alır, sağ taraftaki ifadeyi değerlendirir ve bu değeri bir "sembol tablosu" veya "çevre" adı verilen bir bellek yapısında saklar.
- Değişken Düğümleri (VarNode): Sembol tablosundan değişkenin adını arar ve değerini döndürür.
- Koşullu İfade Düğümleri (IfStatementNode): Koşul ifadesi düğümünü değerlendirir. Eğer koşul
TRUEise,THENdalını değerlendirir; aksi takdirde (eğer varsa)ELSEdalını değerlendirir.
Yorumlayıcının en kritik bileşenlerinden biri, değişkenlerin değerlerini saklamak için kullandığı bellektir. Buna genellikle "çevre" (environment) veya "sembol tablosu" denir. Bu yapı, anahtar-değer çiftleri (değişken adı - değişken değeri) tutarak Axion'ın ifadeler arasında state (durum) korumasını sağlar.
class Interpreter:
def __init__(self):
self.variables = {} # Değişkenleri saklamak için basit bir sözlük
def visit(self, node):
method_name = f'visit_{type(node).__name__}'
visitor = getattr(self, method_name, self.generic_visit)
return visitor(node)
def generic_visit(self, node):
raise Exception(f'Ziyaret metodu bulunamadı: {type(node).__name__}')
def visit_NumberNode(self, node):
return node.value
def visit_BinaryOpNode(self, node):
left_val = self.visit(node.left)
right_val = self.visit(node.right)
if node.op.type == 'PLUS': return left_val + right_val
if node.op.type == 'MINUS': return left_val - right_val
if node.op.type == 'MUL': return left_val * right_val
if node.op.type == 'DIV': return left_val / right_val
if node.op.type == 'GT': return left_val > right_val # >
if node.op.type == 'LT': return left_val < right_val # <
if node.op.type == 'EQ': return left_val == right_val # ==
if node.op.type == 'AND': return left_val and right_val
if node.op.type == 'OR': return left_val or right_val
raise Exception(f"Bilinmeyen operatör: {node.op.type}")
def visit_VarAssignNode(self, node):
var_name = node.var_name
value = self.visit(node.value)
self.variables[var_name] = value
return value # Atanan değeri döndür
def visit_VarNode(self, node):
var_name = node.name
if var_name in self.variables:
return self.variables[var_name]
raise Exception(f"Tanımlanmamış değişken: {var_name}")
def visit_IfStatementNode(self, node):
condition_result = self.visit(node.condition)
if condition_result:
return self.visit(node.then_branch)
elif node.else_branch:
return self.visit(node.else_branch)
return None # ELSE dalı yoksa ve koşul false ise None döndür
Gerçek Dünya Senaryosu 1: Bütçe Denetleme Scripti
Diyelim ki, aylık gelir ve giderlerinizi takip eden basit bir bütçe denetleme mekanizması kurmak istiyorsunuz. Axion ile bunu şöyle ifade edebilirsiniz:
gelir = 5000;
gider = 3000;
tasarruf_hedefi = 1500;
kalan = gelir - gider;
IF (kalan > tasarruf_hedefi) THEN print("Harika! Tasarruf hedefine ulaşıldı!") ELSE print("Biraz daha dikkatli harcama yapmalısın.");
Burada Axion yorumlayıcısı, önce gelir, gider ve tasarruf_hedefi değişkenlerini sembol tablosuna kaydeder. Ardından kalan değişkenini hesaplar. Son olarak, IF koşulunu değerlendirir: kalan > tasarruf_hedefi (yani 2000 > 1500) ifadesi TRUE döndürürse, "Harika! Tasarruf hedefine ulaşıldı!" mesajını ekrana basar. Bu basit örnek, Axion'ın sadece sayıları işlemekle kalmayıp, bu sayılar üzerinden mantıksal kararlar alabilme yeteneğini açıkça göstermektedir. Bu, geleneksel bir hesap makinesinin yapamayacağı bir iştir.
Adım Adım Axion İnşası: Kendi Mantık Motorunuzu Kurmak İçin Pratik Rehber
Kendi Axion benzeri mantık motorunuzu inşa etmek, Lexer, Parser ve Interpreter aşamalarını sırayla ele alarak gerçekleştirilir. Bu süreçte, seçtiğiniz programlama dili ve kütüphaneler önemli rol oynar. Python veya JavaScript gibi yüksek seviyeli diller, string işlemleri ve veri yapıları konusunda sundukları kolaylıklar nedeniyle bu tür projeler için harika başlangıç noktalarıdır.
Hangi Programlama Dilini Seçmeliyim?
Genellikle bu tür projeler için Python veya JavaScript tercih edilir:
- Python: Temiz sözdizimi, zengin string işleme fonksiyonları ve listeler/sözlükler gibi güçlü veri yapıları sayesinde Lexer ve Parser yazmak oldukça kolaydır.
- JavaScript: Eğer hedefiniz web tabanlı bir terminal hesap makinesi ise veya Node.js kullanarak backend'de çalışmak istiyorsanız JavaScript doğal bir seçimdir. Regex desteği de güçlüdür.
Bu rehberde genel prensipleri açıklayacağımız için, kod örneklerini Python benzeri bir sözdizimiyle sunacağız, ancak mantık diğer dillere de kolayca adapte edilebilir.
Gerekli Kütüphaneler ve CLI Arayüzü
Axion'ı sıfırdan inşa ettiğimiz için özel bir kütüphaneye ihtiyaç duymayız. Ancak, komut satırı arayüzü (CLI) için Python'da input(), JavaScript'te readline modülü gibi temel I/O fonksiyonları yeterlidir. Kullanıcıdan sürekli girdi alabilmek için basit bir döngü kurarız:
# Python CLI İskeleti
def run_axion():
interpreter = Interpreter() # Yorumlayıcı nesnesi
print("Axion Terminal Hesap Makinesi (Çıkmak için 'exit' yazın)")
while True:
try:
text = input(">>> ")
if text.lower() == 'exit':
break
if not text.strip(): # Boş girdiyi atla
continue
lexer = Lexer(text)
parser = Parser(lexer)
tree = parser.parse()
result = interpreter.visit(tree)
if result is not None: # Sadece bir değer döndüğünde yazdır
print(result)
except Exception as e:
print(f"Hata: {e}")
# run_axion() # Uygulamayı başlatmak için bu satırı çağırın
Bu iskelet, kullanıcıdan girdi alır, lexer ve parser'a gönderir, AST'yi oluşturur ve yorumlayıcı ile değerlendirir. Hata yönetimi de try-except bloğu ile sağlanır.
Adım Adım Uygulama
- Token Sınıfları ve Lexer Oluşturma:
Tokensınıfı: Tip (örn. 'NUMBER', 'PLUS', 'IF') ve değer (örn. 10, None, 'IF') içermeli.Lexersınıfı: Girdiyi karakter karakter okuyup token'ları belirleyecek metotları içermeli (skip_whitespace,integer,_id,get_next_token).- Temel operatörleri, sayıları, tanımlayıcıları ve anahtar kelimeleri tanıdığından emin olun.
# Lexer'dan örnek bir bölüm def _id(self): # Tanımlayıcılar ve Anahtar Kelimeler result = '' while self.current_char is not None and (self.current_char.isalnum() or self.current_char == '_'): result += self.current_char self.advance() KEYWORDS = {'IF': 'IF', 'THEN': 'THEN', 'ELSE': 'ELSE', 'AND': 'AND', 'OR': 'OR', 'NOT': 'NOT', 'TRUE': True, 'FALSE': False} token_type = KEYWORDS.get(result.upper(), 'ID') return Token(token_type, KEYWORDS[result.upper()] if result.upper() in ['TRUE', 'FALSE'] else result) # Boolean değerleri de ele al - AST Düğümleri ve Parser Oluşturma:
- Farklı ifade tipleri için (sayı, ikili işlem, atama, if ifadesi) ayrı AST düğüm sınıfları tanımlayın.
Parsersınıfı: Lexer'dan tokenları alıp, dilbilgisi kurallarına göre bu düğümleri birleştiren metotları içermeli (factor,term,expr,assignment,if_statement,parse).- Operatör önceliğini doğru bir şekilde uyguladığından emin olun (örn.
*ve/,+ve-'den önce).
# Parser'dan örnek bir bölüm (ifade zincirlemesi) def expr(self): node = self.term() while self.current_token.type in ('PLUS', 'MINUS', 'GT', 'LT', 'EQ', 'AND', 'OR'): token = self.current_token if token.type in ('PLUS', 'MINUS'): self.eat(token.type) elif token.type in ('GT', 'LT', 'EQ'): self.eat(token.type) # Karşılaştırma operatörleri elif token.type in ('AND', 'OR'): self.eat(token.type) # Mantıksal operatörler node = BinaryOpNode(node, token, self.term()) # Daha fazla operatör için term yerine uygun parse fonksiyonu return node - Yorumlayıcı (Interpreter) Oluşturma:
Interpretersınıfı: AST düğümlerini ziyaret edip, her düğüm tipine özgü işlemi gerçekleştiren metotları içermeli (visit_NumberNode,visit_BinaryOpNode,visit_VarAssignNode,visit_IfStatementNode).- Değişkenleri saklamak için bir sözlük (
self.variables = {}) kullanın. - Mantıksal operatörleri (
AND,OR,NOT) ve karşılaştırma operatörlerini (>,<,==) doğru bir şekilde işlediğinden emin olun.
# Interpreter'dan örnek bir bölüm (koşullu ifade) def visit_IfStatementNode(self, node): condition_result = bool(self.visit(node.condition)) # Koşulu boolean'a çevir if condition_result: return self.visit(node.then_branch) elif node.else_branch: return self.visit(node.else_branch) return None # ELSE dalı yoksa ve koşul false ise None döndür
Bu adımları takip ederek ve her bir bölümü dikkatlice test ederek kendi Axion'ınızı oluşturabilirsiniz. Unutmayın, bu tür bir projede adım adım ilerlemek ve her bileşeni ayrı ayrı doğrulamak, hata ayıklama sürecini çok daha kolay hale getirecektir. Bir sonraki bölümde, Axion'ı daha da güçlendirmek için ileri düzey özelliklere ve performans ipuçlarına değineceğiz.
Axion'ı Geliştirmek: İleri Düzey Özellikler ve Performans İpuçları
Axion'ın temelini attıktan sonra, onu daha güçlü ve esnek bir araç haline getirmek için birçok ileri düzey özellik ekleyebilirsiniz. Bu geliştirmeler, Axion'ın sadece basit mantık ifadelerini değil, aynı zamanda daha karmaşık programlama yapılarını da işleyebilmesini sağlar.
Fonksiyon Tanımlamaları ve Çağrıları
Kullanıcıların kendi fonksiyonlarını (örn. FUNC kare(x) { RETURN x * x; }) tanımlayıp çağırabilmesi, Axion'ın gücünü katlar. Bu özellik için Lexer'a FUNC ve RETURN anahtar kelimeleri eklemeli, Parser'a fonksiyon tanımlama ve çağrılarını işleyecek yeni düğümler (FunctionDefinitionNode, FunctionCallNode) eklemeli ve Interpreter'ı da bunları değerlendirecek şekilde güncellemelisiniz. Özellikle, fonksiyon çağrılarında parametre geçişi ve dönüş değeri yönetimi önemlidir.
# Fonksiyon tanımlama ve çağırma için basit bir örnek (Pseudocode)
# Lexer'da: 'FUNC', 'RETURN' tokenları
# Parser'da:
# FunctionDefinitionNode(name, params, body_nodes)
# FunctionCallNode(name, args)
# Interpreter'da:
# def visit_FunctionDefinitionNode(self, node):
# self.functions[node.name] = {'params': node.params, 'body': node.body_nodes}
# def visit_FunctionCallNode(self, node):
# # Fonksiyonu bul, parametreleri ata, body'yi yeni bir kapsamda ziyaret et
# # return değeri varsa onu döndür
Bu, kullanıcıların tekrarlayan mantık bloklarını yeniden kullanılabilir hale getirmesine olanak tanır.
Hata Yönetimi ve Anlamlı Hata Mesajları
Sağlam bir Axion için, kullanıcı dostu hata mesajları vazgeçilmezdir. Lexer, Parser ve Interpreter'ın her aşamasında meydana gelebilecek hataları (tanınmayan karakter, sözdizimi hatası, tanımlanmamış değişken, tip uyumsuzluğu vb.) yakalayıp, kullanıcının anlayabileceği bir dille bildirmelisiniz. Bu, genellikle hata konumunu (satır/sütun numarası) belirten özel hata sınıfları oluşturarak yapılır.
# Hata yönetimi örneği (Python)
class AxionSyntaxError(Exception):
def __init__(self, message, line=None, col=None):
super().__init__(message)
self.line = line
self.col = col
def __str__(self):
if self.line and self.col:
return f"Sözdizimi Hatası ({self.line}:{self.col}): {self.args[0]}"
return f"Sözdizimi Hatası: {self.args[0]}"
# Parser'da hata fırlatma
# if self.current_token.type != expected_type:
# raise AxionSyntaxError(f"Beklenmeyen token. '{expected_type}' bekliyordum, '{self.current_token.type}' geldi.", ...)
Kullanıcı Tanımlı Değişkenler ve Kapsam Yönetimi
Mevcut basit değişken sözlüğünü geliştirerek, iç içe kapsamları (nested scopes) destekleyen bir yapı kurabilirsiniz. Bu, bir fonksiyon içinde tanımlanan değişkenin sadece o fonksiyona özel olmasını sağlar. Her fonksiyon çağrısı veya blok, kendi yerel kapsamına sahip olur ve değişkenler bu kapsamlar arasında doğru bir şekilde çözümlenir. Bu, genellikle bir "çevre zinciri" (chain of environments) ile gerçekleştirilir.
Uzman İpucu: Kapsam Yönetimi için Sembol Tablosu Kullanımı. Global değişkenler için ana bir sembol tablosu, her fonksiyon veya blok için ise bu tablonun bir alt tablosunu oluşturmak, değişkenlerin doğru kapsamda bulunmasını sağlar. Bu sayede "shadowing" (gölgeleme) ve yerel değişkenlerin dışarıya sızmasını engellersiniz.
Modüler Yapılandırma ve Eklenti Desteği
Axion'ı daha esnek hale getirmek için, kullanıcıların özel komutlar veya fonksiyonlar eklemesine olanak tanıyan bir eklenti (plugin) sistemi düşünebilirsiniz. Bu, Axion'ın çekirdek kodunu değiştirmeden yeni özellikler eklemek için idealdir. Örneğin, belirli bir API'den veri çeken bir fonksiyonu bir eklenti olarak ekleyebilirsiniz.
Performans İpuçları: JIT Derlemesi veya Önbelleğe Alma
Axion'ı daha hızlı hale getirmek isterseniz, özellikle çok tekrarlayan veya karmaşık ifadeler için Just-In-Time (JIT) derlemesi veya AST'yi önbelleğe alma gibi teknikleri araştırabilirsiniz. JIT derlemesi, AST'yi doğrudan makine koduna veya bir ara dile çevirerek yorumlama adımını ortadan kaldırır. Ancak bu, oldukça karmaşık bir konudur ve Axion'ın başlangıç aşamalarında genellikle gerekli değildir.
Uzman İpucu: JIT Derlemesi ile Performansı Nasıl Artırılır? JIT derlemesi, yorumlama maliyetini ortadan kaldırarak kodun doğrudan CPU üzerinde çalışmasını sağlar. Python'da Numba gibi kütüphanelerle veya LLVM gibi platformlarla entegrasyon düşünerek performans artışı sağlanabilir. Ancak başlangıç için basit AST yorumlaması yeterlidir. Eğer performansı artırmak isterseniz, sık kullanılan ifadelerin AST'lerini önbelleğe almak veya basitleştirilmiş bir bytecode'a derlemek daha pratik ilk adımlar olabilir.
Bu ileri düzey özellikler, Axion'ı basit bir hesap makinesinden güçlü, esnek ve hatta programlanabilir bir komut satırı aracına dönüştürür. Her bir özelliği eklerken, Lexer, Parser ve Interpreter katmanlarını tutarlı bir şekilde güncellemek ve kapsamlı testler yapmak önemlidir.
Vaka Analizi: Axion ile Karmaşık Bir Karar Mekanizması Nasıl Modellenir?
Axion'ın sadece basit hesaplamalar yapmaktan öte, gerçek dünyadaki karar mekanizmalarını modelleyebilme yeteneğini daha iyi anlamak için bir vaka analizine odaklanalım. Bir envanter yönetim sisteminde otomatik sipariş verme kararını ele alalım. Bu tür bir sistemde, ürünlerin stok seviyeleri, geçmiş talep verileri ve belirli eşikler göz önünde bulundurularak otomatik siparişler oluşturulması gerekebilir. Geleneksel bir terminal hesap makinesi bu karmaşık mantığı asla işleyemezken, Axion bunu kolayca yapabilir.
Senaryo: Otomatik Sipariş Verme Kararı
Bir e-ticaret deposunda, belirli ürünler için otomatik sipariş tetikleyicileri oluşturmak istiyoruz. Siparişin tetiklenmesi için iki koşulun aynı anda sağlanması gerekiyor:
- Ürünün stok seviyesi, belirli bir minimum stok seviyesinin altına düşmüş olmalı.
- Son 30 gündeki ortalama talep tahmini, günlük ortalama talep seviyesinin üzerinde olmalı (bu, talebin artışta olduğunu gösterir).
Axion ile bu karar mantığını aşağıdaki gibi ifade edebiliriz:
stok_seviyesi = 45;
min_stok_seviyesi = 50;
talep_tahmini_son_30gun = 15;
ortalama_talep_gunluk = 10;
IF (stok_seviyesi < min_stok_seviyesi AND talep_tahmini_son_30gun > ortalama_talep_gunluk)
THEN print("Otomatik sipariş tetiklendi! Miktar: 100")
ELSE print("Sipariş için koşullar sağlanmadı, beklemede.");
Axion'ın yorumlayıcısı bu ifadeyi adım adım nasıl işler:
- Önce,
stok_seviyesi,min_stok_seviyesi,talep_tahmini_son_30gunveortalama_talep_gunlukdeğişkenlerinin değerlerini kendi sembol tablosuna kaydeder. - Ardından,
IFkoşuluna ulaşır. Koşul, iki alt koşuldan oluşan birANDoperatörü içerir:- İlk alt koşul:
stok_seviyesi < min_stok_seviyesi. Bu durumda45 < 50, yaniTRUE. - İkinci alt koşul:
talep_tahmini_son_30gun > ortalama_talep_gunluk. Bu durumda15 > 10, yaniTRUE.
- İlk alt koşul:
ANDoperatörü, her iki tarafı daTRUEolduğu için genel koşuluTRUEolarak değerlendirir.- Koşul
TRUEolduğu için, AxionTHENdalını çalıştırır ve"Otomatik sipariş tetiklendi! Miktar: 100"mesajını çıktı olarak verir.
Bu senaryo, Axion'ın sadece aritmetik işlemleri değil, aynı zamanda birden fazla koşulu birleştirerek karmaşık iş mantığını nasıl ifade edebildiğini açıkça göstermektedir. Bu sayede, sistem yöneticileri veya iş analistleri, doğrudan terminalde basit betikler yazarak anlık kararlar alabilir veya sistem davranışlarını test edebilirler.
Mobil Uyumlu HTML ve Terminal Çıktısını Web'de Gösterme
Axion bir terminal uygulaması olsa da, çıktılarının veya arayüzünün web ortamında da mobil uyumlu bir şekilde sunulması gerekebilir. Örneğin, Axion'ın bir web arayüzü varsa veya bir blog yazısında Axion çıktısını göstermek istiyorsanız mobil uyumluluk önemlidir. Temel CSS medya sorguları ile bunu sağlayabiliriz:
>> stok_seviyesi = 45;
>> min_stok_seviyesi = 50;
>> talep_tahmini_son_30gun = 15;
>> ortalama_talep_gunluk = 10;
>> IF (stok_seviyesi < min_stok_seviyesi AND talep_tahmini_son_30gun > ortalama_talep_gunluk)
...> THEN print("Otomatik sipariş tetiklendi! Miktar: 100")
...> ELSE print("Sipariş için koşullar sağlanmadı, beklemede.");
"Otomatik sipariş tetiklendi! Miktar: 100"
Bu CSS örnekleri, Axion terminal çıktısının farklı ekran boyutlarında nasıl daha okunabilir hale getirilebileceğini göstermektedir. Bu, Axion gibi bir aracın sadece terminalde değil, aynı zamanda çeşitli platformlarda da etkili bir şekilde kullanılabileceği potansiyelini vurgular.
Sonuç: Axion ve Terminal Hesap Makinelerinin Geleceği
Bu makalede, geleneksel terminal hesap makinelerinin sınırlılıklarını aşarak, daha güçlü ve "mantık işleten" bir araç olan Axion'ı nasıl inşa edebileceğimizi derinlemesine inceledik. Lexer, Parser ve Interpreter gibi temel bileşenlerin adım adım nasıl çalıştığını, soyut sözdizimi ağacının (AST) önemini ve gerçek dünya senaryolarında nasıl uygulanabileceğini gördük. Axion, sadece basit aritmetik işlemlerle yetinmeyip, koşullu ifadeler, mantıksal operatörler, değişken atamaları ve hatta ileri düzeyde fonksiyon tanımlamaları gibi programlama dili özelliklerini terminal ortamına getirerek kullanıcı deneyimini zenginleştirir. Bu sayede, geliştiriciler, analistler ve sistem yöneticileri gibi teknik kullanıcılar, karmaşık karar mekanizmalarını hızlı ve etkili bir şekilde modelleyebilir, test edebilir ve uygulayabilirler.
Axion gibi bir projenin inşası, programlama dillerinin iç işleyişini anlamak için harika bir öğrenme fırsatı sunar. Kendi Lexer'ınızı, Parser'ınızı ve Interpreter'ınızı yazmak, dil tasarımı, sözdizimi analizi ve semantik değerlendirme gibi temel bilgisayar bilimi kavramlarını pratik bir şekilde deneyimlemenizi sağlar. Ayrıca, hata yönetimi, kapsam yönetimi ve performans optimizasyonu gibi ileri düzey konulara değinerek, projenizi daha da sağlam ve kullanışlı hale getirme potansiyelini keşfettik. Terminal hesap makinelerinin geleceği, kesinlikle sadece sayılarla sınırlı kalmayacak; Axion gibi araçlar, komut satırı ortamını daha akıllı, etkileşimli ve programlanabilir bir alana dönüştürecektir. Kendi Axion projenizi başlatarak bu heyecan verici alana ilk adımı atın ve yaratıcılığınızı konuşturun!
Sıkça Sorulan Sorular (SSS)
- Axion sadece terminalde mi çalışır?
- Hayır, Axion'ın temel mantık motoru (Lexer, Parser, Interpreter) herhangi bir ortamda çalışabilir. Terminal, sadece varsayılan girdi/çıktı arayüzünü ifade eder. Web tabanlı bir arayüzle veya masaüstü uygulaması içinde de kullanılabilir. Hatta bir otomasyon betiğinin parçası olarak bir sunucuda bile çalıştırılabilir.
- Hangi programlama dilleriyle Axion benzeri bir araç geliştirebilirim?
- Python ve JavaScript, string işleme kolaylıkları ve zengin veri yapıları nedeniyle bu tür projeler için popüler ve uygun dillerdir. Ancak Java, C#, Go veya C++ gibi dillerde de benzer bir Lexer/Parser/Interpreter yapısı inşa edilebilir; bu dillerde genellikle performans avantajları elde edilebilir.
- Axion'ı bir web uygulamasına entegre etmek mümkün mü?
- Kesinlikle! Axion'ın Lexer, Parser ve Interpreter'ı bir JavaScript (Node.js veya tarayıcıda) veya Python (Flask, Django gibi frameworklerle) backend'i üzerinden web arayüzüne entegre edilebilir. Kullanıcılar bir web formuna Axion kodu yazabilir, backend bunu işleyebilir ve sonucu web sayfasında gösterebilir. Mobil uyumlu CSS ile de bu çıktıları mobil cihazlarda güzel görünmesini sağlayabilirsiniz.
- Performans kritik uygulamalar için uygun mudur?
- Axion'ın bu makalede açıklanan basit yorumlayıcı modeli, tipik bir terminal kullanım senaryosu için yeterince hızlıdır. Ancak, çok karmaşık veya aşırı derecede sık çalışması gereken performans kritik uygulamalar için JIT derlemesi veya bytecode derlemesi gibi daha gelişmiş teknikler gerekebilir. Bu tür uygulamalar için genellikle özel olarak optimize edilmiş derleyiciler veya sanal makineler kullanılır.
- Öğrenmek zor mu?
- Axion gibi bir mantık motoru inşa etmek, Lexer, Parser ve Interpreter kavramlarını anlamayı gerektirir. Bu kavramlar ilk başta karmaşık gelebilir, ancak adım adım ilerleyerek ve her bir bileşeni ayrı ayrı uygulayarak kolayca öğrenilebilir. Bu, bilgisayar bilimi ve programlama dilleri üzerine bilginizi derinleştirmek için çok değerli bir projedir.