একটি সিম্পল সিনট্যাক্স অ্যানালাইজার তৈরি করা, যা গাণিতিক (অ্যারিথমেটিক) এক্সপ্রেশন পার্স করতে পারে, একটি ভাল প্রকল্প হতে পারে। আমরা এই উদাহরণে একটি টপ-ডাউন পার্সার ব্যবহার করব যা গাণিতিক এক্সপ্রেশন যেমন সংখ্যা, যোগ, বিয়োগ, গুণ, এবং ভাগ পরিচালনা করবে।
ধাপ ১: ইনপুট এবং টোকেন প্রস্তুত করা
আমরা গাণিতিক এক্সপ্রেশন পার্স করার জন্য একটি লেক্সিকাল অ্যানালাইজার ব্যবহার করব, যা আগে তৈরি করেছি।
ধাপ ২: সিনট্যাক্স অ্যানালাইজার কোড লেখা
import re
# টোকেনের ধরন
TOKEN_TYPES = [
('NUMBER', r'\d+'), # সংখ্যা
('PLUS', r'\+'), # যোগ
('MINUS', r'-'), # বিয়োগ
('MULTIPLY', r'\*'), # গুণ
('DIVIDE', r'/'), # ভাগ
('LPAREN', r'\('), # খোলা বন্ধনী
('RPAREN', r'\)'), # বন্ধনী
('WHITESPACE', r'\s+'), # ফাঁকা স্থান
]
# সমস্ত টোকেন নিয়মকে একত্রিত করুন
TOKEN_REGEX = '|'.join(f'(?P<{pair[0]}>{pair[1]})' for pair in TOKEN_TYPES)
def tokenize(code):
tokens = []
for match in re.finditer(TOKEN_REGEX, code):
token_type = match.lastgroup
token_value = match.group(token_type)
if token_type != 'WHITESPACE': # ফাঁকা স্থান বাদ দিন
tokens.append((token_type, token_value))
return tokens
# সিনট্যাক্স অ্যানালাইজার
class Parser:
def __init__(self, tokens):
self.tokens = tokens
self.current_token_index = 0
self.current_token = tokens[self.current_token_index] if tokens else None
def consume(self, token_type):
if self.current_token and self.current_token[0] == token_type:
self.current_token_index += 1
self.current_token = self.tokens[self.current_token_index] if self.current_token_index < len(self.tokens) else None
else:
raise Exception(f"Unexpected token: {self.current_token}")
def parse(self):
result = self.expression()
if self.current_token is not None:
raise Exception("Unexpected token at the end of input")
return result
def expression(self):
result = self.term()
while self.current_token and self.current_token[0] in ('PLUS', 'MINUS'):
token = self.current_token
self.consume(token[0])
if token[0] == 'PLUS':
result += self.term()
elif token[0] == 'MINUS':
result -= self.term()
return result
def term(self):
result = self.factor()
while self.current_token and self.current_token[0] in ('MULTIPLY', 'DIVIDE'):
token = self.current_token
self.consume(token[0])
if token[0] == 'MULTIPLY':
result *= self.factor()
elif token[0] == 'DIVIDE':
result /= self.factor()
return result
def factor(self):
token = self.current_token
if token[0] == 'NUMBER':
self.consume('NUMBER')
return int(token[1])
elif token[0] == 'LPAREN':
self.consume('LPAREN')
result = self.expression()
self.consume('RPAREN')
return result
else:
raise Exception(f"Unexpected token: {token}")
# টেস্ট কোড
if __name__ == "__main__":
code = "(2 + 3) * 5 - 10 / 2"
tokens = tokenize(code)
parser = Parser(tokens)
result = parser.parse()
print(f"Result: {result}")
ধাপ ৩: কোডের ব্যাখ্যা
লেক্সিকাল অ্যানালাইজার: আগে লেখা টোকেনাইজারটি ইনপুট গাণিতিক এক্সপ্রেশনকে টোকেনে রূপান্তর করে।
পার্সার ক্লাস: Parser ক্লাসে গাণিতিক এক্সপ্রেশন পার্স করার জন্য বিভিন্ন ফাংশন রয়েছে:
parse(): প্রধান পার্সিং ফাংশন।expression(): যোগ এবং বিয়োগ পরিচালনা করে।term(): গুণ এবং ভাগ পরিচালনা করে।factor(): সংখ্যা বা বন্ধনী উন্মুক্ত করে।
অপারেশন লজিক: ইনপুটের উপর ভিত্তি করে সংখ্যা, অপারেটর এবং বন্ধনীগুলির জন্য কার্যক্রম পরিচালনা করে।
ফলাফল
এই কোডটি চালানোর পর, আপনি নিচের মতো আউটপুট পাবেন:
Result: 20
উপসংহার
এটি একটি সিম্পল সিনট্যাক্স অ্যানালাইজার তৈরির মৌলিক উদাহরণ যা গাণিতিক এক্সপ্রেশন পার্স করতে পারে। আপনি এই অ্যানালাইজারটিকে আরও উন্নত করতে পারেন, যেমন বিভিন্ন অপারেটর, কাস্টম ফাংশন, এবং এর আউটপুটের গঠন পরিবর্তন করে। এই প্রকল্পটি সিনট্যাক্স বিশ্লেষণ এবং প্রোগ্রামিং ভাষার সামগ্রিক ধারণা বোঝার জন্য একটি দুর্দান্ত উপায়।
Read more