موضوع مقاله: تجزیه‌کننده | مخاطب: عمومی | لحن: دانشنامه‌ای | ساختار: عنوان، مقدمه، 3 بخش، جمع‌بندی | مقاله: | # تجزیه‌کننده | مقدمه: وظیفهٔ اصلی اسکنر این است که با خواندن کاراکترهای ورودی، توکن‌ها را تشخیص داده و برای parser ارسال نماید. | ## بخش 1: تجزیه‌کننده | علاوه بر این اسکنر می‌تواند محل‌های خالی و توضیحات(comments) موجود در برنامه اصلی را ضمن خواندن برنامه حذف نماید. به عبارتی دیگر در ورودی، رشته‌هایی وجود دارند که توکنِ یکسانی برای آن‌ها تشخیص داده می‌شود. به دنباله‌ای از نویسه‌ها که تشکیل یک توکن می‌دهند، واژه (Lexem) آن توکن می‌گویند. مثلاً اسکنر با دیدن علامت <در ورودی نیاز دارد که کاراکتر ورودی بعدی را نیز بخواند. در صورتی‌که این کاراکتر = باشد، در نتیجه توکن '<=' و در غیر اینصورت توکن ' <' تشخیص داده می‌شود. یکی دیگر از مشکلاتی که اسکنر با آن روبروست این است که در زبان‌هایی نظیر فرترن مثلاً محل خالی یا (space) بجز در رشته‌های کاراکتری، نادیده گرفته می‌شود. به عنوان مثال کلمهٔ Do در زبان فرترن را در دستور زیر در نظر بگیرید: do bi =۱٫۲۵ تا زمانی‌که به نقطهٔ اعشار در ۱٫۲۵ نرسیده باشیم نمی‌توان گفت که do در این دستور کلمه کلیدی نیست، بلکه بخشی از متغیری است که نام آن do bi است. به همین ترتیب در دستور do bi=۱٬۲۵ تا زمانی‌که علامت کاما دیده نشود، نمی‌توان گفت که این دستور یک حلقهٔ do است. | ## بخش 2: تجزیه‌کننده | در زبان‌هایی که کلمات کلیدی آن جزو کلمات رزرو شده نیستند، اسکنر نمی‌تواند کلمات کلیدی را از شناسه‌های همنام آن‌ها تشخیص دهد. ۲–۲- خطاهای واژه‌ای (Lexical Errors): به‌طور کلی خطاهای محدودی را اسکنر می‌تواند بیابد، زیرا اسکنر تمام برنامهٔ ورودی را یکجا نمی‌بیند بلکه هر بار قسمت کوچکی از برنامهٔ منبع را. به‌عنوان مثال هرگاه رشتهٔ fi در یک برنامهٔ C برای بار اول مشاهده شود، اسکنر قادر نیست تشخیص دهد که آیا fi یک املای غلط از کلمهٔ کلیدی if است یا نام یک متغیر است: fi (x==۳) از آنجایی که fi می‌تواند نام یک متغیر مجاز باشد، اسکنر این توکن را به‌عنوان یک شناسه به پارسر می‌فرستد تا اینکه پارسر در اینمورد تصمیم بگیرد. در این روش آنقدر از رشتهٔ ورودی حذف می‌شود تا اینکه یک توکن درست، تشخیص داده شود. سایر روش‌های تصحیح خطا (error recovery) عبارت‌اند از: a) حذف یک کاراکتر غیرمجاز (تبدیل:$= به :=) b) وارد کردن یک کاراکتر گم شده (مثلاً تبدیل: به :=) c) تعویض کردن یک کاراکتر غلط با یک کاراکتر درست (مثلاً تبدیل :: به :=) d) جابجایی دو کاراکتر مجاز (مانند =: به :=) ۲–۳- روشهایی جهت بهبود کار اسکنر: الف)استفاده از بافر: در بسیاری از زبان‌ها اسکنر برای تشخیص نهایی توکن‌ها و مطابقت دادن آن با الگوهای موجود، نیاز دارد که چند کاراکتر جلوتر را نیز مورد بررسی قرار دهد. از آنجایی که مقدار زیادی از زمان در جابجایی کاراکترها سپری می‌شود، از تکنیک‌های بافرینگ، برای پردازش کاراکترهای ورودی استفاده می‌گردد. در یکی از این تکنیک‌ها از یک بافر که به دو نیمهٔ n کاراکتری تقسیم شده‌است، استفاده می‌کنند (که در آن n تعداد کاراکترهایی است که در روی یک بلوک از دیسک جای می‌گیرند). به این ترتیب با یک فرمان read به جای خواندن یک کاراکتر، می‌توان n کاراکتر ورودی را در هر نیمهٔ بافر وارد کرد. | ## بخش 3: تجزیه‌کننده | در صورتی‌که ورودی شامل تعداد کاراکترهای کمتر از n باشد، بعد از خواندن این کاراکترها یک کاراکتر خاصِ eof نیز وارد بافر می‌گردد. کاراکتر eof بیانگر پایان فایل منبع بوده و با سایر کاراکترهای ورودی به نوعی تفاوت دارد. در ابتدا هر دو نشانه رو به اولین کاراکتر Lexem بعدی که باید پیدا شود اشاره می‌کنند. با این وجود در مواردی که جهت تشخیص یک توکن، نشانه روِ forward ناچار است بیشتر از طول بافر جلو برود، این روش درست کار نمی‌کند. در این دستور تا زمانی‌که کاراکتر بعد از پرانتز سمت راست را بررسی نکنیم، نمی‌توان گفت که declare یک کلمهٔ کلیدی است یا اسم یک آرایه‌است. درصورتی‌که به انتهای یک نیمه از بافر رسیده باشد، باید نیمهٔ دیگر را دوباره بار می‌کردیم. در الگوریتم فوق، همان‌طور که مشاهده شد، برای هر جلورَویِ نشانه رویِ forward، دو بار عمل مقایسه انجام می‌شود. | ## جمع‌بندی | برای این کار باید در انتهای هر نیمهٔ بافر، یک کاراکتر نگهبان قرار دهیم (نگهبان به عنوان قسمتی از برنامهٔ منبع نخواهد بود).