সিনট্যাক্স বনাম সিমান্টিক্স
এই পাঠে যা শিখবেন
- সিনট্যাক্স ও সিমান্টিক্সের সুনির্দিষ্ট সংজ্ঞা ও পার্থক্য
- স্ট্যাটিক সিমান্টিক্স বনাম ডায়নামিক সিমান্টিক্স
- কেন একটি প্রোগ্রাম সিনট্যাক্টিক্যালি ঠিক থেকেও সিমান্টিক্যালি ভুল হতে পারে
- Python দিয়ে পৃথক সিনট্যাক্স-চেকার ও সিমান্টিক্স-চেকার বাস্তবায়ন
১ · সিনট্যাক্স কী — প্রোগ্রামের গঠন
সিনট্যাক্সSyntaxএকটি প্রোগ্রামিং ল্যাঙ্গুয়েজে কোন টোকেন-সিকোয়েন্স গঠনগতভাবে বৈধ প্রোগ্রাম গঠন করে তার নিয়ম — প্রোগ্রামের "ফর্ম", অর্থ নয়।
হলো একটি ভাষার গঠনগত (structural) নিয়ম — কোন কোন টোকেন-সিকোয়েন্স একটি বৈধ প্রোগ্রাম গঠন করে তা
নির্ধারণ করে (M3-এর ফরমাল গ্রামারের সরাসরি পূর্বাভাস)। একটি সিনট্যাক্স এরর মানে প্রোগ্রামের
গঠনটাই ভুল — যেমন একটি বন্ধনী মিসিং। গুরুত্বপূর্ণ বিষয় হলো, সিনট্যাক্স এরর ধরতে প্রোগ্রামের অর্থ জানার
দরকার নেই — শুধু গঠন যাচাই করলেই চলে। যেমন (3 + 5 — এখানে বন্ধনী অসম্পূর্ণ, এটি বোঝার জন্য "৩" বা
"৫" সংখ্যা দুটোর অর্থ কী তা জানার প্রয়োজনই নেই।
২ · সিমান্টিক্স কী — স্ট্যাটিক বনাম ডায়নামিক
সিমান্টিক্সSemanticsএকটি সিনট্যাক্টিক্যালি বৈধ প্রোগ্রামের প্রকৃত অর্থ — রান করলে আসলে কী মান গণনা হয়, কী side effect ঘটে। হলো একটি সিনট্যাক্টিক্যালি বৈধ প্রোগ্রামের অর্থ — রান করলে আসলে কী ঘটে। এটি দুই ভাগে ভাগ করা হয় —
রান না করেই চেক করা যায় এমন অর্থ-সংক্রান্ত নিয়ম — যেমন "ব্যবহারের আগে ভ্যারিয়েবল ডিক্লেয়ার করতে হবে," টাইপ কম্প্যাটিবিলিটি (M6/M7-এর সরাসরি পূর্বাভাস)। অর্থ নিয়ে হলেও এগুলো সাধারণত কম্পাইল-টাইমেই ধরা পড়ে।
প্রোগ্রামের আসল রানটাইম আচরণ — কী মান গণনা হয়, কী side effect ঘটে। এটিই ইন্টারপ্রেটার/কম্পাইলড প্রোগ্রাম এক্সিকিউশন আসলে করে।
৩ · সিনট্যাক্টিক্যালি ঠিক, সিমান্টিক্যালি ভুল — মূল কথা
এই পাঠের কেন্দ্রীয় বিষয় হলো — একটি প্রোগ্রাম সম্পূর্ণ সিনট্যাক্টিক্যালি বৈধ হয়েও
সিমান্টিক্যালি অর্থহীন বা ভুল হতে পারে। উদাহরণ: x = "hello" + 5 — এটি
সিনট্যাক্টিক্যালি সম্পূর্ণ ঠিক (একটি অ্যাসাইনমেন্ট স্টেটমেন্ট, ডানপাশে একটি প্লাস-এক্সপ্রেশন — গঠন হিসেবে কোনো
সমস্যা নেই)। কিন্তু এর অর্থ প্রশ্নবিদ্ধ — একটি স্ট্রিং ও একটি সংখ্যা যোগ করার কোনো সুনির্দিষ্ট,
সার্বজনীন অর্থ নেই, তাই অনেক ভাষায় এটি একটি সিমান্টিক এরর (টাইপ এরর)।
সিনট্যাক্স আর সিমান্টিক্স দুটো স্বতন্ত্র প্রশ্ন — "গঠনটা কি বৈধ?" (সিনট্যাক্স) এবং "গঠনটার অর্থ কি সংগত?" (সিমান্টিক্স)। একটি প্রোগ্রামের প্রথম প্রশ্নের উত্তর "হ্যাঁ" হলেও দ্বিতীয় প্রশ্নের উত্তর "না" হতে পারে — এই দুটো ব্যর্থতা-মোড একেবারেই আলাদা এবং কম্পাইলারে আলাদা ধাপে ধরা পড়ে।
৪ · কেন এই পার্থক্য প্রতিটি প্রোগ্রামারের কাজে লাগে
এই পার্থক্য বোঝা সরাসরি আপনার প্রতিদিনের ডিবাগিংয়ে কাজে লাগে —
- এরর মেসেজ পড়া: Python-এ
SyntaxErrorমানে গঠন ভুল (পার্সিং ব্যর্থ, M5) — প্রোগ্রামটি রানই হতে শুরু করেনি। কিন্তুTypeErrorবাNameErrorমানে গঠন ঠিক ছিল, কিন্তু অর্থ-সংক্রান্ত কোনো নিয়ম ভাঙা হয়েছে (সিমান্টিক্স, M6-M7)। - ধাপের ক্রম: একটি কম্পাইলার/ইন্টারপ্রেটার সবসময় আগে সিনট্যাক্স চেক করে (পার্সিং সফল না হলে পার্স ট্রি-ই তৈরি হয় না), তারপর সিমান্টিক অ্যানালাইসিস চালায় — কারণ সিমান্টিক অ্যানালাইসিস কাজ করে পার্স ট্রি-র উপর, যা সিনট্যাক্স ব্যর্থ হলে অস্তিত্বই থাকে না।
৫ · কোডে সিনট্যাক্স ও সিমান্টিক্স চেকার আলাদা করে বাস্তবায়ন
নিচে দুটি সম্পূর্ণ আলাদা ফাংশন — একটি শুধু গঠন (বন্ধনী ব্যালান্সড কিনা, স্ট্যাক ব্যবহার করে) যাচাই করে, আরেকটি শুধু অর্থ (একটি টয় এক্সপ্রেশন ট্রিতে টাইপ কম্প্যাটিবিলিটি) যাচাই করে — দুটো সম্পূর্ণ ভিন্ন ধরনের ব্যর্থতা প্রদর্শন করা হয়েছে।
# সিনট্যাক্স চেক -- শুধু গঠন যাচাই, স্ট্যাক দিয়ে বন্ধনী ব্যালান্স চেক করা হয়
def check_syntax(tokens):
stack = []
for tok in tokens:
if tok == "(":
stack.append(tok)
elif tok == ")":
if not stack:
return False, "অতিরিক্ত ')' -- কোনো ম্যাচিং '(' নেই"
stack.pop()
if stack:
return False, "ম্যাচ না হওয়া '(' রয়ে গেছে"
return True, "সিনট্যাক্স ঠিক আছে"
# সিমান্টিক্স চেক -- শুধু অর্থ (টাইপ কম্প্যাটিবিলিটি) যাচাই, একটি টয় এক্সপ্রেশন ট্রি (left, op, right)-এর উপর
def check_semantics(expr_tree):
left, op, right = expr_tree
left_type = "str" if isinstance(left, str) else "num"
right_type = "str" if isinstance(right, str) else "num"
if op == "+":
if left_type != right_type:
return False, f"টাইপ মিসম্যাচ: {left_type} + {right_type} সংজ্ঞায়িত নয়"
return True, "সিমান্টিক্স ঠিক আছে"
return False, "অজানা অপারেটর"
# কেস ১: সিনট্যাক্সই ব্যর্থ -- সিমান্টিক্স চেক করার সুযোগই আসে না
tokens1 = ["(", "3", "+", "5"]
ok1, msg1 = check_syntax(tokens1)
print(f"কেস ১ -- টোকেন {tokens1}")
print(f" সিনট্যাক্স: {ok1} ({msg1})")
# কেস ২: সিনট্যাক্স ঠিক, কিন্তু সিমান্টিক্স ব্যর্থ
tokens2 = ["(", "hello", "+", "5", ")"]
expr2 = ("hello", "+", 5)
ok2, msg2 = check_syntax(tokens2)
print(f"\nকেস ২ -- টোকেন {tokens2}")
print(f" সিনট্যাক্স: {ok2} ({msg2})")
if ok2:
sem2, smsg2 = check_semantics(expr2)
print(f" সিমান্টিক্স (এক্সপ্রেশন ট্রি {expr2}): {sem2} ({smsg2})")
# কেস ৩: সিনট্যাক্স ও সিমান্টিক্স দুটোই ঠিক
tokens3 = ["(", "3", "+", "5", ")"]
expr3 = (3, "+", 5)
ok3, msg3 = check_syntax(tokens3)
print(f"\nকেস ৩ -- টোকেন {tokens3}")
print(f" সিনট্যাক্স: {ok3} ({msg3})")
if ok3:
sem3, smsg3 = check_semantics(expr3)
print(f" সিমান্টিক্স (এক্সপ্রেশন ট্রি {expr3}): {sem3} ({smsg3})")
check_semantics ফাংশনটি ডাকাই হয়নি — কারণ সিনট্যাক্স ব্যর্থ হওয়ার পর
সিমান্টিক্স চেক করার আর কোনো মানে নেই (গঠনই ভুল হলে "অর্থ" নিয়ে প্রশ্ন তোলার সুযোগ নেই)। কেস ২-এ সিনট্যাক্স
পাস করেছে (বন্ধনী ব্যালান্সড) কিন্তু সিমান্টিক্স ব্যর্থ হয়েছে (স্ট্রিং + সংখ্যা) — এটিই এই পাঠের কেন্দ্রীয়
উদাহরণ। কেস ৩-এ দুটোই পাস করেছে।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১ কেন সিনট্যাক্স এরর সবসময় সিমান্টিক্স চেক করার আগে ধরা পড়ে — সিমান্টিক্স চেক করে দেখা যায় সিনট্যাক্সও আসলে ঠিক ছিল কিনা, এভাবে হয় না কেন?
কারণ সিমান্টিক অ্যানালাইসিস কাজ করে পার্স ট্রি-র উপর (M6) — আর পার্স ট্রি তৈরিই হয় পার্সিং ধাপে (M5), যা নিজেই সিনট্যাক্স চেক করে। সিনট্যাক্স ব্যর্থ হলে কোনো পার্স ট্রি-ই তৈরি হয় না, তাই সিমান্টিক অ্যানালাইসিসের কাছে বিশ্লেষণ করার মতো কোনো ডেটা কাঠামোই থাকে না। এটি নিছক একটি কনভেনশন নয় — একটি বাস্তব নির্ভরতা: সিমান্টিক্স ধাপের ইনপুটই হলো সিনট্যাক্স ধাপের সফল আউটপুট।
প্র ০২
x = 5 + 3 ও x = "hello" + 5 — এই দুটো কি সিনট্যাক্টিক্যালি একই রকম বৈধ? তাহলে কেন একটির সিমান্টিক্স ঠিক আর আরেকটির ভুল?
হ্যাঁ, দুটোই সিনট্যাক্টিক্যালি হুবহু একই গঠনের — একটি অ্যাসাইনমেন্ট স্টেটমেন্ট, ডানপাশে একটি
<operand> + <operand> এক্সপ্রেশন। একটি পার্সার শুধু গঠন দেখে, তাই দুটোকেই সমানভাবে
বৈধ ধরবে। পার্থক্যটা আসে সিমান্টিক ধাপে, যেখানে অপারেন্ডের টাইপ পরীক্ষা করা হয় — সংখ্যা +
সংখ্যা একটি সুসংজ্ঞায়িত অপারেশন (যোগফল), কিন্তু স্ট্রিং + সংখ্যা নয় (একে "কী মানে?" প্রশ্নের কোনো
স্বতঃসিদ্ধ উত্তর নেই, তাই ভাষা এটিকে টাইপ এরর ঘোষণা করে)।
প্র ০৩
উপরের কোড সেলে check_syntax(["(", "3", "+", "5"]) কেন False রিটার্ন করে — স্ট্যাকের অবস্থা ধাপে ধাপে ব্যাখ্যা করুন।
টোকেন লিস্টে হাঁটা শুরু হয়: "(" পেলে স্ট্যাকে পুশ হয় → স্ট্যাক = ["("]।
"3", "+", "5" — এগুলো বন্ধনী নয়, তাই স্ট্যাক অপরিবর্তিত থাকে।
লুপ শেষ হওয়ার পর স্ট্যাক এখনও ["("] — খালি নয়। ফাংশনের শেষে if stack: চেক
এটি ধরে ফেলে এবং False, "ম্যাচ না হওয়া '(' রয়ে গেছে" রিটার্ন করে — কারণ একটি খোলা বন্ধনীর
কোনো বন্ধ জোড়া পাওয়া যায়নি।
অনুশীলন
-
চিন্তা করুন: আরেকটি সিনট্যাক্টিক্যালি বৈধ কিন্তু সিমান্টিক্যালি ভুল বা অর্থহীন এক্সপ্রেশনের উদাহরণ দিন (উপরের
"hello" + 5ছাড়া) এবং ব্যাখ্যা করুন কেন এটি সিমান্টিক্যালি সমস্যাযুক্ত।সাধারণ উদাহরণ:
x = 10 / 0(শূন্য দিয়ে ভাগ — গঠন সম্পূর্ণ বৈধ, কিন্তু "১০-কে ০ দিয়ে ভাগ করলে কী?" প্রশ্নের গাণিতিকভাবে কোনো সংজ্ঞায়িত উত্তর নেই, তাই এটি একটি রানটাইম সিমান্টিক এরর)। আরেকটি উদাহরণ:arr[10]যেখানেarr-এর মাত্র ৫টি এলিমেন্ট আছে (ইনডেক্স আউট অফ রেঞ্জ) — গঠন ঠিক, কিন্তু "কোন মান রিটার্ন হবে?" প্রশ্নের কোনো অর্থপূর্ণ উত্তর নেই। -
পরীক্ষা করুন: উপরের কোড সেলে
tokens1-এর মান["(", "(", "3", "+", "5", ")"]করে Run চেপে দেখুনcheck_syntaxকী রিটার্ন করে এবং কেন।এই টোকেন লিস্টে দুটো
"("আছে কিন্তু মাত্র একটি")"— স্ট্যাক ট্রেস করলে: প্রথম"("পুশ (স্ট্যাক =["("]), দ্বিতীয়"("পুশ (স্ট্যাক =["(", "("]), শেষে")"একটি পপ করে (স্ট্যাক =["("])। লুপ শেষে স্ট্যাক খালি নয়, তাই ফলাফলFalse, "ম্যাচ না হওয়া '(' রয়ে গেছে"— উপরের প্র-০৩ এর মতোই যুক্তি, শুধু একটি অতিরিক্ত নেস্টিং লেভেল সহ।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৮টি পাঠ প্যারাডাইম, গ্রামার, লেক্সিং, পার্সিং, টাইপ সিস্টেম ও কোড জেনারেশন পর্যন্ত সম্পূর্ণ যাত্রা।
- আগের পাঠ L01 প্রোগ্রামিং ল্যাঙ্গুয়েজ ও কম্পাইলার ডিজাইন কী ও কেন গুরুত্বপূর্ণ — না পড়ে থাকলে আগে এটি দেখে নিন।
- পরের পাঠ L03 ট্রান্সলেটর — কম্পাইলার বনাম ইন্টারপ্রেটার বনাম হাইব্রিড (JIT) — সোর্স কোড থেকে এক্সিকিউশনের পুরো ছবি।
- Data Structures & Algorithms কোর্স সঙ্গী কোর্স উপরের সিনট্যাক্স চেকার একটি ক্লাসিক stack অ্যাপ্লিকেশন — সেই ডেটা স্ট্রাকচারের ভিত্তি এই কোর্সে শেখানো হয়েছে।
- সব Courses দেখুন ABCL TECH C, C++, Python, Java, JavaScript, DSA, DBMS, Discrete Mathematics, System Design, Cybersecurity, Cloud Computing & DevOps, Computer Networks, Operating Systems, Computer Architecture ও Programming Languages & Compiler Design — সব এক জায়গায়।