0% found this document useful (0 votes)
12 views90 pages

Come Back

Uploaded by

youtfa3
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views90 pages

Come Back

Uploaded by

youtfa3
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 90

‫طراحی اصول کامپایلر‬

‫مقدمه و معرفی کامپایلر توسط ( استاد مسائلی )‬

‫انواع زبانها از لحاظ درک انسان‬

‫زبانهایی مثل ‪ C# ،C+‬و ‪ ...‬برای انسان قابل فهم است‪.‬‬

‫‪ -۱‬زبان ماشین‪ :‬دادهها و دستورالعملها به صورت باینری هستند‪  .‬به لحاظ معماری ماشین‬

‫‪ -۲‬زبان اسمبلی‪ :‬برای پیاده سازی یک برنامه در این زبان استفاده از کلمات اختصاری استفاده میشود‪.‬‬

‫‪ -۳‬زبان سطح باال‪ :‬به زبان انسان نزدیکتر است و دارای ساختارهای و امکانات بیشتری برای استفاده برنامه‬

‫نویس است‪.‬‬

‫ساختار برای هر ماشین ‪ ۰‬و ‪۱‬‬

‫‪ -۱‬براساس نوع معماری ماشینها ‪ ‬زبان ماشینها متفاوت است تعداد و نوع دستورالعملها‬

‫به نوع پردازنده وابسته است‪.‬‬

‫‪ -۲‬در زبان اسمبلی با مقادیری که ثباتها کار میکند‪.‬‬

‫به زبان ماشین نزدیکتر است‪.‬‬

‫‪x=x+y‬‬ ‫کار با دو متغیر‬

‫‪ADD‬‬ ‫‪Ax, Bx‬‬ ‫‪Ax = Ax + Bx‬‬

‫‪ -۳‬سرعت رسیدن به جواب نسبت به زبان اسمبلی کمتر است‪.‬‬

‫سرعت اجرا در زبان ماشین باالست‪.‬‬

‫‪1‬‬
‫{ )‪for (i = 0; i < 0; i++‬‬

‫}‬

‫به چه صورت زبان اسمبلی یا زبان سطح باال اجرا میشود؟ هدف هر برنامهای باید به زبان ماشین دربیاید‪.‬‬

‫استفاده از مفسر یا کامپایلر‪.‬‬

‫روشهای اجرای برنامههای سطح باال‬

‫متلب فوترن‬ ‫‪ ‬استفاده از مفسر‬

‫‪ C#‬ابتدا کامپایلر ‪ C++‬نصب میشود‪.‬‬ ‫‪ ‬استفاده از کامپایلر‬

‫استفاده از مفسر‬

‫برنامه شما را به صورت دستورالعمل دستورالعمل اجرا میکند‪.‬‬

‫خطا‬

‫برنامه مبدأ‬ ‫واکشی یک دستور‬ ‫اجرای دستور‬ ‫پایان‬

‫دستورالعمل بعدی‬

‫برنامه خط به خط اجرا میشود‪.‬‬

‫مترجم زبان بیگانه در یک کنفرانس ‪ ‬جمله به جمله ترجمه میکند‪.‬‬

‫فایل جداگانهای تولید نمیشود‪.‬‬

‫همیشه باید مفسر را همراه داشته باشیم‪.‬‬

‫‪2‬‬
‫مثل مترجم زبان انگلیسی که جمله به جمله تفسیر میکند‪ .‬در زبان کامپایلری یک فایل ‪ exe‬ایجاد میکند‬

‫و این فایل را هرکجا ببریم اجرا میشود و یکی از معایب زبان مفسری همین است که همه جا باید مفسر را‬

‫همراه داشته باشید‪ .‬چون نیاز به اجرای مجدد داریم‪.‬‬

‫مزایای استفاده از مفسر‬

‫‪ ‬سهولت در اشکالزدایی ‪ ‬برنامههایی که مدام در حال تغییر است ‪ ‬رمان ساخت نرم افزار را‬

‫کاهش میدهد‪.‬‬

‫‪ ‬قابلیت انعطاف باال‬

‫‪ ‬پیاده سازی آسان‬

‫‪ ‬قابلیت حمل ‪ ‬هر کجا مفسر باشد مستقل از نوع سخت افزار روی هر ماشینی میتوان اجرا کرد‪.‬‬

‫معایب‬

‫برنامه مبدا‬ ‫‪ ‬تکرار تفسیر ‪ ‬چون باید خط به خط اجرا شود‪.‬‬

‫مفسر‬

‫سخت افزار‬

‫‪ ‬سرعت اجرا پائین ‪ ‬چون برنامه به طور مستقیم روی سخت افزار اجرا نمیشود و یک الیه میانی‬

‫بین سخت افزار و برنامه است‪.‬‬

‫‪ ‬نیاز به مفسر‬

‫‪ ‬دسترسی به کد منبع ‪ ‬حتماً باید کد منبع در اختیار استفاده کننده قرار گیرد‪.‬‬

‫کامپایلر‬

‫کامپایلر برنامهای است که برنامههای یک زبان برنامهنویسی را‪ ،‬از زبان مبدأ(همان زبان) به زبان هدف ترجمه‬

‫میکند‪.‬‬

‫‪3‬‬
‫برنامه مبدأ‬ ‫ورودیها‬

‫کامپایلر‬ ‫گزارش خطا‬ ‫سخت افزار را اجرا میکند‬ ‫برنامه هدف‬

‫برنامه هدف‬ ‫خروجی‬

‫فایلی که روی ‪ HW‬اجرا شود ‪ ‬در صورتیکه هیچ خطایی نداشته باشد‪.‬‬

‫برنامه به زبان ماشین ترجمه میشود و میتوان روی سخت افزار اجرا شود برای همین است که میگوئیم‬

‫سرعت زبانهایی که کامپایلری هستند نسبت به زبانهای مفسری بیشتر است‪.‬‬

‫مزایای استفاده از کامپایلر‬

‫‪ ‬سرعت اجرای باالتر از مفسر‬

‫برنامهای که اجرا میکنیم روی هر کامپیوتری ببریم‬ ‫‪‬‬ ‫‪ ‬اجرای برنامه بعد از کامپایل روی ماشین‬

‫بدون نیاز به کامپایلر اجرا میشود‪.‬‬

‫‪ ‬عدم نیاز به کد منبع بعد از کامپایل ‪ ‬کد اجرایی را به هرکسی بدهیم‪.‬‬

‫‪ ‬عدم نیاز به کامپایل مجدد ‪ ‬یک بار که ساخته میشود دیگر نیازی به اجرای برنامه نیست برخالف‬

‫مفسر که هر زمان الزم است اجرا شود باید مفسر اجرا میشد‪.‬‬

‫معایب استفاده از کامپایلر‬

‫‪ ‬زمانبر بودن اشکالزدایی چون کل برنامه باید بررسی شود‪.‬‬

‫‪ ‬قابلیت حمل پائین ‪ ‬وقتی کامپایل میشود از زبان مبدأ به زبان ماشین تفسیر میشود‪ .‬چون زبان‬

‫همه ماشینها ‪ 0‬و ‪ 1‬است ولی باهم فرق دارند برای هر ماشین خاص کامپایلر خاص داریم‪(.‬فایل‬

‫اجرایی ‪ – exe‬ممکن است روی همه سیستمها اجرا نشود‪.‬‬

‫‪ ‬پیچیدگی پیاده سازی کامپایلر‬

‫‪4‬‬
‫جلوبندی و عقب بندی کامپایلر‬

‫جلوبندی‪ :‬تجزیه برنامه مبدأ به قطعات تشکیل دهنده و ایجاد یک نمایش میانی از برنامه مبدأ‬

‫عقب بندی‪ :‬ایجاد برنامه هدف با استفاده از نمایش میانی و اطالعات جدول نماد‬

‫جدول نماد در طول روال کامپایل تشکیل میشود‪ .‬مثالً اطالعات شناسه در جدول قرار میگیرد که در بخش‬

‫برنامه مبدأ‬ ‫های بعدی بتوان از آن استفاده نمود‪.‬‬

‫نمایش میانی‬ ‫زبان‬

‫برنامه هدف‬ ‫زبان ماشین‬

‫به تعداد ‪ n‬ماشین ‪ n ‬کامپایلر داشته باشیم‪.‬‬

‫فرض ‪ n‬زبان برنامه نویسی داریم و ‪k‬تا ماشین مختلف داشته باشیم بر روی اجرای هر زبان روی هر ماشین‪.‬‬

‫تعداد کامپایلر ‪.n × k ‬‬

‫برای حل این مشکککل ‪ ‬از نمایش میانی اسککتفاده میکنیم یعنی برنامه هدف از نمایش میانی اسککتفاده می‬

‫زبان فارسی‬ ‫کنند‪.‬‬

‫زبان انگلیسی‬ ‫زبانی که همه قبولش دارند‬

‫به هر زبان ترجمه میشود‬

‫‪ ‬سادگی طراحی‬

‫‪ ‬استقالل جلوبندی از زبان مقصد‬

‫‪ ‬استقالل عقب بندی از زبان مبدأ‬

‫‪ ‬کاهش پیچیدگی‬

‫‪ ‬افزایش قابلیت استفاده مجدد‬

‫‪5‬‬
‫‪ ‬افزایش سرعت تولید کامپایلر برای سخت افزار جدید و زبانهای جدید‬
‫برنامه‬
‫مبدأ‬

‫جلوبندی‬

‫کد میانی‬

‫عقب بندی‬

‫برنامه هدف‬

‫توجه‪ :‬بعضی از زبانها از مفسر برای اشکالزدایی ساده و برای تولید کد منبع از کامپایلر استفاده میکند‪.‬‬

‫برنامه مبدأ‬

‫جلوبندی‪1‬‬ ‫جلوبندی‪2‬‬ ‫جلوبندی‪3‬‬ ‫‪...‬‬ ‫جلوبندی زبان ‪n‬‬

‫کد میانی‬

‫عقب بندی برای‬ ‫عقب بندی برای‬ ‫عقب بندی برای‬ ‫‪...‬‬ ‫عقب بندی برای‬
‫ماشین ‪1‬‬ ‫ماشین ‪2‬‬ ‫ماشین ‪3‬‬ ‫ماشین ‪n‬‬

‫ویژوال بیسیک از مفسر و کامپایلر استفاده میکند‪ .‬قابلیت حمل ویژگی دیگری از مفسری استفاده میکند‪.‬‬

‫‪6‬‬
‫‪ Lisp‬و متلب ‪ ‬مفسری‬

‫‪  C++‬کامپایلری‬

‫جاوااسکریپت به طور مفسری توسط مرورگرها اجرا میشود ‪ ‬در هر سیستم سخت افزاری اجرا میشوند‪.‬‬

‫جاوا ‪ ‬مفسر و کامپایلر‬

‫برنامه را به زبان ‪ JVM‬ماشین مجازی جاوا ترجمه میکند حاال ‪ JVM‬هرکجا باشد روی هر سخت افزاری این‬

‫پالتفرم باشد اجرا میشود و یک مفسر است‪.‬‬

‫‪  common language Runtime CLR  C#‬نقش ماشین مجازی را بازی میکند پالتفرمی است که‬

‫با سخت افزار در ارتباط است‪ .‬فایل اجرایی هم بوجود میآید که در مراحل بعدی نیاز به اجرای دوباره برنامه‬

‫نداریم‪.‬‬

‫‪ CLR‬نقش ماشین مجازی را ایفا میکند‪ .‬اما برای اجرا باید آن فریم ورک حتماً نصب باشد مثالً برای‪ CF‬حتماً‬

‫‪ .net fromwork‬نصب باشد‪.‬‬

‫الزاما همه مراحل در یک کامپایلر وجود ندارد‬ ‫فازهای مختلف کامپایلر‬

‫‪ ‬تحلیلگر لغوی‬

‫‪ ‬تحلیلگر نحوی‬

‫‪ ‬تحلیلگر معنایی‬

‫‪ ‬مولد کد میانی‬

‫‪ ‬بهینه سازی کد میانی‬

‫‪ ‬مولد کد‬

‫‪ ‬بهینه ساز مولد کد‬

‫‪7‬‬
‫) ‪(Lexical Analyzer‬‬ ‫تحلیلگر لغوی‬

‫‪ ‬بخش باالیی کامپایلر که به برنامه مبدأ دسترسی مستقیم دارد‪.‬‬

‫‪ ‬تشخیص نوع لغات برنامه و در صورت عدم خطا در دیکته لغت‪ ،‬ارسال آن برای تحلیلگر نحوی‬

‫کاراکتر بعدی‬ ‫لغت بعدی‬


‫تحلیلگر لغوی‬ ‫تحلیلگر نحوی‬
‫برنامه مبدأ‬

‫پیام خطا‬

‫تحلیلگر لغوی در قالب توکنها‪،‬‬

‫‪ -‬کاراکتر به کاراکتر از برنامه مبدأ میخواند و نشانه یا ‪ token‬را برای تحلیلگر نحوی ارسال میکند در واقع‬

‫تحلیلگر نحوی با فراخوانی تحلیلگر لغوی این درخواستها را ارسال میکند‪ .‬تحلیلگر لغوی این لغتها را‬

‫در خواست میکند و تحلیلگر لغوی آن نشانه را همراه با ویژگیهایش میخواند و برای تحلیلگر نحوی ارسال‬

‫میکند‪.‬‬

‫‪Int Temp‬‬ ‫>کلمه کلیدی و ‪< temp, Id>, < if‬‬ ‫ارسال میکند‬

‫‪if‬‬ ‫‪i+f‬‬

‫کلمه کلیدی‬ ‫نشانه – کلمه رزرو شده – کلمه کلیدی‬

‫اگر تحلیلگر لغوی جملهای را بخواند و به لحاظ امالیی و دیکته نادرست باشد خطا میدهد‪.‬‬

‫مثال متغیرها باید با حروف شوند‪.‬‬

‫‪8‬‬
‫تحلیلگر نحوی (‪)syntax Analyzer‬‬

‫‪ ‬تشخیص ظاهری فرم برنامه و بررسی صحت و درستی ترتیب لغات برنامه مبدا‬

‫‪ ‬ایجاد ساختار درختی(درخت تجزیه) از خروجی تحلیلگر لغوی‬

‫تحلیلگر نحوی یک درخت تجزیه از نشانهها که برایش ارسال میکند به طور ضمنی ارسال میکند‪.‬‬

‫(حافظه ای وجود ندارد که در آن دخیره شود)‬

‫تجزیه کننده‪ -‬پارسر‬

‫مثال‪:‬‬

‫صابون‬

‫×‬ ‫است‬ ‫شوینده‬ ‫تحلیلگر لغوی‪:‬‬


‫سابون‬

‫توکن‬ ‫توکن‬ ‫توکن‬

‫تحلیلگر نحوی‪ :‬شوینده صابون است‪× .‬‬

‫نحوه قرار گرفتن توکنها در کنار یکدیگر را بررسی میکند‪.‬‬

‫) ‪For (i=0; i<10; i++‬‬ ‫گیرد‪.‬گر نحوی خطا میبه لحاظ لغوی درست است اما تحلیل‬

‫{‬ ‫اگر نباشد لغوی درسته اما نحوی غلط‬

‫‪x+y=z‬‬ ‫‪z=x+y‬‬

‫}‬

‫‪9‬‬
‫تحلیلگر معنایی )‪(semantic Analyzer‬‬

‫‪ ‬تعیین صحت مفهوم جمالت‬

‫‪ ‬استفاده از اطالعات موجود در درخت تجزیه و جدول نماد برای بررسی مطابقت معنایی برنامه با‬

‫تعریفهای زبان ‪ ‬دستور با ساختار آن زبان برنامه نویسی مغایرت نداشته باشد‪.‬‬

‫لغوی درست ‪‬‬ ‫مثال‪ :‬صابون شوینده را خورد‪.‬‬

‫نحوی دست ‪‬‬

‫معنایی نادرست ×‬
‫;‪Int x‬‬
‫;‪Char ch‬‬

‫گر معناییتحلیل ‪x = x + ch;  error‬‬

‫صحیح‬ ‫کاراکتر‬

‫‪ -1‬بررسی هماهنگی پارامترها‪:‬‬

‫{ )‪int f (int x , int y‬‬ ‫یکسان‬ ‫نوع پارامترها‬

‫;‪return x + y‬‬ ‫باشد‬ ‫تعداد پارامترها‬


‫{‬

‫{ )( ‪Int main‬‬
‫;‪Int a =1; int b=3; float c = 1.5‬‬
‫;)‪a = f (b, c‬‬
‫;)‪a = f (a, b, c‬‬

‫‪10‬‬
‫‪ -2‬کنترل نوع عملوندها‪( :‬تبدیل نوع هم میتوان انجام داد)‬

‫;‪int x‬‬
‫;‪float y, z‬‬
‫;‪z = x + y‬‬

‫‪ -3‬خطای متغیرهای تعریف نشده‬

‫;‪int x‬‬ ‫متغیری تعریف شده و حافظه در نظر گرفته شده است ولی از آن‬

‫;‪y = x‬‬ ‫برنامه استفاده نشده است‪ Worning .‬دهد نه خطامی‬

‫خطا‬

‫مولد کد میانی )‪(Intermediate Code‬‬

‫لغوی‬ ‫‪ ‬از خروجی تحلیلگر معنایی‪ ،‬کد میانی تولید میشود‪.‬‬


‫نحوی‬ ‫‪ ‬زبان ماشین‪ ،‬مربوط به یک ماشین مجازی‬
‫معنایی‬ ‫‪ ‬هر کامپایلر میتواند کد میانی خاص خود را داشته باشد‪.‬‬

‫خروجی‬

‫کد میانی‬

‫زبان ماشین مربوط به یک ماشین مجازی میتواند باشد‪.‬‬

‫یک آدرس‪ ،‬دو آدرس‪ ،‬سه آدرس ‪ ‬دستورالعملهای‬

‫آدرس‬ ‫آدرس‬ ‫ثباتی که نتیجه در آن است‬

‫کد عمل‬ ‫نتیجه ‪ ،‬عملوند ‪ ، 2‬عملوند ‪1‬‬


‫‪x=y+z‬‬

‫‪ADD y, z, x‬‬

‫فرض به تعداد کافی ثبات وجود دارد‪.‬‬

‫‪11‬‬
‫بهینه سازی کد میانی‬

‫‪ ‬اعمال تغییرات در برنامه بدون تغییر در عملکرد آن به منظور افزایش سرعت و کاهش حافظه‬
‫مصرفی‬
‫)‪x = int to real (p1‬‬
‫‪y = p2 + x‬‬
‫‪z =p3 + y‬‬ ‫‪int to real 20, , x‬‬ ‫اعشاری‬

‫پارامتر‪ 1‬اگر عدد باشد و مشخص باشد‬ ‫دستورالعمل ‪3‬آدرسه باشد‬ ‫‪mult p2, x, y‬‬ ‫‪mult p2, 20.0, y‬‬

‫‪ADD p3, y, z‬‬ ‫‪ADD p3, y, z‬‬


‫خودش‬

‫مولد کد نهایی‬

‫‪ ‬کد میانی بهینه شده را به زبان اسمبلی ترجمه میکند‪.‬‬

‫‪ ‬توسط اسمبلر به زبان ماشین ترجمه میشود‪.‬‬

‫‪ ‬در این کد جدای تسریع در زمان از ثباتهای پردازنده استفاده میشود‪.‬‬

‫‪ ‬از ارجاعات اجتناب کنیم‪ .‬با کدهای ساده کار کنیم‪.‬‬

‫دستور اسمبلی‬ ‫های پردازنده ثبات‬

‫‪Move R1, P2‬‬

‫‪Mult‬‬ ‫‪R1, 20.0‬‬

‫‪Move R2, P3‬‬ ‫شود‪.‬با اسمبلر به زبان ماشین تبدیل می‬

‫‪ADD R1, R2‬‬

‫‪Move Z, R1‬‬

‫‪12‬‬
‫‪X=y+2*z‬‬

‫تحلیلگر لغوی‪ ‬مشکلی ندارد و ‪token‬ها را برای«؟؟؟» ارسال نماید‬

‫شناسهها‬ ‫‪‬‬ ‫‪Id1 = Id2 + 2 * Id3‬‬

‫تشکیل درخت تجزی بطور ضمنی‬ ‫تحلیلگر نحوی ‪‬‬

‫=‬

‫‪Id1‬‬ ‫‪+‬‬

‫‪Id2‬‬ ‫*‬

‫‪2‬‬ ‫‪Id3‬‬

‫همان درخت تجزیه را داریم‬

‫تحلیلگر معنایی‬ ‫ولی عدد ‪ 2‬به اعشاری تبدیل میشود‬

‫=‬

‫‪Id1‬‬ ‫‪+‬‬

‫‪Id2‬‬ ‫*‬

‫‪Int to real‬‬ ‫‪Id3‬‬

‫‪2‬‬

‫‪13‬‬
‫‪Front END‬جلوبندی‬ ‫‪‬‬

‫توجه!‬

‫‪ Back END‬عقببندی‬

‫از یکسری متغیر استفاده میکنیم‪  .‬مولد کد میانی‬


‫)‪Temp = int to real (2‬‬

‫متغیرهای کمکی‬ ‫‪Temp2 = Id3 * temp 1‬‬ ‫بهینه سازی کد میانی‬


‫‪Temp 3 = temp2 + Id2‬‬
‫‪Id 1 = temp3‬‬

‫بهینه سازی کد میانی‬


‫‪Temp1 = Id3 * 2.0‬‬

‫کد بهینه شده‬


‫‪Id1 = Id2 + Temp 1‬‬

‫مولد کد نهایی‬

‫‪Move Ax, Id3‬‬


‫‪Mult Ax, 2.0‬‬

‫سیستم اعداد باشد شارپ می گذاریم‬ ‫آدرس دهی مستقیم ‪#2.0‬‬

‫‪Move Bx, Id2‬‬ ‫بهینه ساز کد میانی‬

‫‪ADD Ax, Bx‬‬ ‫عقب بندی کامپایلر‬ ‫کد بهینه شده‬

‫‪Move Id1, Ax‬‬ ‫مولد کد نهایی‬

‫‪Z = 4*y + 6*x‬‬

‫‪14‬‬
‫تحلیلگر لغوی‬

‫‪ ‬فاز اول از فرایند کامپایل‬

‫‪ ‬خواندن کاراکترهای برنامه مبدأ – گروه بندی در قالب لغتها و ایجاد دنبالههایی از نشانهها برای هر‬

‫لغت است‪.‬‬

‫‪ ‬ارسال نشانهها برای تجزیه کننده (تحلیلگر نحوی)‬

‫فراخوانی توکن‬ ‫‪get next token‬‬

‫(پارسر) تجزیه کننده‬

‫برنامه مبدأ‬ ‫کاراکتر بعدی‬ ‫نشانه ها‬


‫تحلیلگر لغوی‬ ‫تحلیلگر نحوی‬

‫بصورت بسته بندی‬ ‫متغیر‪ ،‬شناسه‪ ،‬رزرو شده است‬

‫شده‪ ،‬تحلیلگر نحوی‬ ‫جدول نماد‬

‫تحلیلگر نحوی‪ ،‬تحلیلگر لغوی را فراخوانی میکند و درخواست نشانه میکند‪.‬‬

‫تحلیلگر نحوی با ارسال دستور ‪ get next token‬درخواست نشانه میکند و تحلیلگر لغوی را فراخوانی می‬

‫کند‪ .‬تحلیلگر لغوی وقتی لغتی را میخواند در جدول نماد بنویسید و لغت را در قالب توکن برای تحلیلگر‬

‫نحوی ارسال میکند(شناسه – رزرو شده و‪ ...‬در قالب بستهبندی شده) ارسال میکند‪.‬‬

‫پردازشهای تحلیلگر لغوی‬

‫پویش‪:‬شامل پردازش سادهای است که نیازی به تولید نشانه ندارد‪ .‬مانند تشخیص توضیحات‪ ،‬حذف‬

‫کاراکترهای فضای خالی متوالی ‪  .....‬در فرایند کامپایل نیازی نیست رویش کاری انجام شود(برای فضای‬

‫خالی هیچ توکنی تولید نمیشود هیچ نشانهای ساخته نمیشود)‬

‫‪15‬‬
‫تحلیل لغوی‪ :‬استخراج نشانهها از خروجی پویشگر(تحلیلگر لغوی)‬

‫‪Int x‬‬

‫;‪x = x + 2‬‬

‫;‪cout << x‬‬

‫ورودی تحلیل گر لغوی‬


‫کاراکتر به کاراکتر است‬

‫;‪Int x; \n x = x + 2; \n cout<< x‬‬


‫خط بعدی‬ ‫خط بعدی‬

‫یکی یکی میخواند و نشانهها را استخراج میکند – تحلیلگر لغوی با جدول نماد در ارتباط بطور دوطرفه و‬

‫بررسی کند این لغت چی است‪.‬‬

‫انواع لغات برنامه مبدأ‬

‫کلمات کلیدی(رزرو شده)‪:‬لغاتی که در زبان مبدأ‪ ،‬مفهوم خاصی دارند مثال ‪ if‬را نمیتوان بعنوان نام‬

‫متغیر به کار برد‪.‬‬

‫عالئم نشانهگذاری‪:‬عالئمی که به منظور نشانهگذاری خاصی در زبان مبدأ کاربرد دارند‪.‬‬

‫«؟؟؟»ویرگول‪‬پایان دستور در ‪ } .C++‬آکوالد یک بلوک برنامه را مشخص کنیم‪ ] .‬براکت در آرایه‬

‫عملگرها‪ :‬برای انجام عملیات مساوی‪ ،‬مقایسه و منطق ‪ ...‬در زبان مبدأ کاربرد دارد‪ >(.‬و < ‪)or ،and ،‬‬

‫شناسهها‪ :‬نام متغیرها‪ ،‬توابع‪ ،‬کالسها‪ ،‬آرایهها در برنامه مبدأ‬

‫‪const‬‬ ‫ثابتها‪ :‬مقادیر عددی‪ ،‬کاراکتری ثابت در برنامه‬

‫توضیحات‪ :‬برای خوانایی بیشتر برنامه مبدأ است‪ ،‬توسط کامپایلر نادیده گرفته میشود‪.‬‬

‫‪16‬‬
‫; ‪int i , j‬‬ ‫مثال‪ :‬برنامهای به زبان ‪c++‬‬

‫;‪Float 2j‬‬ ‫کلمه کلیدی ‪ int‬شود‪.‬گر نحوی ارسال میدر قالب توکن برای تحلیل‬

‫)‪If (i== j‬‬ ‫شناسه ‪i‬‬

‫{‬ ‫شناسه‪j‬‬

‫;‪i=0‬‬ ‫کلمه کلیدی ‪float‬‬

‫}‬ ‫خطای لغوی ‪2j‬‬

‫کلمه کلیدی ‪if‬‬

‫‪.‬‬
‫‪.‬‬
‫برنامه زیر صحیح نیست اما در فاز اول(تحلیل لغوی) صحیح است‪.‬‬

‫{‬ ‫خواهد آکوالد بسته می‪ ‬آکوالد باز‬

‫;‪Int i‬‬

‫;‪{y=2‬‬ ‫‪an bn‬‬ ‫تعداد‪ b‬و ‪ a‬باهم برابر باشد‬

‫;‪x‬‬ ‫{{‬ ‫}}‬ ‫گر نحویدر تحلیل‬

‫تعداد آکوالد باز و بسته باید باهم مساوی باشد‪  .‬در تحلیلگر نحوی بررسی میشود‪.‬‬

‫نحوه برخورد تحلیلگر لغوی با خطا(کامپایلر در مواجه خطا چه میکند)‬

‫توقف‪ :‬در این روش تحلیلگر لغوی پس از کشف اولین خطا متوقف میشود‪.‬‬

‫‪ -‬تعداد دفعات کامپایل در این روش زیاد است‪.‬‬

‫‪17‬‬
‫‪ -‬زمان تولید نرم افزار افزایش مییابد‪.‬‬

‫پوشش خطا‪ :‬در این روش پس از کشف یک خطای لغوی تحلیلگر متوقف نمیشود‪ ،‬بلکه به کار خود ادامه‬

‫میدهد‪ .‬کل خطاهای برنامه را گزارش میکند‪.‬‬

‫اصالح خط به وسیله کامپایلر‪:‬‬

‫مثال‪:‬‬

‫حذف کاراکتر غیر مجاز‬


‫→ ;‪Int 2xy‬‬ ‫‪int xy‬‬
‫; ‪int x @ y‬‬ ‫→‬ ‫;‪in t x * y‬‬ ‫جایگزین کاراکتر مجاز به جای غیر مجاز‬

‫‪x=:y‬‬ ‫→‬ ‫‪x: = y‬‬


‫اضافه کردن کارکتر‬
‫→ )‪if (x = y‬‬ ‫)‪if (x == y‬‬
‫خطای منطقی ← برنامه کامالً اجرا میشود ولی منطق برنامه اشتباه است‪ .‬خطای منطقی و خطای کمپایلری‬

‫نیست اگر اینجا اضافه کنیم خطا میگیرد‪.‬‬

‫نشانهها )‪(Token‬‬

‫‪ ‬در ورودی تحلیلگر نحوی عالوه بر لغات‪ ،‬باید نوع هر لغت را نیز مشخص کنیم‪ .‬برای ایجاد هماهنگی بین‬

‫تحلیلگر نحوی و لغوی از نشانه )‪ (Token‬استفاده میکنیم‪.‬‬

‫‪ ‬در واقع نشانه‪ ،‬عالمتی است که بین تحلیلگر لغوی و نحوی توافق شده است‪.‬‬

‫تشخیص نشانه به لغات‬

‫کلمات کلیدی برای هر کلمه کلیدی یک شانه مجزا در نظر گرفته میشود‪ .‬مثالً برای کلماتی مثل ‪else, for,‬‬

‫‪ while, if‬یک شانه همراه وجود دارد‪.‬‬

‫اگر کامپایلر را با زبان ‪ C ++‬بنویسیم برای هر توکن یک عدد که توافق شده در نظر بگیریم‪.‬‬

‫‪18‬‬
‫‪# define‬‬ ‫‪IF – TK‬‬ ‫مقدار عددی‬
‫…………‬
‫‪# define‬‬ ‫‪WHILE - TK‬‬ ‫………‬
‫‪# define‬‬ ‫‪ELSE - TK‬‬ ‫………‬
‫‪# define‬‬ ‫‪FoR - TK‬‬ ‫‪……...‬‬
‫عالئم‪ :‬برای هر کدام از عالئم یک نشانه همراه در نظر گرفته میشود‪ .‬مثالً برای عالمتهای تک کاراکتری از‬

‫کدام یک عالمت‪ ،‬به عنوان نشانه )‪ (token‬استفاده کنیم‬

‫‪# define‬‬ ‫‪ASSIGN – TK‬‬ ‫‪………….‬‬


‫‪# define‬‬ ‫‪DOT – TK‬‬ ‫‪………….‬‬
‫‪# define‬‬ ‫‪RARANTES – Tk ………….‬‬

‫عملگرها‪ :‬همانند عالئم برای عملگرها نیز میتوان یک نشانه مجزا در نظر گرفت و برای عملگرهای یک‬

‫کاراکتری ؟ را به عنوان نشانه )‪ (token‬در نظر گرفت‪.‬‬

‫‪ # define‬مساوی‬ ‫‪EQU – TK‬‬ ‫‪…………..‬‬

‫‪ # define‬مخالف‬ ‫‪NOT – EQU – TK‬‬ ‫……………‬

‫‪ # defin‬کمتر‬ ‫‪LESS – TK‬‬ ‫‪………….‬‬

‫شناسهها‪ :‬تحلیلگر لغوی برای شناسهها فقط یک نشانه در نظر میگیرد‬

‫انتخاب‬
‫عملگر‬
‫‪ Dentifier token‬داریم با شناسه‬ ‫شناسه ‪ y‬با شماره ‪ 2‬داریم‬
‫‪1‬‬
‫‪X=y‬‬ ‫تحلیلگر لغوی‬ ‫> ‪< ID – TK , L > < ASSIGN > < ID – TK, 2‬‬

‫‪x‬‬ ‫‪y‬‬

‫اندیس‬ ‫لغت‬
‫‪1‬‬ ‫‪x‬‬
‫‪2‬‬ ‫‪y‬‬
‫جدول نماد‬

‫ثوابت مطابق با نوع ثابت تحلیگر لغوی یک نشانه را برای تحلیلگر نحوی ارسال میکند‬

‫‪19‬‬
‫فضاهای خالی و توضیحات فضاهای خالی و توضیحات بدلیل بیتأثیر بودن در نتیجه برنامه توسط تحلیلگر‬

‫ال نشانهای برای تحلیلگر نحوی ارسال نمیکنند‪.‬‬


‫لغوی حذف میشوند و عم ً‬

‫رشتهها و زبانها‪ :‬برای طراحی تحلیلگر لغوی یا اسکنر لغات را با استفاده از عبارات منظم و با قاعده پیاده‬

‫کنیم و بعد ماشین متناهی پیادهسازی کنیم که تحلیلگر لغوی را پیادهسازی کنیم آیا دیکته با ساختارها‬

‫متناسب است مثالً طراحی یا ‪ DFA‬ممکن است‬

‫الف‪ :‬مجموعه محدودی از نمادها (حروف و کارکترها) را الفبا زبان گویند‪.‬‬

‫مثال‪ :‬همگی جزء حروف الفبا زبان است‬

‫)‪IF (x! = y‬‬


‫این یک رشته یا ساختار از زبانها است‪.‬‬

‫الفبا را با سیگما نمایش میدهند‪.‬‬

‫}‪Σ {0 , 1‬‬
‫}‪Σ {a , b , c‬‬
‫}… ‪Σ {a , b , c , d …, A , B , C, … [ , ] , { , } , 8 , α , ! ,‬‬
‫در زبان برنامهنویسی این الف زبان میشود‬

‫رشته‪ :‬دنباله متناهی از نمادهای الفبا را رشته گویند‬

‫رشته باید تابع قواعد آن زبان باشند‪.‬‬

‫‪Σ {0 , 1} ⇒ 101011101‬‬
‫‪Σ {a , b , c} ⇒ abcbb ≪ aaba‬‬

‫زبان مجموعهای از رشتهها بر روی یک الفبا را زبان گویند‪.‬‬

‫}… ‪= {λ , a, ab, abb, abbb, abbbb,‬‬ ‫*‪λ ⃓ ab‬‬ ‫𝑛𝑏‬ ‫‪𝑛 ≥ 0 ← 𝑏 ∗ 𝐿1‬‬
‫‪n=0→λ‬‬
‫‪= {abc, aa bb cc, aaa bbb ccc, …} 𝑎𝑛 𝑏 𝑛 𝑐 𝑛 ∶ 𝑛 ≥ 1𝐿2‬‬
‫‪= {W ∈ {𝑎 , 𝑏}∗ ∶ |𝑎| = |𝑏|} 𝐿3‬‬

‫تعداد ‪ b , a‬دو برابر‬

‫‪Abaabb‬‬ ‫‪abab‬‬ ‫‪aabb‬‬

‫‪20‬‬
‫عملیات بر روی زبانها‬

‫} ‪𝐿1 ∪ 𝐿2 = {𝑊: 𝑊 ∈ 𝐿1 𝑜𝑟 𝑊 ∈ 𝐿2‬‬ ‫اجتماع دو زبان‬

‫} ‪𝐿1 𝐿2 = {𝑎𝑣: 𝑎 ∈ 𝐿1 𝑎𝑛𝑑 𝑣 ∈ 𝐿2‬‬ ‫الحاق دو زبان‬


‫‪𝐿1 = 𝑎𝑛 𝑏 𝑛 +‬‬ ‫‪2‬‬
‫‪⇒𝐿1 𝐿2‬‬
‫⇒‬
‫𝑛‬ ‫‪𝑛+ 2‬‬
‫𝑎 𝑏 = ‪𝐿2‬‬
‫‪𝑎𝑛 𝑏 𝑛 + 2 𝑏 𝑛 𝑎𝑛 +‬‬ ‫‪2‬‬
‫‪= 𝑎𝑛 𝑏 2𝑛 + 2 𝑎𝑛 +‬‬ ‫‪2‬‬

‫تعداد ‪ b , a‬برابر و اول ‪ a‬بیاید‬

‫𝑛 𝑏 𝑛𝑎 = 𝐿‬
‫𝑛 𝑏 𝑛𝑎 ‪𝐿̅ = {𝑎 , 𝑏}∗ −‬‬
‫∗}𝑏 ‪ :{𝑎 ,‬تمامی رشتههای ممکن‬

‫𝐿 ∈ 𝑏𝑏𝑎 ⇐ 𝑎𝑏𝑏 ∋ 𝑅𝐿‬

‫𝐿 ‪𝐿̅ = 𝛴 ∗ −‬‬ ‫مکمل زبان‬

‫}𝐿 ∈ 𝑊 ‪𝐿𝑅 = {𝑊 𝑅 :‬‬ ‫برعکس‬

‫… ∪ ‪𝐿∗ = 𝐿0 ∪ 𝐿1 ∪ 𝐿2 ∪ 𝐿3‬‬ ‫استار‬

‫⋯ ∪ ‪𝐿+ = 𝐿1 ∪ 𝐿2 ∪ 𝐿3‬‬ ‫بستار‬


‫*‪L = ab‬‬ ‫… ‪a, ab, abb,‬‬
‫کوچکترین رشته = ‪ λ‬الندا‬

‫‪L* = ababba‬‬
‫‪L+ = a‬‬ ‫کوچکترین رشته‬

‫انواع زبانها‬

‫زبانهای منظم )‪ ← (Regular‬بیشترین محدودیت دارند (* برای هر زبان یک گراف وجود دارد)‬

‫زبانهای مستقل از متن )‪(Context free‬‬

‫زبانهای حساس به متن )‪(Context sensitive‬‬

‫زبانهای بدون محدودیت )‪(unrestricted‬‬

‫‪Reg ⊂ Content free ⊂ Context – sens ⊂ unres‬‬

‫‪21‬‬
‫زبانهای بدون محدودیت‬

‫زبانهای حساس به متن‬

‫زبانهای مستقل از متن‬

‫زبانهای منظم‬

‫گرامر‪:‬‬

‫گرامر مجموعهای از قواعد میباشد که ساختار جمالت یک زبان را مشخص میکند با استفاده از گرامر می‪-‬‬

‫توانیم تعلق یک رشته به زبان را مشخص کنیم‪ .‬هر گرامر با چهارتایی زیر مشخص میشود‪.‬‬

‫>‪G = <V, T, S, P‬‬


‫!‪δ‬‬ ‫نماد شروع‬

‫‪V:‬‬ ‫میتوان عمل اشتقاق را انجام داد توسعه داد → غیر پایانهها (متغیرها)‬

‫‪T:‬‬ ‫پایانهها‬

‫‪P:‬‬ ‫مجموعه متنهای از قواعد‬

‫مثال‪( ab* → abb :‬هر رشته را گرامر بپذیرد) یک گرامر بنویسیم (محدودیتی نمیگذاریم‪ :‬فرض)‬

‫‪S → aB‬‬
‫=‪P‬‬
‫‪B → bB ⃓ λ‬‬
‫}‪T = {a , b‬‬
‫}‪V = {S , B‬‬
‫حتماً با ‪ a‬شروع شود یا هیچ ‪ b‬یا هر تعداد ‪b‬‬

‫‪G:‬‬
‫‪E→E+T⃓T‬‬ ‫‪S: E‬‬ ‫}‪V: {E, T, F‬‬
‫‪T→T*F⃓F‬‬ ‫با اشتقاق‬ ‫}‪T = {+ , * , (,) , id‬‬
‫‪F → (E) ⃓ id‬‬

‫‪22‬‬
‫‪E‬‬
‫⃓‬
‫)‪(id + id * id‬‬ ‫این رشته با این گرامر به دست میآید‬
‫‪T‬‬
‫⃓‬ ‫‪E→T‬‬
‫‪F‬‬
‫‪T→F‬‬
‫(‬ ‫)‬ ‫)‪F → (E‬‬
‫‪E‬‬
‫‪E→E+T‬‬
‫‪E‬‬ ‫‪+‬‬ ‫‪T‬‬ ‫‪E→T‬‬

‫‪T‬‬ ‫‪T * F‬‬ ‫‪T→T*F‬‬


‫‪T→F‬‬
‫‪F‬‬ ‫‪F‬‬ ‫‪id‬‬
‫‪F → id‬‬

‫‪id‬‬ ‫‪id‬‬ ‫}‪L (G) = {W: S ⇒ W‬‬


‫)‪ :L (G‬زبان گرامر‪W ،‬هایی که با نماد ‪ s‬به آن برسیم‪.‬‬

‫انواع گرامر‬

‫گرامر خطی چپ ← غیرپایانه سمت چپ قرار دارد‬

‫گرامر منظم (نوع سوم) (گرامر خطی)‬

‫گرامر خطی راست ← غیر پایانه سمت راست قرار دارد‬

‫گرامر مستقل از متن (نوع دوم‬

‫گرامر حساس به متن (نوع اول)‬

‫گرامر بدون محدودیت (نوع صفر)‬

‫گرامر منظم (گرامرهای خطی)‬

‫مثال‪:‬‬

‫𝛽‪A → α‬‬
‫گرامر خطی راست‬ ‫*‪A,B𝝐V , α𝝐T‬‬
‫‪A→α‬‬
‫‪ :α‬پایانه ‪ :𝛽 ،‬غیر پایانه‬

‫‪23‬‬
‫‪S → aA‬‬
‫‪A → bS‬‬
‫‪S → ab‬‬

‫‪A → 𝛽α‬‬
‫گرامر خطی چپ‬ ‫*‪A,B𝝐V , α𝝐T‬‬
‫‪A→α‬‬

‫‪S → bbS │ aaS │aa │ bb‬‬ ‫گرامر خطی راست‪.‬‬

‫‪(aa + bb)+‬‬ ‫عبارت منظم‬

‫هر تعداد زوجهای ‪ aa‬و ‪ bb‬را میتوان کنار هم قرار داد‬

‫𝑎 ∗)𝑏 ‪𝐺1 = ({𝑆}, {𝑎 , 𝑏}, 𝑆 , 𝑃} → 𝑟 = (𝑎 ,‬‬


‫‪S → ab S │ a‬‬ ‫گرامر خطی راست‬

‫‪𝐺2 = ({𝑆, 𝑆1 , 𝑆2 } ,‬‬ ‫}𝑃 ‪{𝑎 , 𝑏}, 𝑆 ,‬‬


‫‪S → S1 ab‬‬

‫گرامر خطی چپ ‪𝑆1 → 𝑆1 𝑎𝑏 │ 𝑆2‬‬

‫𝑎 → ‪𝑆2‬‬
‫)*)‪r = (aab (ab‬‬
‫)‪G = (V, T, S, P‬‬
‫نه منظم راست نه خطی چپ‬

‫‪S→A‬‬
‫‪A → aB │ λ‬‬
‫‪B → Ab‬‬

‫گرامرهای مستقل از متن‬

‫سمت راست هر ترکیبی را میتوان قرار داد‪.‬‬

‫‪{A → a‬‬ ‫}*)‪A 𝝐 V , a 𝝐 (V ⋃ T‬‬


‫‪( :T‬حروف کوچک) پایانهها‬ ‫‪ :V‬غیر پایانهها‬

‫‪24‬‬
‫همه گرامرهای منظم مستقل از متن هستند‬

‫مثال‪:‬‬

‫‪S → aSb │A‬‬


‫𝑚 𝑏 𝑛𝑎‬ ‫𝑛 > 𝑚‬
‫‪A → bB │ b‬‬
‫توجه‪ :‬همزمان مستقل از متن و همزمان منظم را میتوانند توصیف کنند‬

‫‪S → aSa │ bSb‬‬


‫‪a bb a‬‬
‫‪S → aa │bb‬‬
‫}}‪L (G) = {wwR: W 𝝐 {a , b‬‬
‫گرامر حساس به متن ←سمت چپ و سمت راست هر قوانین آن ممکن توسط نمادهای پایانی یا غیرپایانی‬

‫احاطه شده باشد‪.‬‬

‫)‪G = (N , Σ , P , S‬‬
‫‪ :N‬متغیر ها‬

‫‪ :Σ‬ترمینالها‬

‫‪ :P‬قوانین‬

‫‪ :S‬نمادین‬

‫‪{a → B‬‬ ‫*)‪a , B 𝝐 (V ⋃ T‬‬ ‫‪aB → aa AB‬‬ ‫|𝐵| < |𝑎|‬


‫هر زبان منظمی‪ ،‬حساس به متن است ولی هر زبان حساس به متن‪ ،‬منظم نیست‪.‬‬

‫روشهای توصیف زبانهای منظم‪:‬‬

‫زبانهای منظم نقش مهمی در طراحی تحلیلگر لغوی دارند‬

‫روشهای توصیف زبانهای منظم‪:‬‬

‫گرامر منظم – خطی راست یا خطی چپ‬

‫عبارت منظم (با قاعده)‬

‫ماشین خودکار متناهی )‪ (Finite Slate wachine‬طراحی کنیم‪.‬‬

‫‪25‬‬
‫مثال‪:‬‬

‫}‪Σ {a , b‬‬
‫زمانی که حداکثر ‪ a ،3‬داشته باشد‬

‫عبارت منظم و با قاعده‬

‫∗ 𝑏 )𝜆 ‪(𝑎 + 𝜆) 𝑏 ∗ (𝑎 + 𝜆) 𝑏 ∗ (𝑎 +‬‬
‫روی ‪ b‬محدودیت نداریم ‪b‬ها تولید شوند یا نشوند‪.‬‬

‫مثال‪ :‬گرامر منظم‬

‫آیا زبان زیر منظم است؟‬

‫}‪{𝑎2𝑛 𝑏 2𝑚 + 1 : 𝑛 ≥ 0 , 𝑚 ≥ 0‬‬
‫𝑛‪ :𝑎2‬تعداد ‪ a‬زوج‬

‫‪ :𝑏2𝑚 + 1‬تعداد ‪ b‬فرد‬

‫‪ :𝑛 ≥ 0 , 𝑚 ≥ 0‬رابطهای نیست‪.‬‬

‫*‪ A → αB α 𝝐 T‬گرامر منظم‬

‫گرامر خطی راست‪:‬‬

‫‪S → aaS │ B‬‬


‫‪B → bbB │ b‬‬

‫عبارت منظم با قاعده‬

‫تعریف عبارت منظم روی الفبا‪:‬‬

‫مثال‪:‬‬

‫‪a‬‬
‫‪Σ {a, b, c} b‬‬ ‫‪λ‬‬
‫‪c‬‬ ‫‪ϕ‬‬

‫عبارت منظم‬ ‫عبارت منظم‬

‫‪ λ , ϕ , a 𝝐 Σ‬عبارت منظم هستند‬

‫اگر ‪ 𝑟1 , 𝑟2‬عبارت منظم و ) ‪ L (𝑟1 ) , 𝐿 (𝑟2‬زبانهای منظم مربوط به آنها باشد آنگاه‪:‬‬

‫‪26‬‬
‫‪ 𝑟1 + 𝑟2 )1‬نیز عبارت‪ ،‬منظم است‪.‬‬

‫‪ 𝑟1 , 𝑟2 )2‬نیز عبارت‪ ،‬منظم است‪.‬‬

‫‪ 𝑟1∗ )3‬نیز عبارت‪ ،‬منظم است‪.‬‬

‫‪ :𝑟1 │ 𝑟2‬عبارت اول انتخاب یا دوم همان ‪or‬است‪.‬‬

‫‪(a + b)* ab‬‬


‫در عبارت باال ‪ a , b‬منظم هستند‪ .‬و کل مجموعه هم منظم هستند‬

‫مثال‪ :‬عبارت منظم‬

‫عبارت منظم برای رشتههایی که حداکثر یک صفر دارند؟ }‪Σ = {0 , 1‬‬

‫هر تعداد یک‬ ‫*)‪(1)* (0 + λ) (1‬‬ ‫‪01111 , 110111 , 111 … 10‬‬


‫‪ 0‬یا ‪λ‬‬

‫عبارت منظم برای رشتههایی که هیچ دو صفر متوالی ندارند؟ }‪Σ = {0 , 1‬‬

‫*)‪(0 + λ) (10 + 1‬‬ ‫‪11 00 1‬‬ ‫‪11 00 000 11‬‬ ‫‪0 111 0‬‬
‫عبارت منظم برای }زوج = 𝑛 ‪[𝑎𝑎]∗ [𝑏𝑏]∗ + [𝑎𝑎]∗ 𝑎 [𝑏𝑏]∗ 𝑏 {𝑎𝑛 𝑏 𝑚 ∶ 𝑚 +‬‬

‫∗]𝑏𝑏[ ∗]𝑎𝑎[‪ :‬تعداد زوج و 𝑎 ∗]𝑎𝑎[‪ :‬تعداد فرد‪.‬‬

‫دو حالت وجود دارد اول ‪ a‬و بعد ‪ .1 . b‬تعداد ‪ b , a‬زوج باشد مجموع زوج‪ .2 .‬اگر تعداد ‪ b , a‬فرد باشد مجموع‬

‫زوج میشود‪.‬‬

‫آیا برای }‪ {𝑎𝑛 𝑏𝑛 : 𝑛 ≥ 0‬عبارت منظم وجود دارد؟‬

‫∗ 𝑏 ∗𝑎‬ ‫‪𝑎2 𝑏 4‬‬


‫برای زبان 𝑛𝑏 𝑛𝑎 عبارت منظم وجود ندارد چون یک زبان منظم نیست‪.‬‬

‫زوج = 𝑚 ‪𝑎𝑛 𝑏 𝑚 , 𝑛 +‬‬

‫مثال‪ :‬زبان مشخص توسط عبارتهای زیر را بنویسید‬

‫*)‪ ((0 + 1) (0 + 1)*)* 00 (0 + 1‬عبارت منظم‬

‫در عبارت باال *)*)‪(0 + 1)* 00 (0 + 1)* ← ((0 + 1) (0 + 1‬‬

‫‪27‬‬
‫زبانی روی الفبای }‪ {0 , 1‬که حداقل دو صفر متوالی دارند‬

‫زبان روی الفبا }‪ ،{a , b‬دقیقاً سه ‪.b‬‬

‫∗𝑎 𝑏 ∗𝑎 𝑏 ∗𝑎 𝑏 ∗𝑎‬
‫)‪(a + b) (a + b + c)* (a + c‬‬ ‫‪a (a │ b │ c)* c , b (a │ b │ c)* c‬‬
‫‪ 4‬فرم مختلف ابتدا یا با ‪ a‬یا ‪ b‬و انتهایی ‪ a‬یا ‪ c‬باشد‪.‬‬

‫∗ 𝑏𝑎 ∗𝑏 )𝜆 ‪ (𝑏∗ 𝑎𝑏∗ 𝑎𝑏∗ 𝑎𝑏∗ )∗ (𝑏∗ (𝑎 +‬تکلیف‬ ‫مراحل تولید 𝜆‬

‫دقیقاً ‪ a ،3‬و هر تعداد ‪ b‬که دلمان خواست‪.‬‬

‫∗) ∗𝑏𝑎 ∗𝑏 𝑎 ∗𝑏 𝑎 ∗𝑏(‪ :‬تمامی رشتهها روی الفبای ‪ b , a‬که تعداد ‪a‬ها بر ‪ 3‬بخشپذیر است‬

‫) ∗𝑏 𝜙 ∗ 𝑏 )𝜆 ‪ :(𝑏∗ 𝑎 𝑏∗ 𝑎 𝑏∗ 𝑎𝑏∗ ) (𝑏∗ (𝑎 +‬رشتههایی را تولید میکند که باقیمانده تقسیم تعداد ‪ϕ‬های‬

‫آنهای بر ‪ 3‬مخالف صفر است‪.‬‬

‫ماشین خودکار متناهی ← ابزاری که نشان میدهد زبانی منظم است‪.‬‬

‫ماشین خودکار متناهی یک رشته از یک زبان منظم را دریافت میکند‪ ،‬و در صورتیکه رشته متعلق به زبان‬

‫باشد آن را تصدیق میکند و در غیر این صورت آن را رد میکند‪ .‬ماشین خودکار متناهی دو نوع است‪:‬‬

‫‪ -1‬ماشین خودکار قطعی )‪ ← (DFA‬کامالً قطعی است که با حروف الفبا به چه حالتی میرسیم‪.‬‬

‫‪ -2‬ماشین خودکار غیر قطعی )‪ ← (NFA‬به ازای هر حروف چندین حرکت ممکن است‪.‬‬

‫ماشین خودکار غیرقطعی‬

‫ماشین خودکار قطعی را به صورت )‪ M = (Q , Σ , δ , q0 , F‬تعریف میکنیم‬

‫‪ Q‬مجموعه متناهی از حاالت‬

‫‪ Σ‬مجموعه متناهی از نمادها که الفبای زبان است‬

‫‪ δ‬تابع گذر‬

‫‪ q0‬حالت شروع‬

‫‪ F‬حالت یا حاالت نهایی ← ماشین رشته را پذیرفته‬

‫‪28‬‬
‫‪δ (qi , a) = qj‬‬
‫‪δ (qi , b) = qk‬‬
‫در این ماشین‪ ،‬در هر حالت با خواندن یکی از الفبای زبان امکان چندین گذر وجود دارد‪ .‬گذر ‪ λ‬هم وجود‬

‫دارد‬

‫‪δ (qi , λ) = qk‬‬


‫مثال‪ :‬یک ‪ NFA‬برای }‪ 𝐿 = {𝑏 𝑎𝑛 : 𝑛 ≥ 1} ∪ {𝑏𝑛 𝑎: 𝑛 > 2‬طراحی کنید‬

‫𝑛𝑎 𝑏‬ ‫‪𝑛 ≥ 1 𝑎𝑎𝑘 → 𝑎𝑛 𝑛 ≥ 1‬‬


‫𝑎 𝑛𝑏‬ ‫‪𝑛 ≥ 2 𝑏𝑏𝑏 𝑘 → 𝑏 𝑛 𝑛 ≥ 2‬‬

‫‪𝑞1‬‬ ‫‪b‬‬ ‫‪𝑞2‬‬ ‫‪a‬‬


‫‪λ‬‬ ‫‪F‬‬ ‫‪a‬‬

‫‪𝑞0‬‬ ‫‪b‬‬

‫‪λ‬‬ ‫‪𝑞3‬‬ ‫‪b‬‬ ‫‪b‬‬ ‫‪a‬‬


‫‪𝑞4‬‬ ‫‪𝑞5‬‬ ‫‪F‬‬

‫طراحی دوم‪:‬‬

‫‪a‬‬
‫‪𝑞1‬‬ ‫‪a‬‬
‫‪b‬‬ ‫‪F‬‬

‫‪𝑞0‬‬

‫‪b‬‬ ‫‪𝑞2‬‬ ‫‪a‬‬


‫‪𝑞3‬‬ ‫‪F‬‬
‫‪b‬‬

‫‪b‬‬

‫مثال‪ :‬آیا زبان زیر منظم است؟‬

‫‪L = {V w V‬‬ ‫}‪:V , w 𝝐 {a , b}* , |𝑉| = 2‬‬


‫زبان منظم است لذا برای آن یک ‪ NFA‬طراحی میکنیم‪.‬‬

‫‪a‬‬
‫‪a‬‬
‫‪ b‬یا ‪( a‬شروع)‬ ‫‪ b‬یا ‪( a‬ختم)‬ ‫‪b‬‬
‫‪a‬‬
‫‪b‬‬
‫‪b‬‬
‫‪29‬‬
‫‪a,b‬‬ ‫طول ‪ 2‬است ⇐ ‪ 4‬حالت‬
‫‪a‬‬ ‫‪a‬‬ ‫‪a‬‬ ‫‪a‬‬
‫‪0‬‬ ‫‪1‬‬ ‫‪2‬‬ ‫‪3‬‬ ‫‪F‬‬

‫‪b‬‬
‫‪b‬‬
‫‪5‬‬
‫‪4‬‬
‫‪a‬‬
‫‪a,b‬‬ ‫‪a‬‬
‫‪b‬‬

‫‪6‬‬ ‫‪a,b‬‬
‫‪a‬‬ ‫‪10‬‬

‫‪8‬‬
‫‪b‬‬ ‫‪b‬‬

‫‪7‬‬

‫‪a,b‬‬ ‫‪b‬‬
‫‪9‬‬
‫‪b‬‬ ‫‪F‬‬

‫ماشین خودکار قطعی )‪(DFA‬‬

‫ماشین خودکار قطعی را به صورت }‪ M (Q , Σ , δ , q0 , F‬تعریف میکنیم‬

‫‪ :Q‬مجموعه متناهی از حاالت‬

‫‪ :Σ‬مجموعه متنهای از نمادها که الفبای زبان است‪.‬‬

‫‪ :δ‬تابع گذر‬

‫‪ :q0‬حالت شروع‬

‫‪ :F‬حالت یا حاالت نهایی‬

‫در این ماشین‪ ،‬در هر حالت با خواندن یکی از الفبای زبان تنها یک گذر وجود دارد‪( .‬گذر ‪ λ‬نداریم)‬

‫مثال‪ :‬یک ‪ DFA‬برای پذیرش زبان با رشتههایی که دقیقاً دو ‪ a‬داریم‬

‫‪30‬‬
‫‪b‬‬
‫‪b‬‬ ‫‪b‬‬
‫‪0 0‬‬ ‫‪a‬‬ ‫‪1‬‬ ‫‪a‬‬ ‫‪F‬‬ ‫‪bb aa b‬‬

‫∗𝑏 𝑎 ∗𝑏 𝑎 ∗𝑏‬
‫مثال‪ :‬یک ‪ DFA‬برای پذیرش زبان با رشتههایی که حداقل یک ‪ a‬و دقیقاً دو تا ‪ b‬دارند‬
‫‪a‬‬ ‫‪a‬‬ ‫‪a‬‬
‫‪a‬‬ ‫‪b‬‬ ‫‪b‬‬
‫‪0‬‬ ‫‪1‬‬ ‫‪2‬‬ ‫‪F‬‬

‫‪b‬‬ ‫‪a‬‬

‫‪a‬‬ ‫‪b‬‬
‫‪3‬‬

‫‪4‬‬ ‫‪t‬‬

‫‪b‬‬
‫‪a,b‬‬

‫حالت تله ← رشتهای که تولید میکند از روال عادی زبان خارج شود‬
‫∗𝑎 𝑏 ∗𝑎 𝑏 ∗𝑎 𝑎‬

‫با ‪ b‬شروع‬ ‫∗𝑎 𝑏 ∗𝑎 𝑎 𝑏‬


‫∗𝑎 𝑎 𝑏𝑏‬
‫کل رشتهها خارج از این سه قاعده نیست‬

‫مثال‪ :‬یک ‪ DFA‬برای عبارت با قاعده (‪ 0 (1 0)* )0 1‬رسم کنید‬


‫‪0‬‬ ‫‪0‬‬ ‫‪1‬‬
‫‪0‬‬ ‫‪1‬‬ ‫‪2‬‬ ‫‪F‬‬

‫‪0‬‬
‫‪1‬‬ ‫‪0‬‬ ‫‪0‬‬

‫‪3‬‬
‫‪t‬‬
‫‪1‬‬

‫حالت تله (‪)trap‬‬


‫‪31‬‬
‫ایجاد ‪ nfa‬از عبارت منظم (باقاعده) – الگوریتم تامپسون‬

‫‪ ‬ابتدا عبارت منظم ‪ r‬را به زیرعبارتهای سازنده آن تجزیه میکنیم‪.‬‬

‫تمام اعضا تشکیل دهنده‬


‫⇒ ‪𝑟 = (𝑎 + 𝑏 )2 (𝑐 + 𝜆 )3‬‬ ‫𝜆 = ‪𝑟1 = 𝑎 𝑟2 = 𝑏 𝑟3 = 𝑐 𝑟4‬‬

‫‪ ‬برای هر کدام از عبارتها یک ‪ nfa‬رسم میکنیم‪ .‬یعنی برای هر ‪ 𝑎𝜖Σ‬یک ‪ nfa‬با حالت شروع ‪ i‬بدین‬

‫صورت ایجاد میکنیم‪.‬‬

‫‪s=a‬‬ ‫مثال‪:‬‬

‫‪t=c‬‬

‫‪r=s+t‬‬

‫‪ ‬مثال‪ N(r) :‬را برای عبارت منظم 𝑡 ‪ 𝑟 = 𝑠 +‬به صورت زیر رسم میکنیم‪.‬‬

‫‪32‬‬
‫‪ N(s) ‬را برای عبارت منظم 𝑡 ∙ 𝑠 = 𝑟 (الحاق ‪ s‬در ‪ t‬است) به صورت زیر رسم میکنیم‪.‬‬

‫مثال‪ :‬بنویسید؟‬

‫‪---------------------------------------------------------------------------‬‬

‫‪ N(r) ‬را برای عبارت منظم ∗ 𝑠 = 𝑟 به صورت زیر رسم میکنیم‪.‬‬

‫‪33‬‬
‫‪ ‬یک ‪ NFA‬برای عبارت با قاعده )‪ 0(10)∗ (01‬رسم کنید‪.‬‬

‫مثال‪ :‬یک ‪ NFA‬برای عبارت با قاعده ∗)𝑐 ‪ 𝑎 + 𝑏 ∗ (𝑎𝑏 +‬رسم کنید‪.‬‬

‫این طراحی کامل نیست و نیز میتوان بهینه نمود‪.‬‬

‫‪ ‬تبدیل ‪ NFA‬به ‪DFA‬‬

‫تعریف )𝑞(𝑒𝑟𝑢𝑠𝑜𝑙𝑐 ‪ : 𝜆 −‬مجموعه حاالتی از ‪ NFA‬که از حالت 𝑞 با تبدیل 𝜆 قابل دسترس هستند‪.‬‬

‫‪34‬‬
‫}‪𝜆 − 𝑐𝑙𝑜𝑠𝑢𝑟𝑒(0) = {0.1.2.5‬‬

‫}‪𝜆 − 𝑐𝑙𝑜𝑠𝑢𝑟𝑒(4) = {4.5‬‬

‫تعریف )𝑇(𝑒𝑟𝑢𝑠𝑜𝑙𝑐 ‪ : 𝜆 −‬مجموعه حاالتی از ‪ NFA‬که از حاالت 𝑇 با تبدیل 𝜆 قابل دسترس هستند‪.‬‬

‫}‪𝑇 = {1.4.5‬‬

‫}‪𝜆 − 𝑐𝑙𝑜𝑠𝑢𝑟𝑒(𝑇) = {1.4.5‬‬

‫}‪𝑇 = {0.3‬‬

‫}‪𝜆 − 𝑐𝑙𝑜𝑠𝑢𝑟𝑒(𝑇) = {0.1.2.5.3‬‬

‫‪ ‬تعریف )𝑎 ‪ : 𝑚𝑜𝑣𝑒(𝑇.‬مجموعه حاالتی از ‪ NFA‬که از حالت ‪ S‬در مجموعه ‪ T‬و با نماد ورودی ‪ a‬یک‬

‫گذر به آنها انجام میشود‪.‬‬

‫}‪𝑇 = {1.3‬‬

‫}‪𝑚𝑜𝑣𝑒(𝑇. 𝑎) = {3‬‬

‫الگوریتم تبدیل ‪ NFA‬به ‪DFA‬‬

‫‪ 𝜆 − 𝑐𝑙𝑜𝑠𝑢𝑟𝑒(𝑠) ‬را محاسبه میکنیم و به مجموعه حاصل یک اسم اختصاصی میدهیم و آن را به‬

‫جدول ‪ Dtrans‬اضافه میکنیم‪ .‬مجموعه مرود نظر حالت شروع ‪ DFA‬میباشد‪.‬‬

‫‪35‬‬
‫‪ ‬یک حالت عالمت نخورده‪ ،‬در ‪ Dtrans‬را پیدا میکنیم و آن را ‪ T‬مینامیم‪ .‬و مراحل زیر را روی آن اجرا‬

‫میکنیم (ابتدا فقط یک حالت در جدول ‪ Dtrans‬وجود دارد)‪ .‬درصورت عدم وجود حالت عالمت خورده‬

‫الگوریتم تمام است‪.‬‬

‫‪ -1‬حالت انتخاب شده را عالمت میزنیم‪.‬‬

‫‪ -2‬برای هر نماد از الفبای زبان (در الگوریتم آنها را ‪ a‬مینامیم) مراحل زیر را انجام میدهیم‪:‬‬

‫‪ )1-2‬مجموعه ))𝑎 ‪ λ − 𝑐𝑙𝑜𝑠𝑢𝑟𝑒(𝑚𝑜𝑣𝑒(𝑇.‬را محاسبه میکنیم‪( .‬در الگوریتم آن را ‪ u‬مینامیم) اگر‬

‫این مجموعه با مجموعههای موجود در ‪ Dtrans‬یکسان نبود نام جدیدی به آن اختصاص میدهیم و آن را به‬

‫‪ Dtrans‬اضافه میکنیم‪.‬‬

‫‪ )2-2‬در واقع باید به جدول ‪ Dtrans‬درصورت تکراری نبودن 𝑢 = ]𝑎 ‪ 𝐷𝑡𝑟𝑎𝑛𝑠[𝑇.‬را اضافه کنیم‪.‬‬

‫مجموعهای را که شامل حداقل یکی از حالتهای پایانی ‪ NFA‬باشد را به عنوان حالت پایانی ‪ DFA‬مشخص‬

‫میکنیم‪.‬‬

‫‪ ‬مثال‪ NFA :‬زیر را به ‪ DFA‬تبدیل کنید‪.‬‬

‫‪36‬‬
‫𝐴 = }‪𝜆 − 𝑐𝑙𝑜𝑠𝑢𝑟𝑒(−1) = {−1.0.1.2‬‬

‫}‪𝑚𝑜𝑣𝑒(𝐴. 𝑎) = {3‬‬

‫از ‪ 3‬با گذر 𝜆 به کجاها میروم‬

‫𝐵 = }‪𝜆 − 𝑐𝑙𝑜𝑠𝑢𝑟𝑒(3) = {0.1.2.3.5‬‬

‫}‪𝑚𝑜𝑣𝑒(𝐴. 𝑏) = {4‬‬

‫* هر چیزی خودش هم میشود ‪ /‬مجموعه جدید است و به جدول اضافه میشود‪.‬‬

‫𝐶 = }‪𝜆 − 𝑐𝑙𝑜𝑠𝑢𝑟𝑒(4) = {0.1.2.4.5‬‬

‫𝐵 → }‪𝑚𝑜𝑣𝑒(𝐵. 𝑎) = {3‬‬

‫}‪𝑚𝑜𝑣𝑒(𝐵. 𝑏) = {4.6.3‬‬

‫𝐷 = }‪𝜆 − 𝑐𝑙𝑜𝑠𝑢𝑟𝑒(3.4.6) = {0.1.2.3.4.5.6‬‬

‫}‪𝑚𝑜𝑣𝑒(𝐶. 𝑎) = {3.4‬‬

‫𝐸 = }‪𝜆 − 𝑐𝑙𝑜𝑠𝑢𝑟𝑒(3.4) = {0.1.2.3.4.5‬‬

‫}‪𝑚𝑜𝑣𝑒(𝐶. 𝑏) = {4.6‬‬

‫𝐹 = }‪𝜆 − 𝑐𝑙𝑜𝑠𝑢𝑟𝑒(4.6) = {0.1.2.4.5.6‬‬

‫‪37‬‬
: Dtrans ‫جدول‬

a b

A B C

B B D

C E F

D E D

E E D

F E F

𝜆 − 𝑐𝑙𝑜𝑠𝑢𝑟𝑒(0) = {0.1.2} = 𝐴

𝑚𝑜𝑣𝑒(𝐴. 𝑎) = 3 = 𝐵

𝑚𝑜𝑣𝑒(𝐴. 𝑏) = 4 = 𝐶

𝜆 − 𝑐𝑙𝑜𝑠𝑢𝑟𝑒(3) = {3} = 𝐵

𝑚𝑜𝑣𝑒(3. 𝑎) = ∅

𝑚𝑜𝑣𝑒(3. 𝑏) = 3

𝜆 − 𝑐𝑙𝑜𝑠𝑢𝑟𝑒(4) = {4} = 𝐶

𝑚𝑜𝑣𝑒(4. 𝑎) = 4

𝑚𝑜𝑣𝑒(4. 𝑏) = ∅

𝑚𝑜𝑣𝑒(𝐷. 𝑎) = {3.4} → 𝐸 ‫تکراری‬

𝑚𝑜𝑣𝑒(𝐷. 𝑏) = {3.4.6} → 𝐷 ‫تکراری‬

𝑚𝑜𝑣𝑒(𝐸. 𝑎) = {3.4} → 𝐸

38
‫𝐷 → }‪𝑚𝑜𝑣𝑒(𝐸. 𝑏) = {3.4.6‬‬

‫𝐸 → }‪𝑚𝑜𝑣𝑒(𝐹. 𝑎) = {3.4‬‬

‫𝐹 → }‪𝑚𝑜𝑣𝑒(𝐹. 𝑏) = {4.6‬‬

‫رسم ‪DFA‬‬

‫‪‬مثال‪ NFA−𝜆 :‬زیر را به ‪ DFA‬تبدیل کنید‪.‬‬

‫‪39‬‬
𝛿(𝑁𝐹𝐴) a b c 𝜆

𝑞0 {𝑞0 . 𝑞1 . 𝑞2 } 𝜙 𝜙 𝜙

𝑞1 𝜙 {𝑞1 } 𝜙 𝜙

𝑞2 𝜙 𝜙 {𝑞2 } {𝑞1 }

𝜆 − 𝑐𝑙𝑜𝑠𝑢𝑟𝑒(𝑞0 ) = {𝑞0 }

𝜆 − 𝑐𝑙𝑜𝑠𝑢𝑟𝑒(𝑞1 ) = {𝑞1 }

𝜆 − 𝑐𝑙𝑜𝑠𝑢𝑟𝑒(𝑞2 ) = {𝑞2 . 𝑞1 } = 𝑃

t a b c

𝑞0 {𝑞0 . 𝑞1 . 𝑞2 } 𝜙 𝜙

𝑞1 𝜙 {𝑞1 } 𝜙

𝑞2 𝜙 {𝑞1 } {𝑞2 . 𝑞1 }

𝐹 = {𝑋|𝑋 ∩ 𝐹 ≠ ∅}

40
‫‪t‬‬ ‫‪a‬‬ ‫‪b‬‬ ‫‪c‬‬

‫‪𝑞0‬‬ ‫} ‪{𝑞0 . 𝑞1 . 𝑞2‬‬ ‫𝜙‬ ‫𝜙‬

‫} ‪{𝑞0 . 𝑞1 . 𝑞2‬‬ ‫} ‪{𝑞0 . 𝑞1 . 𝑞2‬‬ ‫} ‪{𝑞1‬‬ ‫} ‪{𝑞1 . 𝑞2‬‬

‫} ‪{𝑞1‬‬ ‫𝜙‬ ‫} ‪{𝑞1‬‬ ‫𝜙‬

‫} ‪{𝑞1 . 𝑞2‬‬ ‫𝜙‬ ‫} ‪{𝑞1‬‬ ‫} ‪{𝑞1 . 𝑞2‬‬

‫𝜙‬ ‫𝜙‬ ‫𝜙‬ ‫𝜙‬

‫} ‪𝑡(𝑞0 . 𝑎) = 𝜆 − 𝑐𝑙𝑜𝑠𝑢𝑟𝑒({𝑞0 . 𝑞1 . 𝑞2 }) = {𝑞0 . 𝑞1 . 𝑞2‬‬

‫} ‪𝑡(𝑞2 . 𝑐) = 𝜆 − 𝑐𝑙𝑜𝑠𝑢𝑟𝑒({𝑞2 }) = {𝑞1 . 𝑞2‬‬

‫} ‪𝑡(𝑞1 . 𝑏) = 𝜆 − 𝑐𝑙𝑜𝑠𝑢𝑟𝑒({𝑞1 }) = {𝑞1‬‬

‫‪ ‬مثال‪ NFA :‬زیر را به ‪ DFA‬تبدیل کنید‪.‬‬

‫به ازای حالتهای جدید نامگذاری میکنیم‪:‬‬

‫‪41‬‬
‫سپس جدول ‪ Dtrance‬میکشیم‪:‬‬

‫‪a‬‬ ‫‪b‬‬

‫‪A‬‬ ‫‪B‬‬ ‫‪C‬‬

‫‪B‬‬ ‫‪-‬‬ ‫‪B‬‬

‫‪C‬‬ ‫‪C‬‬ ‫‪-‬‬

‫ساخت ‪ DFA‬از عبارت منظم (باقاعده)‬

‫به صورت زیر عبارت منظم را به درخت نحو تبدیل میکنیم‪:‬‬

‫‪ -1‬هر نماد یا الندا در عبارت منظم ‪ r‬در برگ درخت قرار میگیرد‪.‬‬
‫‪42‬‬
‫‪ -2‬درخت نحو را برای هر کدام از عملگرها به صورت زیر رسم میکنیم‪.‬‬

‫‪ -3‬نهایت درخت نحو عبارت ≠ 𝑟 (𝑟 شارپ) را به صورت بازگشتی رسم میکنیم‪ .‬به هر برگ که غیرالندا‬

‫است یک عدد منحصر به فرد داده میشود‪.‬‬

‫𝑎) 𝜆 ‪𝑎 + 𝑏 ∗ (𝑎 +‬‬ ‫‪ ‬مثال‪ :‬درخت نحو برای عبارت با قاعده‬

‫‪ : 𝑁𝑢𝑙𝑙𝑎𝑏𝑙𝑒(𝑛) ‬این تابع مشخص میکند که آیا زیردرخت ‪ n‬میتواند 𝜆 را تولید کند یا خیر؟ در صورت‬

‫مثبت بودن مقدار ‪ true‬و در غیر این صورت ‪ false‬برمیگرداند‪.‬‬

‫‪ -1‬اگر ‪ n‬برگی با برچسب الندار باشد آنگاه جواب ‪ true‬است‪.‬‬

‫‪43‬‬
‫‪ -2‬اگر∗ 𝑟 = 𝑛 یک برگ ستاره باشد آنگاه 𝑒𝑢𝑟𝑡 = )𝑛(𝑒𝑙𝑏𝑎𝑙𝑙𝑢𝑁‬

‫‪ 𝑛 = 𝑟1 + 𝑟2 -3‬آنگاه )‪ 𝑁𝑢𝑙𝑙𝑎𝑏𝑙𝑒(𝑛) = 𝑁𝑢𝑙𝑙𝑎𝑏𝑙𝑒(𝑟1) 𝑜𝑟 𝑁𝑢𝑙𝑙𝑎𝑏𝑙𝑒(𝑟2‬کافی است یکی‬

‫از آنها ‪ λ‬تولید کنند‪.‬‬

‫‪ 𝑛 = 𝑟1 + 𝑟2 -3‬آنگاه )‪ 𝑁𝑢𝑙𝑙𝑎𝑏𝑙𝑒(𝑛) = 𝑁𝑢𝑙𝑙𝑎𝑏𝑙𝑒(𝑟1) 𝑜𝑟 𝑁𝑢𝑙𝑙𝑎𝑏𝑙𝑒(𝑟2‬کافی است یکی‬

‫از آنها هم تولید کنند‪.‬‬

‫‪( 𝑛 = 𝑟1 ∙ 𝑟2 -4‬الحاق ‪ /‬هر دو 𝜆 تولید) آنگاه‪:‬‬

‫)‪𝑁𝑢𝑙𝑙𝑎𝑏𝑙𝑒(𝑛) = 𝑁𝑢𝑙𝑙𝑎𝑏𝑙𝑒(𝑟1) 𝑎𝑛𝑑 𝑁𝑢𝑙𝑙𝑎𝑏𝑙𝑒(𝑟2‬‬

‫‪ -5‬اگر یک برگ در موقعیت ‪ i‬ام باشد آنگاه 𝑒𝑠𝑙𝑎𝑓 = )𝑛(𝑒𝑙𝑏𝑎𝑙𝑙𝑢𝑁‬

‫𝑎 ∙ ∗)𝑏𝑎(‬

‫∗)𝑏𝑎( ‪ 𝜆 :‬تولید میکند ‪ 𝜆 : 𝑎 /‬تولید نمیکند ‪ : (𝑎𝑏)∗ ∙ 𝑎 /‬کوچکترین 𝑎 است؛ نتیجه‪:‬‬

‫𝑒𝑠𝑙𝑎𝑓 = 𝑒𝑙𝑏𝑎𝑙𝑙𝑢𝑁‬

‫‪ : 𝐹𝑖𝑟𝑠𝑡 𝑝𝑜𝑠(𝑛) ‬مجموعه مکان نمادهایی را برمیگرداند که منطبق بر اولین نماد رشتههای تولیدی از‬

‫عبارت باقاعده هستند‪.‬‬

‫‪ -1‬برای یک برگ با برچسب الندا برابر صفر است‪.‬‬

‫‪ -2‬برای یک برگ در موقعیت 𝑖 برابر } 𝑖{ است‪.‬‬

‫‪ -3‬اگر ‪ 𝑛 = 𝑟1 + 𝑟2‬آنگاه‪:‬‬

‫)‪𝐹𝑖𝑟𝑠𝑡 𝑝𝑜𝑠(𝑛) = 𝐹𝑖𝑟𝑠𝑡 𝑝𝑜𝑠(𝑟1) ∪ 𝐹𝑖𝑟𝑠𝑡 𝑝𝑜𝑠(𝑟2‬‬

‫‪ -4‬اگر ‪ 𝑛 = 𝑟1 ∙ 𝑟2‬آنگاه‪:‬‬

‫𝑛𝑒‪𝑖𝑓(𝑛𝑢𝑙𝑙 𝑎𝑏𝑙𝑒(𝑟1)) 𝑡ℎ‬‬

‫‪44‬‬
‫𝑒𝑠𝑙𝑒 )‪𝐹𝑖𝑟𝑠𝑡 𝑝𝑜𝑠(𝑟1) ∪ 𝐹𝑖𝑟𝑠𝑡 𝑝𝑜𝑠(𝑟2‬‬ ‫)‪𝐹𝑖𝑟𝑠𝑡 𝑝𝑜𝑠(𝑟1‬‬

‫‪ -5‬اگر ∗ 𝑟 = 𝑛 آنگاه )𝑟(𝑠𝑜𝑝 𝑡𝑠𝑟𝑖𝐹 = )𝑛(𝑠𝑜𝑝 𝑡𝑠𝑟𝑖𝐹‬

‫}‪𝐹𝑖𝑟𝑠𝑡 𝑝𝑜𝑠(𝑟1) = {1‬‬

‫}‪𝐹𝑖𝑟𝑠𝑡 𝑝𝑜𝑠(𝑟2) = {3‬‬

‫∗)𝑏𝑎(‬
‫⏟‬ ‫∗⏟‬
‫𝑏𝑎‬
‫‪𝑟1‬‬ ‫‪𝑟2‬‬

‫‪ ‬مثال‪ First pos :‬برای عبارتهای زیر چگونه است؟‬

‫‪1 2 3‬‬ ‫‪4 5‬‬


‫}‪(∗ (𝑎|𝑏) + 𝜆)𝑑 + 𝑒 → 𝑓𝑖𝑟𝑠𝑡 𝑝𝑜𝑠 = {4.1.2.3‬‬
‫‪+‬‬

‫}‪((𝑎𝑏𝑎)∗ 𝑏)𝑎𝑐 → 𝑓𝑖𝑟𝑠𝑡 𝑝𝑜𝑠 = {4.1‬‬

‫‪ : 𝑙𝑎𝑠𝑡 𝑝𝑜𝑠(𝑛) ‬مجموعه مکان نمادهایی را برمیگرداند که منطبق بر آخرین نماد رشتههای تولیدی از‬

‫عبارت باقاعده هستند‪.‬‬

‫}‪𝑎𝑏 ∗ 𝑐 → 𝑙𝑎𝑠𝑡 𝑝𝑜𝑠 = {3‬‬

‫}‪𝑎𝑏 ∗ 𝑐 ∗ → 𝑙𝑎𝑠𝑡 𝑝𝑜𝑠 = {3.2.1‬‬

‫‪ : 𝑓𝑜𝑙𝑙𝑜𝑤 𝑝𝑜𝑠 (𝑖) ‬مجموعه مکانهایی را برمیگرداند که پس از مکان ‪ i‬قرار میگیرند‪.‬‬

‫‪ -1‬اگر ‪ n‬یک گره الحاق باشد ‪ 𝑟1‬فرزند چپ و ‪ 𝑟2‬فرزند راست آن است‪ .‬برای هر موقعیت ‪ i‬در‬

‫)‪ 𝑙𝑎𝑠𝑡 𝑝𝑜𝑠 (𝑟1‬تمام موقعیتها در )‪ 𝐹𝑖𝑟𝑠𝑡 𝑝𝑜𝑠 (𝑟2‬در )𝑖( 𝑠𝑜𝑝 𝑤𝑜𝑙𝑙𝑜𝑓 قرار دارند‪.‬‬

‫‪ -2‬اگر ‪ n‬یک گره ستاره و ‪ i‬یک موقعیت در محموله )𝑛( 𝑠𝑜𝑝 𝑡𝑠𝑎𝑙 باشد همه موقعیتها در‬

‫)𝑛( 𝑠𝑜𝑝 𝑡𝑠𝑟𝑖𝐹 در )𝑖( 𝑠𝑜𝑝 𝑤𝑜𝑙𝑙𝑜𝑓 قرار میگیرند‪.‬‬

‫‪𝑟1 ∙ 𝑟2‬‬ ‫𝑐 ∗𝑎 ∙ ∗ 𝑏𝑎‬ ‫𝑐𝑎𝑏𝑎‬

‫𝑐𝑏𝑎‬

‫‪45‬‬
‫∗)𝑏𝑎(‬ ‫𝑏𝑎𝑏𝑎‬

‫‪ ‬مثال ‪ followpos‬برای عبارتهای زیر چگونه است؟‬

‫)𝑒 ‪(𝑎 + 𝑏 + 𝑐) ∗∙ (𝑐𝑑 +‬‬ ‫?= )‪𝑓𝑜𝑙𝑙𝑜𝑤𝑝𝑜𝑝(3‬‬ ‫}‪{1.2.3.4.6‬‬

‫)𝑏 ‪(𝑎𝑏 + 𝑐) ∙ (𝑎 +‬‬ ‫?= )‪𝑓𝑜𝑙𝑙𝑜𝑤𝑝𝑜𝑝(2‬‬ ‫}‪{4.5‬‬

‫𝑎𝑏𝑎‬

‫𝑏𝑏𝑎‬

‫ساخت ‪ DFA‬از عبارت منظم (باقاعده)‬

‫‪ -1‬درخت نحو ‪ T‬عبارت با قاعده ‪ 𝑟#‬را رسم میکنیم‪.‬‬

‫‪ -2‬توابع 𝑒𝑙𝑏𝑎 𝑙𝑙𝑢𝑁 ‪ 𝑓𝑜𝑙𝑙𝑜𝑤 𝑝𝑜𝑠 ، 𝑙𝑎𝑠𝑡 𝑝𝑜𝑠 ، 𝐹𝑖𝑟𝑠𝑡 𝑝𝑜𝑠 ،‬را در پیمایش عمقی درخت مشخص‬

‫میکنیم‪.‬‬

‫‪ 𝐹𝑖𝑟𝑠𝑡 𝑝𝑜𝑠 (𝑟𝑜𝑜𝑡) -3‬را محاسبه میکنیم‪ .‬و آن را به عنوان یک حالت عالمت نخورده به جدول ‪Dtrans‬‬

‫اضافه میکنیم‪ .‬در واقع این مجموعه حالت شروع ‪ DFA‬است‪.‬‬

‫‪ -4‬اگر در جدول ‪ Dtrans‬حالت عالمت نخوردهای وجود ندارد آن را انتخاب میکنیم‪ .‬در این الگوریتم این‬

‫حالت را ‪ T‬مینامیم‪ .‬اگر حالت عالمت نخورده وجود ندارد الگوریتم تمام میشود‪.‬‬

‫‪ -5‬حالت انتخاب شده ‪ T‬را عالمت میزنیم‪.‬‬

‫‪ -6‬برای هر نماد ‪ a‬مراحل زیر را اجرا میکنیم‪.‬‬

‫‪ )1-6‬مجموعه مکانهایی در ‪ T‬که نماد متناظر در عبارت با قاعده ‪ a‬است را محاسبه کرده و آن را ‪ P‬مینامیم‪.‬‬

‫‪ )2-6‬مجموعه )𝑝( 𝑠𝑜𝑝 𝑤𝑜𝑙𝑙𝑜𝑓 را محاسبه میکنیم مجموعه بدست آمده را ‪ u‬مینامیم‪.‬‬

‫‪ u )3-6‬را به جدول ‪ Dtrans‬اضافه میکنیم‪.‬‬

‫‪46‬‬
‫‪ -7‬به مرحله ‪ 4‬برمیگردیم‪.‬‬

‫‪ -8‬حالتی که شامل مکان متناظر‪ #‬است حالت پذیرش ‪ DFA‬است‪.‬‬

‫‪ ‬مثال‪ :‬برای عبارت باقاعده ‪ (𝑎 + 𝑏)∗ 𝑎 𝑏 𝑏 #‬مستقیما یک ‪ DFA‬بسازید‪.‬‬

‫𝑎 ∗)𝑏 ‪𝑓𝑜𝑙𝑙𝑜𝑤 𝑝𝑜𝑠 ∶ (𝑎 +‬‬

‫مکان ‪: 1‬‬

‫}‪1 → {1.2.3‬‬

‫}‪2 → {1.2.3‬‬

‫توجه‪ :‬آخر همه رشتهها به ≠ ختم میشود‪.‬‬

‫}‪3 → {4‬‬

‫}‪4 → {5‬‬

‫}‪5 → {6‬‬

‫‪6 → −‬‬

‫}‪𝐴 = {1.2.3} {6‬‬

‫‪47‬‬
‫‪a‬‬ ‫‪b‬‬

‫‪A‬‬ ‫‪B‬‬ ‫‪A‬‬

‫‪B‬‬ ‫‪B‬‬ ‫‪C‬‬

‫‪C‬‬ ‫‪B‬‬ ‫‪D‬‬

‫‪D‬‬ ‫‪B‬‬ ‫‪A‬‬

‫}‪𝑃𝑎 = {1.3‬‬

‫𝐵 = }‪𝑓𝑜𝑙𝑙𝑜𝑤 𝑝𝑜𝑠(1.3) = {1.2.3.4‬‬

‫}‪𝑃𝑏 = {2‬‬

‫𝐴 = }‪𝑓𝑜𝑙𝑙𝑜𝑤 𝑝𝑜𝑠(2) = {1.2.3‬‬

‫𝐵 → }‪𝑃𝑎 = {1.3‬‬

‫}‪𝑃𝑏 = {2.4‬‬

‫𝐶 = }‪𝑓𝑜𝑙𝑙𝑜𝑤 𝑝𝑜𝑠(2.4) = {1.2.3.5‬‬

‫𝐵 → }‪𝑃𝑎 = {1.3‬‬

‫}‪𝑃𝑏 = {2.5‬‬

‫𝐷 = }‪𝑓𝑜𝑙𝑙𝑜𝑤 𝑝𝑜𝑠(2.5) = {1.2.3.6‬‬

‫𝐵 → }‪𝑃𝑎 = {1.3‬‬

‫}‪𝑃𝑏 = {2‬‬

‫𝐴 = }‪𝑓𝑜𝑙𝑙𝑜𝑤 𝑝𝑜𝑠(2) = {1.2.3‬‬

‫حالت جدید بوجود نیامد ← الگوریتم تمام میشود‪.‬‬

‫‪48‬‬
.‫ بسازید‬DFA ‫ یک‬a(ab )* a*b ‫ برای عبارت با قاعده‬:‫مثال‬

a (ab )* a b 
*
First pos  {1}  A 1 2 3 4 5 6
.‫ ختم شود‬ ‫عبارت باید به‬

follow pos a b
1  }2 ,4 ,5{ A B -
2  }3{ B C D
3  }2 ,4 ,5{ C E F
4  }4 ,5{ D - -
5  }6{ E E D
6  - F C D

A:
a
P {1}

Follow pos (1) = {2 ,4 ,5} =B

b
P o ‫ کجا است؟ تهی‬1 ‫در موقعیت‬

B:
a
P {2, 4} ‫ است؟‬a ‫ کجا‬5 ‫و‬4 ,2 ‫در موقعیت‬

49
Follow pos (2 ,4) = {3 ,4 ,5} =C ‫مجموعه‬

‫جدید‬

Follow pos 2  Follow pos  4


b
P {5} ‫ است؟‬b ‫ کجا‬B ‫در این مجموعه‬

Follow pos (5) = {6} =D


C:

Follow pos  4  {4, 5}  E


b
P {3, 4}

Follow pos  3, 5  {2, 4, 5, 6}  F

E:
a
P {4}  E ‫ است؟‬a ‫ برابر‬4 ‫ و‬5 ‫کجاهای‬
b
P {5}  D ‫ است؟‬b‫ برابر‬4‫ و‬5 ‫کجاهای‬

F:
a
P {2, 4}  C A

b a
P {5}  D
B
a a,b
a,b
C D +
a
b
a ‫ دارد که حالت‬# ‫عالمت‬
b
E
a ‫پایانی‬
F

b
6 ‫ دارد که عدد‬# ‫عالمت‬
50
‫گرامرها‬

‫در این فصل در مورد نحوه تولید یک گرامر و اصالح آن برای اینکه بتوانیم یک تجزیه کننده را تولید کنیم‬

‫توضیح می دهیم و گرامر مستقل از متن برای شناسایی ساختار زبان استفاده می شود و نحوه اصالح آن را‬

‫بحث می کنیم‪.‬‬

‫‪ ‬ویژگی نحوی ساختارهای زبان های برنامه نویسی با استفاده از یک گرامر مستقل از متن توصیف می‬

‫شود‪.‬‬

‫‪ ‬گرامر یک نمایش دقیق و قابل فهم از زبان برنامه نویسی را ارایه می کند‪.‬‬

‫‪ ‬یک گرامر به زبان این امکان را می دهد که بلورت تکرار پذیر نکامل یافته یا توسعه پیدا کند‪ .‬این‬

‫عمل با افزدن ساختارهای جدید برای انجام اعمال جدید انجام می شود‪.‬‬

‫فرم کلی گرامرهای مستقل از متن‬

‫‪Sx‬‬ ‫‪S V‬‬ ‫*)‪x  (vuT‬‬


‫(گرامر مستقل از متن)‬ ‫‪EE+T|T‬‬

‫‪TT*F|F‬‬
‫‪F(E) |id‬‬
‫مثال گرامری مستقل از متن برای عبارات محاسباتی اولیه‬

‫‪expr  expr + term‬‬


‫‪expr  expr - term‬‬
‫‪expr  term‬‬
‫‪term  term * factor‬‬
‫‪term  term / factor‬‬
‫‪term  factor‬‬
‫)‪factor  (expr‬‬ ‫پارامتر اولویت بندی را محاسبه می کنیم‪‬‬

‫‪factor  id‬‬

‫‪51‬‬
‫به لحاظ بعدی مشکل ندارد به لحاظ نحوی مشکل دارد‬
‫‪id +* id‬‬
‫گرامر این رشته را نمی پذیرد و می گوید بدی فا نحوری مشکل دارد‪.‬‬
‫‪1  *2 ‬‬
‫‪1 2* 3 ‬‬
‫‪ ‬برای سادگی گرامرها معموال از قواعد زیر استفاده می شود‪:‬‬

‫‪-1‬نماهای زیر‪ ،‬پایانه هستند‪:‬‬

‫‪-‬حرف کوچک مانند ‪a,b,c‬‬

‫‪-‬نمادهای عملگر مانند جمع و تفریق و ‪...‬‬

‫‪-‬نمادهای پرانتز‪ ،‬کاما و ‪...‬‬

‫‪-‬ارقام‬

‫‪-2‬نمادهای زیر‪ ،‬غیر پایانه هستند‪:‬‬

‫‪-‬حروف بزرگ (در سمت چپ قوانین)‬

‫‪-‬اسامی حروف کوچک‬

‫( ‪ ‬می تواند ترکیبی از پایانه یا غیرپایانه باشد)‪.‬‬

‫‪A 1‬‬
‫*در گرامر ‪ A 2‬را می توان به صورت ‪ A 1|2|3 | ...‬نوشت‪.‬‬
‫‪A  ...‬‬

‫مثال‪ :‬ساده شدن گرامر مثل قبل‬

‫‪id  id * id‬‬ ‫اگر این را بخواهیم‪:‬‬

‫‪EE+T|E-T|T‬‬ ‫‪E+T‬‬

‫‪TT*F|T\F|F‬‬
‫‪E+T*F‬‬
‫‪F(E)|id‬‬
‫‪T‬‬ ‫‪F id‬‬

‫‪F‬‬
‫‪id‬‬

‫‪id‬‬

‫‪52‬‬
‫اشتقاق (‪)Derivation‬‬

‫‪ ‬فرآیند تولید یک رشته از نماد شروع را اشتقاق گوئیم‪.‬‬

‫‪ ‬تولید یک رشته بوسیله گرامر مستقل از متن از نماد شروع آغاز می شود‪.‬‬

‫‪ ‬در هر مرحله یک غیرپایانه بوسیله سمت راست قاعده تولید آن گسترش داده می شود‪.‬‬

‫‪ ‬روند تولید تا زمانی ادامه پیدا می کند که هیچ غیر پایانه ای نماند‪.‬‬

‫دو نوع اشتقاق وجود دارد‪:‬‬

‫‪ -1‬اشتقاق راست (‪)RMD‬‬

‫‪-2‬اشتقاق چپ (‪)LMD‬‬

‫اشتقاق راست‪ :‬در این اشتقاق همواهر سمت راست ترین غیرپایانه‪ ،‬با سمت راست‪ ،‬قاعده تولید آن جایگزین‬

‫می شود‪.‬‬

‫اشتقاق چپ‪ :‬در این اشتقاق همواره سمت چپ ترین غیرپایانه‪ ،‬با سمت راست‪ ،‬قاعده تولید آن جایگزین می‬

‫شود‪.‬‬
‫اشتقاق چپ‬
‫‪E  E+T| E-T| T‬‬ ‫اشتقاق راست‬
‫‪id + id‬‬
‫‪T  T*F| T/F| F‬‬ ‫‪E+T‬‬ ‫‪EE+T‬‬
‫‪id + id‬‬
‫‪EE+T‬‬
‫‪F  (E)| id‬‬ ‫‪T+T‬‬ ‫‪E T‬‬
‫‪E+T‬‬

‫‪E+F‬‬ ‫‪TF‬‬
‫‪F+T‬‬
‫‪E+id‬‬ ‫‪Fid‬‬
‫‪id+T‬‬
‫اشتقاق چپ‬ ‫‪T+id‬‬ ‫‪ET‬‬
‫‪id+F‬‬
‫‪E‬‬ ‫اشتقاق راست‬ ‫‪TF‬‬
‫‪F+id‬‬
‫‪id + id‬‬
‫‪E‬‬
‫‪id + id‬‬
‫‪E‬‬ ‫‪+‬‬ ‫‪T‬‬

‫‪E‬‬ ‫‪+‬‬ ‫‪T‬‬

‫‪T‬‬ ‫‪F‬‬

‫‪T‬‬ ‫‪F‬‬
‫‪F‬‬ ‫‪id‬‬

‫‪F‬‬ ‫‪id‬‬
‫‪id‬‬

‫‪53‬‬ ‫‪id‬‬
‫درخت تجزیه‪ :‬یک نمایش گرافیکی برای اشتقاق می باشد‪ .‬در واقع نحوه جایگزینی غیرپایانه ها با سمت‬

‫راست قاعده تولید را نشان می دهد‪.‬‬

‫توجه‪ :‬در درخت تجزیه ‪ ‬ترتیب ها مشخص نیست ولی در درخت اشتقاق مشخص است‪.‬‬

‫نحوه ساختن درخت تجزیه به صورت زیر است‪:‬‬

‫الف) در ریشه درخت تجزیه‪ ،‬نماد شروع گرامر می آید‪.‬‬

‫ب) در برگ های درخت تجزیه‪ ،‬پایانه ها یا الندا می آید‪.‬‬

‫ج) هر گره میانی درخت تجزیه یک غیرپایانه است‪.‬‬

‫د) اگر ‪ A‬یک غیر پایانه و گره میانی درخت تجزیه باشد ‪ x 1, x 2 ,..., x n‬فرزندان این گره هستند آنگاه در‬

‫گرامر باید قاعده تولیدی به صورت ‪ A  x 1, x 2 ,..., x n‬وجود داشته باشد‪.‬‬


‫‪E‬‬
‫‪E  E+T|E-T|T‬‬
‫‪T  T*F| T/F| F‬‬
‫‪E‬‬ ‫‪+‬‬ ‫‪T‬‬
‫‪F  (E)/ id‬‬
‫‪id+id/id‬‬ ‫‪T‬‬ ‫‪T‬‬ ‫‪/‬‬ ‫‪F‬‬

‫‪F‬‬ ‫‪F‬‬ ‫‪id‬‬

‫‪id‬‬ ‫‪id‬‬

‫در اشتقاق ترتیب بکارگیری قواعد مشخص است اما در درخت تجزیه ای موضوع مشخص نیست‪.‬‬ ‫‪‬‬

‫گرامر مبهم‪ :‬در صورتی که در یک گرامر برای یک رشته بتوان دو اشتقاق چپ یا دو اشتقاق‬

‫راست و یا دو درخت تجزیه متقاوت ایجاد نمود‪ ،‬آنگاه گرامر مبهم است‪.‬‬

‫‪E  E+T|E-T|T‬‬
‫‪T  T*F| T/F| F|E‬‬
‫‪F  (E)| id‬‬

‫‪54‬‬
‫‪E‬‬ ‫‪E‬‬

‫‪E‬‬ ‫‪+‬‬ ‫‪T‬‬ ‫‪T‬‬

‫‪T‬‬ ‫‪T‬‬ ‫‪/‬‬ ‫‪F‬‬ ‫‪T‬‬ ‫‪/‬‬ ‫‪F‬‬

‫‪F‬‬ ‫‪F‬‬ ‫‪id‬‬ ‫‪E‬‬ ‫‪id‬‬

‫‪id‬‬ ‫‪id‬‬ ‫‪E‬‬ ‫‪+‬‬ ‫‪T‬‬

‫‪T‬‬ ‫‪F‬‬

‫‪F‬‬ ‫‪id‬‬

‫‪id‬‬
‫تمرین کتاب ‪AHO‬‬

‫مثال‪ :‬گرامر مستقل از متن زیر در رشته *‪ aa  a‬را در نظر بگیرید‪.‬‬

‫‪S  SS+|SS*|a‬‬
‫الف) یک سمت چپ ترین و سمت راست ترین استقاق برای رشته بنوسید‪.‬‬

‫ب) یک درخت تجزیه ای برای رشته رسم کنید‪.‬‬

‫ج) آیا گرامر مبهم است؟‬

‫د) زبان توصبف شده توسط گرامر چیست؟‬

‫الف) *‪aa  a‬‬

‫‪S  SS+|SS*|a‬‬
‫چون رشته خ به * ختم شده است دو سمت راست ترین پس‬
‫*‪ SS‬انتخاب می شود‬
‫اشتقاق راست‬ ‫اشتقاق چپ‬
‫سمت چپ ترین را‬ ‫سمت چپ ترین را‬
‫*‪ SS‬گسترش دهیم‪.‬‬ ‫گسترش دهیم‪.‬‬ ‫*‪SS‬‬
‫*‪Sa‬‬ ‫*‪SS+ S‬‬
‫* ‪SS + a‬‬ ‫*‪aS+ S‬‬
‫*‪Sa+ a‬‬ ‫*‪aa+ S‬‬
‫‪55‬‬
‫*‪aa+ a‬‬ ‫*‪aa+ a‬‬
‫ب) برای این رشته فقط یک درخت تجزیه به این فرم وجود دارد‪.‬‬
‫‪S‬‬

‫‪S‬‬ ‫‪S‬‬ ‫*‬

‫ج) مبهم نیست‪ ( .‬هر رشته ای در نظر بگیریم این امکان‬


‫‪S‬‬ ‫‪S‬‬ ‫‪+‬‬ ‫‪a‬‬
‫وجود ندارد که دو رشته مختلف برسد و ‪)...‬‬

‫‪a‬‬ ‫‪a‬‬ ‫د) چند رشته مختلف تولید شده توسط گرامر‬

‫‪a‬‬
‫‪aa+‬‬
‫*‪aa‬‬

‫‪SS+‬‬
‫‪SSS++‬‬
‫‪SSS*S++‬‬
‫‪aaa*a++  a+a*a+a‬‬
‫سه عملگر ‪ 4‬عملوند‬

‫این گرامر تمامی عبارات ریاضی بفرم پیشوندی با عملگرهای ‪ * ،+‬را تولید می کند‪.‬‬

‫مثال‪ :‬گرامر مستقل از متن زیر و رشته ‪ (a+a)*a‬را در نظر بگیرید‪.‬‬

‫‪SS  S+S |(S)| S* |SS |a‬‬


‫الف) یک سمت چپ ترین و سمت راست ترین اشتقاق برای رشته بنویسید‪.‬‬

‫ب) یک درخت تجزیه ای برای رشته رسم کنید‪.‬‬

‫ج) آیا گرامر مبهم است؟‬

‫د) زبان توصیف شده توسط گرامر چیست؟‬

‫‪SS  S+ S|SS| (S) |S*| a‬‬

‫‪56‬‬
‫الف)‬
‫اشتقاق راست‬ ‫اشتقاق چپ‬
‫‪SS‬‬ ‫‪SS‬‬
‫‪Sa‬‬ ‫‪S*S‬‬
‫‪S*a‬‬ ‫‪(S)*S‬‬
‫‪(S)* a‬‬ ‫‪(S+S)*S‬‬
‫‪(S+S)*a‬‬ ‫‪(a+S)*S‬‬
‫‪(S+a)*a‬‬ ‫‪(a+a)*S‬‬
‫‪(a+a)*a‬‬ ‫‪(a+a)*a‬‬

‫‪S‬‬
‫ب)‬

‫‪S‬‬ ‫‪S‬‬
‫بر اساس این رشته نمی توان گفت گرامر مبهم است‬

‫اما بر اساس رشته ای دیگر مثل ‪ a+a+a‬می توان گفت‪.‬‬


‫‪S‬‬ ‫‪+‬‬ ‫‪a‬‬

‫(‬ ‫‪S‬‬ ‫)‬

‫گرامر مبهم است‪.‬‬


‫‪S‬‬ ‫‪+‬‬ ‫‪S‬‬

‫‪a‬‬ ‫‪a‬‬ ‫‪a+a+a‬‬


‫‪S‬‬
‫‪S‬‬

‫‪S‬‬ ‫‪+‬‬ ‫‪S‬‬


‫‪S‬‬ ‫‪+‬‬ ‫‪S‬‬

‫‪S‬‬ ‫‪+‬‬ ‫‪S‬‬ ‫‪a‬‬


‫‪a‬‬ ‫‪S‬‬ ‫‪+‬‬ ‫‪S‬‬
‫‪a‬‬ ‫‪a‬‬
‫‪57‬‬ ‫‪a‬‬ ‫‪a‬‬
‫مثال‪ :‬برای هر یک از ربالهای زیر یک گرامر بنویسید‪.‬‬

‫الف) مجموعه تمام رشته ها از صفر و یک که تعداد یک ها و صفرها یکسان نیست‪.‬‬

‫ب) مجموعه تمام رشته ها که تعداد ‪ a‬ها دو برابر تعداد ‪b‬ها است‪.‬‬

‫‪S  p |q‬‬ ‫افزایش تعداد صفر‬


‫تعداد ‪ 0‬و‪ 1‬مساوی‬
‫| ‪p  p1| 1p | pp | Ap‬‬
‫‪A  A |‬‬ ‫‪p : n  n1‬‬

‫تعداد ‪ 0‬و‪ 1‬مساوی‬ ‫افزایش تعداد یک ها‬


‫‪q  q1| 1q | qq | Bq | 1‬‬ ‫‪q : n  n1‬‬
‫‪B 1B | ‬‬
‫‪ )1‬جایگشت های مختلف ‪ a‬و ‪ b‬را می نویسیم‪ )2 .‬جاهایی که غیرپایانه می تواند قرار بگیرد‪.‬‬

‫ب)‬

‫‪-a-a-b-‬‬ ‫در قسمت خط تیره غیر پایانه می توان قرار داد‬

‫‪-a-b-a-‬‬
‫‪-b-a-a-‬‬

‫‪SSaab| aSab| aaSb| aabS‬‬


‫‪SSaba| aSba| abSa| abaS‬‬
‫‪SSbaa| bSaa| aaSb| baaS‬‬
‫‪SSS|λ‬‬ ‫الندا برای خاتمه‪ :‬تعداد داده ها صفر می شود قاعده برقرار است‬

‫‪S‬‬ ‫مثال‪ :‬آیا گرامرهای زیر مبهم است؟‬


‫‪ :aab‬گرمر مبهم است‬ ‫دو درخت تجزیه می توان کشید‬
‫‪SAB|aaB‬‬
‫‪B‬‬ ‫‪S‬‬
‫‪A‬‬
‫‪Aa|Aa‬‬
‫‪Bb‬‬ ‫‪A‬‬ ‫‪a‬‬ ‫‪b‬‬ ‫‪a‬‬ ‫‪B‬‬
‫‪a‬‬

‫‪a‬‬ ‫‪58‬‬
‫‪b‬‬
‫‪S‬‬
‫‪S‬‬
‫‪SA|Ab‬‬ ‫‪ :aa‬گرامر مبهم است‬
‫‪A‬‬
‫‪AAa|λ‬‬
‫‪a‬‬ ‫‪B‬‬
‫‪BBb|a‬‬ ‫‪A‬‬
‫‪a‬‬
‫‪a‬‬
‫‪a‬‬ ‫‪A‬‬

‫‪A‬‬
‫‪S‬‬
‫‪S‬‬ ‫‪S‬‬
‫‪S‬‬

‫‪B‬‬
‫‪A‬‬ ‫‪a‬‬ ‫‪B‬‬ ‫‪A‬‬
‫‪a‬‬ ‫‪a‬‬ ‫‪B‬‬
‫‪b‬‬
‫‪A‬‬ ‫‪a‬‬
‫‪b‬‬ ‫‪a‬‬ ‫‪A‬‬
‫‪a‬‬
‫‪a‬‬ ‫‪A‬‬
‫‪a‬‬

‫‪A‬‬

‫دو درخت تجزیه ای برای ‪aab‬‬ ‫دو درخت تجزیه ای برای ‪aa‬‬

‫روش های رفع ابهام‪:‬‬

‫(برای هر زمان گرامرهای مختلف می توان نوشت‪ .‬اگر گرامر یک زمان مبهم می توان تغییر داد یعنی زبانها‬

‫ذاتاً مبهم هستند)‪.‬‬

‫‪-1‬تغییر گرامر‪ :‬هر گرامر یک زبان را توصیف می کند‪ .‬اما برای هر زبان گرامرهای متعددی می توان نوشت‬

‫لذا با تغییر گرامر می توان ابهام آن را رفع نمود‪.‬‬

‫‪59‬‬
‫گرامر مبهم‬

1 ‫ قاعده‬stmt if expr then stmt

2 ‫ قاعده‬stmt -- if expr then stmt else stmt| other

if E1 then if E2 then S1 else S2

)‫ (باید اولویت بندی کرد‬f ‫ معلوم نیست مربوط به کدام‬else

S2

:‫درخت تجزیه‬

1 ‫قاعده‬ stmt

if E1 then stmt

S1 else S2
if E2 then

2 ‫قاعده‬
stmt

then stmt else S2


if E1
‫ عبارت‬else ‫و‬then ‫بین‬

.‫باالیی را قرار دهیم‬


if E2 then S1

60
‫دو درخت تجزیه به دست آمد پس گرامر مبهم است و باید رفع ابهام کرد‪ .‬اگر بجای ‪ stmt‬جمله ‪balance‬‬

‫(‪ )if- else‬بتوان قرار داد ابهام ایجاد نمی شود‪.‬‬

‫گرامر غیر مبهم معادل‪:‬‬

‫‪matchedif expr then matched else matched | other‬‬


‫‪unmatched if expr then stmt‬‬ ‫‪stmtmatched|unmatched‬‬
‫‪|if expr then matched else matched| other‬‬
‫روش های رفع ابهام‪...‬‬

‫‪ -2‬استفاده از قوانین جانبی‪ :‬بدون تغییر گرامر‪ ،‬قوانینی برای انتخاب یک درخت تجزیه از بین درخت های‬

‫تجزیه استفاده می کنیم‪ .‬در این صورت گرامر برای هر رشته مربوط زبان فقط یک درخت تجزیه خواهد داشت‬

‫و مثل این که مبهم نیست‪.‬‬

‫الف) استفاده از اولویت عملگرها‬

‫ب) استفاده از شرکت پذیری‬

‫یا مثال در گرامر مبهم مربوط به ‪ ،if‬می توان گفت که هر ‪ else‬به نزدیک ترین ‪ if‬مربوط می شود‪.‬‬
‫‪E‬‬
‫‪EE+E‬‬ ‫‪E‬‬

‫‪Eid‬‬
‫‪E‬‬ ‫‪+‬‬ ‫‪E‬‬
‫‪E‬‬ ‫‪+‬‬ ‫‪E‬‬

‫‪id‬‬ ‫‪E‬‬ ‫‪+‬‬ ‫‪E‬‬ ‫‪E‬‬ ‫‪+‬‬ ‫‪E‬‬ ‫‪id‬‬

‫‪id‬‬ ‫‪id‬‬ ‫‪id‬‬ ‫‪id‬‬

‫(استفاده از شرکت پذیری چپ برای عملگر جمع)‬

‫‪ id+id+id‬این رشته را دارم گرامر می تواند این رشته را تولید کند در نتیجه دو درخت تجزیه رسم شده‬

‫است‪.‬‬

‫ابهام دارد چون دو درخت تجزیه دارد اما اگر از شرکت پذیری چپ داشته باشیم رفع ابهام می شود‪.‬‬

‫‪61‬‬
‫توجه‪ :‬عملگر یکسان باشند یا اولویت یکسان داشته باشند عملگری اولویت باالتری دارد که سمت چپ باشد‪.‬‬

‫در این صورت تنها یکی از درخت ها مورد قبول است‪.‬‬

‫بازگشتی چپ‪:‬‬

‫اگر سمت راست قاعده تولید با غیرپایانه سمت چپ قاعده تولید شود‪ ،‬در این صورت گرامر دارای بازگشتی‬

‫چپ است‪.‬‬

‫انواع بازگشتی چپ‪:‬‬

‫‪A  A‬‬ ‫*) ‪  (VuT‬‬ ‫‪ )1‬بازگشتی چپ مستقیم‬

‫نیست)‬ ‫مشخص‬ ‫چپ‬ ‫بازگشتی‬ ‫اولیه‬ ‫ظاهر‬ ‫(در‬ ‫مستقیم‬ ‫غیر‬ ‫چپ‬ ‫بازگشتی‬ ‫‪)2‬‬

‫*‬
‫‪A  A‬‬ ‫*) ‪  (V uT‬‬

‫جایگذاری‬
‫مثال‪:‬‬

‫‪S  AB  S  S B‬‬
‫‪ A  S‬بازگشتی چپ غیر مستقیم‬
‫‪‬‬

‫حذف بازگشتی چپ مستقیم‪:‬‬

‫*‪i  V uT ‬‬

‫‪) B i  V uT‬‬ ‫*‪‬‬ ‫(با ‪ A‬شروع نمی شود‪:‬‬

‫‪A  A1 | A2 | ...| Am | B1 | B2 | ...| B n‬‬

‫‪ A  1A  | 2A  | ... |  n A ‬‬


‫‪‬‬
‫‪ A   1A  | 2A  | ... |  m A  | ‬‬

‫‪62‬‬
‫قواعد به دو دسته تقسیم می شوند‪:‬‬

‫‪A  Ai‬‬ ‫‪i 100m -1‬‬

‫‪ A  B i‬که با ‪ B i‬یا ‪ A‬شروع نمی شود‪.‬‬ ‫‪i 100m -2‬‬

‫مثال‪:‬‬

‫‪1 : 2‬‬
‫‪A  Ab | a | b‬‬
‫‪A  aA  | bA ‬‬
‫‪ A   bA  | ‬بازگشتی است در تجزیه کننده باال به پایین مشکل ایجاد نمی کند‪ ،‬بازگشتی چپ‬

‫مشکل ایجاد می کند که باید حل شود‪.‬‬

‫حذف بازگشتی چپ غیر مستقیم‪:‬‬

‫{)‪for (each I from 1 to n‬‬


‫{)‪for(each y from I to i-1‬‬
‫به جای هر قاعده قواعد ‪ A j ، Ai  A j ‬جایگذاری می کنیم با‪:‬‬

‫‪Ai  S1 | S 2 | S 3 | ...‬‬


‫‪A y  S1 | S 2 | S 3 | ...‬‬

‫بازگشتی چپ مستقیم را حذف می کنیم‪.‬‬

‫مثال‪:‬‬

‫‪ S , A‬غیر پایانه‬
‫‪1 2‬‬

‫‪A  A 1 | A 2 | ‬‬
‫‪A  BA ‬‬
‫‪‬‬
‫‪A   1A  | 2A  | ‬‬

‫‪63‬‬
S  Ab |b
A  Sb | A a  A  A bb | bb | A a

.‫بازگشتی چپ مستقیم و بازگشتی چپ غیر مستقیم دارد‬

‫جایگذاری می کنیم‬

S  Ab | b 
 S  Ab | b
A  bbA   
A   aA  | bbA  |  A   Abb | bb | Aa
 
A  bbA 
S  Sb | b |
A 
:‫مثال‬

S  Ab |b S  Ab | b
 S  SbA b | b
.‫*حل استاد رو بنویسید‬ A  Sb | A a  A  SbA   
B A   aA | A A   aA  | 

:‫غیر پایانه جدید‬

S  bS 
.‫) ابتدا بازگتشی چپ مستقیم را حذف کردیم‬1 S   bA bS  | 
A   aA  | 

.‫) سپس بازگشتی چپ غیر مستقیم را حذف کردیم‬2

64
:‫مثال‬

 
E  E  T |T
T T * F | F ‫بازگشتی را حذف کنیم‬
F  (E ) | id

E  TE 
E   TE  | 
T  FT 
T   *FT  | 
F  (E ) | id
:‫مثال‬

N  ATN  N   N 
N  AT  
N   aTN  |  N    N  | 
A  Na | a
T Ta | b A a

T  bT 

T   aT  | 
 
N  N a T | AT
A a
T T a | b
 

65
‫مثال‪:‬‬

‫‪ N   NdN  | aN ‬‬


‫‪ N  BNd | a ‬‬
‫‪‬‬ ‫‪  N   dN  | ‬‬
‫‪  b | ‬‬ ‫‪  b‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬ ‫‪ 1 2‬‬
‫‪ N  N d |  Nd‬‬ ‫‪|a‬‬
‫‪‬‬
‫‪   B‬‬

‫در تجزیه باال به پایین بازگشتی چپ باید حذف شود چون باعث می شود در حلقه بی نهایت بمانند‪.‬‬

‫مثال‪ :‬بازگشتی چپ گرامرهای زیر را رفع کنید؟‬

‫‪1‬‬ ‫‪1‬‬ ‫‪2 ‬‬


‫‪‬‬
‫‪A  Aa | aBc |   ‬‬
‫‪A  aBcA  | A ‬‬
‫‪‬‬
‫‪B  Bb | bc‬‬ ‫‪ ‬‬
‫‪A   aA  | ‬‬
‫‪2  3‬‬ ‫‪‬‬

‫‪S  Aa | b‬‬ ‫‪S  Aa |b‬‬


‫‪A  Ac | Aad | bd | ‬‬ ‫‪A  bdA  | A ‬‬
‫‪1‬‬ ‫‪2‬‬ ‫‪1 2‬‬ ‫‪A   cA  | adA  | ‬‬

‫فاکتورگیری چپ‪:‬‬

‫برای یک غیر پایانه ممکن است‪ ،‬انتخاب های مختلفی از یک قاعده تولید وجود داشته باشد‪ .‬لذا برای راحت‬

‫کردن تجزیه پیشگو (فصل بعدی)‪ ،‬از فاکتورگیری چپ استفاده می کنیم‪.‬‬

‫‪A  1 | 2‬‬

‫‪66‬‬
‫مثال‪:‬‬

‫نمی دونیم کدام را انتخاب کنیم و در تجزیه پیشگو ابهام ایجاد می کند چون به ازاء یک قاعده چندین‬

‫‪A  aA | A‬‬ ‫قاعده تولید نباید باشد‪.‬‬

‫‪A  1 | 2 | ... |  n | ‬‬


‫‪‬‬
‫‪A   A  | ‬‬
‫‪‬‬
‫‪A   1 | 2 | ... |  n‬‬
‫مثال‪:‬‬

‫‪A  aA ‬‬
‫‪A  aA | a ‬‬
‫‪A  A |‬‬
‫به ازای تولید یک قاعده چند حالت که با یک حرف شروع شود را ندارم و فاکتور گیری چپ انجام شده‬

‫مثال‪:‬فاکتورگیری چپ را برای گرامر زیر انجام دهید‪.‬‬

‫(بخش مشترک را در نظر می گیریم)‬

‫‪S  a ABb | a BC‬‬


‫‪1‬‬ ‫‪2‬‬

‫‪S  aS ‬‬
‫‪A  aBB | aB‬‬ ‫‪‬‬
‫‪S   ABb | Bc‬‬
‫‪A  aBA ‬‬ ‫‪C  cC ‬‬
‫‪B  bB | b‬‬ ‫‪‬‬ ‫‪‬‬
‫‪A  B | ‬‬ ‫‪C   C | ‬‬
‫‪B  bB ‬‬
‫‪C  cC | c‬‬ ‫‪‬‬
‫‪B   B | ‬‬

‫‪67‬‬
‫تجزیه باال به پائین(‪(top – down parsing‬‬

‫‪ ‬در تجزیه کننده های باال به پائین برای تشخیص تعلق رشته ورودی به گرامر درخت تجزیه از ریشه‬
‫( عالمت شروع گرامر ) به سمت برگها ( پایانه ها در گرامر ) ساخته می شود ‪ .‬در واقع ترتیب ساخت‬
‫در درخت ‪ ،‬براساس اشتقاق چپ می باشد ‪.‬‬
‫مثال ‪ :‬برای رشته ‪ id+id*id‬براسا س گرامر زیر تجزیه کننده باال به پائین رسم کنید ‪.‬‬

‫‪E→E+T|T‬‬
‫‪T→T*F|F‬‬
‫‪F→(E)|id‬‬

‫‪E‬‬ ‫‪E‬‬ ‫‪E‬‬

‫‪E‬‬ ‫‪T‬‬ ‫‪T‬‬ ‫‪E‬‬ ‫‪T‬‬ ‫‪T‬‬ ‫‪E‬‬ ‫‪T‬‬ ‫‪T‬‬

‫)‪(1‬‬ ‫‪T‬‬ ‫‪T‬‬

‫)‪(2‬‬ ‫‪F‬‬

‫‪id‬‬ ‫)‪(3,4‬‬

‫‪E‬‬ ‫‪E‬‬ ‫‪E‬‬

‫‪E‬‬ ‫‪T‬‬ ‫‪T‬‬ ‫‪E‬‬ ‫‪T‬‬ ‫‪T‬‬ ‫‪E‬‬ ‫‪T‬‬ ‫‪T‬‬

‫‪T‬‬ ‫‪T * F‬‬ ‫‪T‬‬ ‫‪T * F‬‬ ‫‪T‬‬ ‫‪T‬‬ ‫‪* F‬‬

‫‪F‬‬ ‫‪F‬‬ ‫‪F‬‬ ‫‪F‬‬ ‫‪F‬‬ ‫‪id‬‬

‫‪Id‬‬ ‫)‪(5‬‬ ‫‪id‬‬ ‫)‪(6‬‬ ‫‪id‬‬ ‫‪id‬‬ ‫) ‪(7 , 8‬‬

‫‪68‬‬
‫تجربه پیشگو بازگشتی‪:‬‬

‫بطور رسمی و خطا عمل می کند‪ .‬اگر فاکتور گیری چپ انجام نشده باشد این روش می تواند تعلق رشته و‬
‫گرامر را تشخیص دهد‪.‬‬

‫‪S→cAd‬‬

‫هر کدام باید تست شود‬

‫‪A→ab|ac|a‬‬

‫‪S‬‬ ‫‪S‬‬ ‫‪S‬‬ ‫‪S‬‬

‫‪C‬‬ ‫‪A‬‬ ‫‪d‬‬ ‫‪C‬‬ ‫‪A‬‬ ‫‪d‬‬ ‫‪C‬‬ ‫‪A‬‬ ‫‪d‬‬ ‫‪C‬‬ ‫‪A‬‬ ‫‪d‬‬

‫‪a‬‬ ‫‪b‬‬ ‫‪a‬‬ ‫‪c‬‬ ‫‪a‬‬

‫×‬ ‫×‬ ‫√‬


‫رشته‬ ‫‪c‬‬ ‫‪a‬‬ ‫‪d‬‬ ‫قابل قبول نیست ‪ back‬می کنیم‬ ‫‪36367738‬‬

‫قاعده ای که با آن شروع شود‬

‫‪First(α):‬‬

‫‪ ‬اگر ‪ a‬یک رشته از نمادهای گرامر باشد‪ First(α)،‬مجموعه ای از پایانه ها خواهد بود که رشته های‬

‫مشتق شده آن ها شروع می شود ‪ .‬اگر ‪ α→ λ‬آنگاه ‪ λ‬نیز در )‪ First(α‬قرار دارد ‪.‬‬

‫مثال ‪:‬‬

‫‪A→aA|B‬‬ ‫} ‪First(A) = { a , λ‬‬

‫‪B→ λ‬‬ ‫با ‪ n‬شروع می شود رشته های تولیدی با ‪ a‬است‬

‫‪ λ‬را هم ‪ A‬می تواند تولید کند‬

‫‪69‬‬
‫‪A→ a‬‬ ‫}‪First(A) ={0‬‬ ‫نحوه محاسبه )‪: First(x‬‬

‫‪ ‬در صورتیکه ‪ X‬یک پایانه باشد آنگاه ‪First(X)=X‬‬

‫‪ ‬اگر ‪ X‬یک غیرپایانه و ‪ X=y1 y2 ….. yk‬مولد برای‪ k≥ 1‬باشد آنگاه برای هر ‪ i‬و ‪ a‬در مجموعه‬

‫)‪ First(yi‬قرار داشته باشد و ‪ λ‬در تمام مجموعه های )‪ First(y1) …. First(yi-1‬قرار داشته باشد‬

‫‪A→ BCD‬‬ ‫‪D→ d‬‬ ‫‪ ‬آنگاه ‪ a‬به مجموعه )‪ First(x‬اضافه می شود‪.‬‬

‫‪B→λ‬‬

‫‪C→λ‬‬

‫‪ ‬اگر برای تمام مقادیر ‪ Y=1,2,….. K‬رشته الندا در مجموعه )‪ First(YJ‬وجود داشته باشد آنگاه ‪λ‬‬

‫𝐷𝐶𝐵 → ‪A‬‬ ‫به )‪ First(X‬اضافه می گردد ‪.‬‬

‫‪D→ d| λ‬‬ ‫‪B→ λ‬‬

‫‪C→λ‬‬

‫مثال ‪ :‬با توجه به گروه های زیر ‪ First‬را محاسبه کنید ‪.‬‬
‫‪1‬‬ ‫‪2‬‬
‫‪A→ 𝐴𝐶𝑎| λ‬‬ ‫𝐴|𝑠𝐴𝑠|𝑎𝑠𝑏 →‪S‬‬

‫‪C→ 𝑐𝐶| λ‬‬ ‫‪A→ 𝑎𝐴| λ‬‬


‫‪3‬‬ ‫‪4‬‬
‫´‬
‫𝐸𝑇 →‪E‬‬ ‫‪S → ABCbDE‬‬

‫‪𝐸´ → +𝑇𝐸´| λ‬‬ ‫‪A→ 𝑎𝐴|𝐴𝐵𝑐|λ‬‬

‫‪𝑇 → 𝐹𝑇´| λ‬‬ ‫‪B→ 𝑏|λ‬‬

‫‪𝑇´ →∗ 𝐹𝑇´| λ‬‬ ‫‪C→ 𝑆𝑐|λ‬‬

‫‪𝐹 → (𝐸)| id‬‬ ‫𝑑→‪D‬‬

‫‪E→ 𝑒𝐸|λ‬‬

‫‪70‬‬
1 ‫ حل‬:

A→ 𝐴𝐶𝑎| λ First (A)={ λ,C,a}

C→ 𝑐𝐶| λ First (C)={C, λ }

2 ‫ حل‬:

S → 𝑏𝑆𝑎|𝑆𝐴𝑆| A First (S)={ b,a,λ }

a → 𝑎𝐴|λ First (A)={a,λ }

3‫ حل‬:

E→ 𝑇𝐸´ First (E)={ ( , id }

𝐸´ → +𝑇𝐸´|λ First (𝐸´)={+,λ }

T→ 𝐹𝑇´ First (T)= First (E)= First (F)

𝑇´ →∗ 𝐹𝑇|λ First (𝑇´)={ * , λ }

𝐹 → (𝐸)|𝑖𝑑

4‫ حل‬:

S→ 𝐴𝐵𝐶𝑏𝐷𝐸 First (S)={ a,b,c, λ }

𝐴 → 𝑎𝐴|𝐴𝐵𝑐|λ First (𝐴)={a,b,λ,c }

B→ 𝑏|λ First (B)= { b, λ }

𝐶 → 𝑆𝑐|λ First (𝐶)={a,b,c,λ }

𝐷→𝑑 First (𝐷)={d }

71
‫‪𝐸 → 𝑒𝐸|λ‬‬ ‫} ‪First (𝐸)={e,λ‬‬

‫)‪: Follow(A‬‬

‫‪ ‬برای غیر پایانه ‪ Follow(A) ، A‬برابر است با مجموعه ای از پایانه ها مانند ‪ a‬که در هر شبه جمله‬

‫بالفاصله در سمت راست ‪ A‬قرار می گیرند ‪.‬بعبارت دیگر مجموعه ای از پایانه ها مانند ‪ a‬به شکلی‬

‫که برای هر ‪ B‬و ‪ a‬یک اشتقاق بلو است ‪ S→ 𝛼𝐴𝑎𝛽 .‬وجود داشته باشد‬

‫‪ ‬در صورتیکه ‪ ، A‬آخرین نماد در شبه جمله باشد ‪ ،‬آنگاه ‪ $‬در )‪ Follow(A‬قرار می گیرد‬

‫‪ $ ‬در )‪ Follow(A‬قرار داده می شود که ‪ S‬نماد شروع گرامر و ‪ $‬نماد مشخص کننده انتهای سمت‬

‫راست رشته ورودی است ‪.‬‬

‫‪ ‬اگر مولدی به صورت 𝑆 𝛽𝐵 𝛼 → وجود داشته باشد آنگاه هر چندی در )‪ First(β‬به جز الندا‬

‫به مجموعه (‪ Follow(β‬اضافه می شود ‪.‬‬

‫بنابراین داریم ‪:‬‬

‫}‪Follow(B)=( Follow(B)u{First(β) – { λ}|A→a B β ∈ G‬‬

‫‪ab$‬‬ ‫𝑆𝑎𝐴 → 𝑆 ‪ :‬مثال‬

‫𝐵𝐴 → 𝐴‬

‫‪𝐵 → 𝑏𝐵| λ‬‬ ‫} ‪First(B) = {b, λ‬‬

‫‪ ‬اگر مولدی بصورت 𝐵𝛼 → ‪ A‬وجود داشته باشد ‪ ،‬یا مولدی بصورت 𝛽𝐵 𝛼 → ‪ A‬که )‪First(β‬‬

‫حاوی ‪ λ‬باشد )‪ ) β → λ‬آنگاه هر چیزی در مجموعه (‪ Follow(A‬به ( ‪ Follow(B‬اضافه می‬

‫شود‪.‬‬

‫𝐵𝑎 →‪A‬‬ ‫)‪Follow(A( ∈ Follow(B‬‬

‫‪C→ λ‬‬

‫‪72‬‬
E→ 𝑇𝐸´ Follow (E)={ $ , ) }

𝐸´ → 𝑇𝐸´|λ Follow (𝐸´)={ $, ) }

T→ 𝐹𝑇´ Follow (T)= { + , $ , ) }

𝑇´ →∗ 𝐹𝑇|λ Follow (𝑇´)={ + , ) , $ }

𝐹 → (𝐸)|𝑖𝑑 Follow (𝐹)={ *, + , ) , $ }

‫ را محاسبه کنید‬Follow ‫ با توجه به گرامرهای زیر‬: ‫مثال‬


1

𝐴 → 𝐵𝑒𝐶

𝐵 → 𝑎𝐵|λ

𝐶 → 𝑏𝐶𝐴|C

3: E →TE´

2 : 𝐸´ → 𝐸|λ

𝑆 → 𝐵𝑒 𝑇 → 𝐹𝑇´

𝐵 → 𝐴𝐵𝑐|𝐵𝑏|λ 𝑇´ → 𝑇|λ

𝐴 → 𝐴𝛼|λ 𝐹 → 𝑃𝐹´

𝐶 → 𝑑𝐴𝐵|λ 𝐹´ → 𝑃𝐹´

𝐹´ → 𝑃𝐹´

𝐹´ →∗ 𝐹´| λ

𝑃 → (𝐸)|a|b|c

73
1
2
Follow(A( = Follow(C( Follow(S(= {$}

Follow(B( = {e} Follow(B( = {b,d,e}

Follow(c( = First (A) = { a, e} Follow(C( = Follow(B(

{a , e , $ } Follow(A( = { a, d}

B→ 𝐴 𝐵𝐶

A→ 𝐴𝑎

c→ 𝑑 𝐴 𝐵
3

Follow(E( = { ) , $ }

Follow (𝐸´)={ ) , $ }

Follow (𝑇)={ + , ) , $ }

Follow (𝑇´)= Follow (𝑇 )

Follow (𝐹)={ ( , a , b, c , + , ) , $ }

Follow (𝐹´)={ ( , a , b, c , + , ) , $ }

Follow (𝑝)={* , ( , a , b, c , + , ) , $ }

: ‫تجزیه کننده پیشگو‬

. ‫ یک تابع وجود دارد‬، ‫ در این تجزیه کننده برای هر غیر پایانه‬

. ‫ سمت راست یک غیر پایانه انتخاب می شود‬، ‫ براساس هر نماد ورودی از ؟‬

74
aB a ← First (A) ‫ فراخوانی شود‬A ‫ اگر نماد‬

A→
B→ bB λ|

: ‫ایجاد تجزیه کننده پیشگو برای گرامر مقابل‬

S→ A| B

A→ aA | C

B→ bB| d

: ‫ را درنظر می گیریم‬B ) ( ، A ) ( ، S( ) ‫سه تابع‬

Vad s ( ) f

If ( lookahead = = ´a´´ll lookaheed = = ´c´ )

A()

else If ( lookahead = = ´b´´ll lookaheed = = ´d´ )

(B)

Else

(eaut ≪ Error ) }

75
‫) ( ‪Void A‬‬ ‫} ‪First ( A ) = { a , c‬‬

‫{‬ ‫} ‪First ( B ) = { b , d‬‬

‫) ´ ‪If ( lookahead = = ´a‬‬ ‫‪ab‬‬

‫}‪{ Match ( ´a´) , A ( ) ,‬‬

‫‪else‬‬ ‫) ´ ‪If ( lookahead = = ´c‬‬

‫‪{ Match ( ´c´) ,‬‬

‫‪else‬‬

‫} ‪{ cout ≪ Error ,‬‬

‫}‬

‫) ( ‪Void B‬‬

‫) ´ ‪If ( lookahead = = ´b‬‬

‫}‪{ Match ( ´b´) , B ( ) ,‬‬

‫‪else‬‬ ‫) ´ ‪If ( lookahead = = ´d‬‬

‫‪{ Match ( ´d´) ,‬‬

‫} ‪else { cout ≪ Error ,‬‬

‫تجزیه کننده پیشگو‬

‫با استفاده از این کد ما این تجزیه کننده را پیاده سازی کردیم ‪.‬‬

‫در تجزیه پیشگو ( تجزیه باال به پائین ) اگر بازگشت چپ ‪ ،‬فاکتورگیری چپ باشد ما مشکل ایجاد می کنیم‪.‬‬

‫در گرامرهای زیر نمی توان تجزیه کننده پیشگو ایجاد کرد‬

‫‪76‬‬
S→ 𝑆𝑎𝐴|𝐴 S→ 𝑎𝑆|𝑎𝐴

A→ 𝑎𝐴|𝑎 A→ 𝑎𝐴|𝑏

‫هر دو‬First ( S ) ‫ و‬First ( A ) ‫ نمی توان یکی را انتخاب کرد پس مشکل ایجاد می شود چون‬A ‫ و‬S ‫بین‬

‫شده‬a

Void s ( ) {

S( ),

Match (´a ´) ,

A(),

: First / First ‫برخورد‬

A→ α1|α2|…|αn

∃I , j , first ( αi ) ? first ( α j ) ≠ ϕ i≠ 𝑗

‫ حذف کنید‬First / First ‫ در گرامرهای زیر برخورد‬: ‫مثال‬

s→ as|aA|𝑎𝑏 S→as´

A→ bA| λ ‫حل مشکل‬ s´→S|A|b

A→bA| λ

A→ aABb|aAB|𝛼𝐴 A →aAA´ A´→BA´´|λ


‫حل مشکل‬
B→ bB|aB A´→Bb|B|λ ‫برخورد‬ first |

first
77
‫‪B→ bB|aB‬‬ ‫‪A´´→b|λ‬‬

‫𝑆|‪A→ αB1|αB2|…|αBn‬‬ ‫‪A→αA´|s‬‬


‫‪A´→ B1|B2|…|Bn‬‬

‫تجزیه کننده پیشگویی غیر بازگشتی ‪:‬‬

‫استفاده از ساختار کد و ‪ if‬های متوالی سرعت اجرا را پائین می آورد ‪ ،‬اذا برای حل مشکل از جدول تجزیه‬

‫استفاده می کنیم ‪ ،‬در واقع برای هر غیر پایانه ‪ ،‬متناسب با هر پایانه ورودی ‪ ،‬قاعده تولید مناسب را در‬

‫جدول ثبت می کنیم ‪ .‬و تجزیه کننده از این جدول برای انتخاب مولد مناسب استفاده می کنند ‪.‬‬

‫‪S→ aS|bS|λ‬‬
‫‪a‬‬ ‫‪b‬‬
‫‪S → ab‬‬ ‫‪S → bs‬‬

‫‪asb$‬‬
‫*تحلیلگر لغوی به نحوی‬
‫‪ a1‬وارد شده اند آیا مطابقت وارد‬ ‫‪a2‬‬ ‫‪a3‬‬ ‫‪a4‬‬ ‫…‬ ‫‪an‬‬ ‫‪$‬‬
‫با گرامر زبان ما ‪ .‬اگر مطابقت‬
‫دارد اگر ندارد اعالم خطا می‬
‫کند‬
‫به پپشته و رشته ورودی‬
‫مراجعه می کند‬

‫الگوریتم تجزیه کننده‬ ‫‪Accept‬‬


‫‪X‬‬
‫‪Error‬‬
‫‪Y‬‬ ‫پیشگو‬
‫تطابق می دهد رشته ورودی‬
‫‪Z‬‬ ‫را با جدول تجزیه پیشگو‬
‫می تواند اعالم خطا کند‬
‫‪$‬‬ ‫یعنی این رشته وارد شد این‬
‫دنباله ‪ token‬ها که از*‬

‫پشته که غیر پایانه قرار می‬


‫جدول تجزیه پیشگو‬
‫گیرند و پایانه هایی که در‬
‫قواعد مولد هستند‬ ‫با توجه به رشته ورودی از‬
‫جدول تجزیه پیشگو استفاده‬
‫می شود‬
‫‪78‬‬
‫ایجاد جدول تجزیه پیشگو ‪:‬‬

‫‪ ‬برای هر مولد از گرامر به صورت 𝛼 → ‪ A‬مراحل زیر را انجام می دهیم‬

‫𝛼 → ‪M[ A , 𝑎 ] ………… A‬‬

‫‪A→ 𝛼 ∈ 𝑀[𝐴 , 𝐹𝑖𝑟𝑠𝑡(𝛼 ) − λ‬‬

‫‪ -2‬اگر ‪ λ‬در ) 𝛼(𝑡𝑠𝑟𝑖𝐹 باشد 𝛼 → ‪ A‬را برای هر پایانه در ) 𝐴( ‪ Follow‬به ] ‪ M[ A , b‬اضافه می‬

‫کنیم‬

‫‪ -3‬اگر ‪ λ‬در )𝛼(𝑡𝑠𝑟𝑖𝐹 باشد و ‪ $‬در ) 𝐴( ‪ Follow‬باشد 𝛼 → ‪ A‬را به ]‪ M[ A , $‬اضافه می کنیم‬

‫) 𝛼(𝑡𝑠𝑟𝑖𝐹 ∈ ‪A → 𝛼 ∈ 𝑀[𝐴 , Follow (𝐴 )]| λ‬‬

‫اگر با اجرای مراحل باال مولدی در خانه }‪ M[A,a‬وجود نداشته باشد‪ ،‬آنگاه خطا اعالم می شود ‪.‬‬

‫غیر پایانی‬ ‫𝑎‬

‫‪A‬‬ ‫𝑎 →‪A‬‬
‫𝐴𝛼 → ‪A‬‬ ‫مثال‬

‫‪AB → BC‬‬ ‫‪C→ λ‬‬

‫‪B→ Axy | λ‬‬

‫مثال ‪:‬‬

‫´𝐸𝑇 →‪1 E‬‬

‫‪2 𝐸´ → 𝑇𝐸´|λ 3‬‬

‫´𝑇𝐹 →‪4 T‬‬

‫‪5 𝑇´ →∗ 𝐹𝑇|λ‬‬ ‫‪6‬‬ ‫𝑑𝑖|)𝐸( → 𝐹 ‪7‬‬ ‫‪8‬‬

‫‪79‬‬
‫‪id‬‬ ‫‪+‬‬ ‫*‬ ‫(‬ ‫)‬ ‫‪$‬‬

‫‪id‬‬ ‫‪+‬‬ ‫*‬ ‫(‬ ‫)‬ ‫‪$‬‬

‫‪E‬‬ ‫´𝐸𝑇 →‪E‬‬ ‫´𝐸𝑇 →‪E‬‬

‫´𝐸‬ ‫´𝐸𝑇 → ´𝐸‬ ‫‪𝐸´ → λ‬‬ ‫‪𝐸´ → λ‬‬

‫‪T‬‬ ‫´𝑇𝐹 →‪T‬‬ ‫´𝑇𝐹 →‪T‬‬

‫´𝑇‬ ‫𝜆 → ´𝑇‬ ‫´𝑇𝐹 ∗→ 𝐹‬ ‫‪T´ →λ‬‬ ‫𝜆 → ´𝑇‬

‫𝐹‬ ‫𝑑𝑖 → 𝐹‬ ‫)𝐸( → 𝐹‬

‫خواستیم سطر ‪ E‬را پر کنیم باید به ‪First‬نگاه کنیم اگر ‪ λ‬بود‬

‫‪A → 𝐶𝐵|λ‬‬

‫‪𝐵 → 𝑐𝐶𝐵|λ‬‬

‫𝐷𝐸 → 𝐶‬

‫‪𝐷 → 𝑎𝐸𝐷|λ‬‬

‫)‪𝐸 → 𝑏|(A‬‬

‫}‪F(A)={ b , ( , λ‬‬

‫}‪F(B) = { C , λ‬‬

‫‪80‬‬
‫𝑎‬ ‫‪b‬‬ ‫‪c‬‬ ‫(‬ ‫)‬ ‫‪$‬‬

‫‪A‬‬ ‫𝐵𝐶 →‪A‬‬ ‫𝐵𝐶 →‪A‬‬ ‫‪A→λ‬‬ ‫𝜆→𝐴‬

‫𝐵‬ ‫𝐵𝐶𝐶 → 𝐵‬ ‫‪B →λ‬‬ ‫𝜆→ 𝐵‬

‫‪C‬‬ ‫𝐷𝐸 → 𝐶‬ ‫𝐷𝐸 → 𝐶‬

‫‪D‬‬ ‫𝐷𝐸𝑎 → 𝐷‬ ‫‪𝐷→λ‬‬ ‫‪𝐷→λ‬‬ ‫‪𝐷→λ‬‬

‫‪E‬‬ ‫𝑏→𝐸‬ ‫)‪𝐸 → (A‬‬

‫الگوریتم تجزیه غیربازگشتی پیشگو‬

‫‪ ‬در صورتیکه رشته ‪ W‬در )‪ L(G‬باشد ‪ ،‬این الگوریتم سمت چپ ترین اشتقاق را برای ‪ W‬برگشت می‬

‫دهد و در غیر اینصورت اعالم خطا می کند‪.‬‬

‫‪ ‬در ابتدا عالمت ‪ $‬به انتهای رشته ‪ W‬اضافه می شود و در بافر ورودی قرار ی گیرد و نماد شروع گرامر‬

‫در باالی پشته و باالی ‪ $‬قرار می گیرد‬

‫اگرنماد باالی پشته ‪ X‬وتوکن جاری را ‪a‬بنامیم ‪ ،‬آنگاه تجزیه کننده تا هنگامی که پشته خالی نشده است‬

‫اعمال زیر را انجام می دهد ← اگر پشته خالی شود رشته پذیرفته شده‬

‫الف ) اگر ‪ X‬یک غیر پایانه بود و با توکن‪ a‬برابر بود آنگاه از باالی پشته حذف شده و ‪ a‬با توکن بعدی مقدار‬

‫دهی می شود ‪.‬‬

‫ب) اگر ‪ X‬یک غیر پایانه بود و ] 𝑎 ‪ M[X ,‬در جدول تجزیه تهی بود آنگاه اعالم خطا می شود‬

‫ج) اگر ‪ X‬برابر یک غیر پایانه بود و ] 𝑎 ‪ M[X ,‬برابر قاعده ‪ X→ y1 y2….yK‬باشد ‪،‬آنگاه ‪ X‬را از باالی پشته‬

‫حذف کرده و به جای آن ‪ y1, y2,….yK-2,yk‬را قرار میدهیم‪.‬‬

‫د) اگر ‪ X‬پایانه بود و با توکن ‪ a‬یکسان نبود اعالم خطا می شود‪.‬‬

‫‪81‬‬
‫این رشته جزء گرامر هست یا نه ؟‬

Id+ Id* Id $

‫تطبیق داده شده‬ ‫پشته‬ ‫ورودی‬ ‫قاعده‬

E$ id+id*id$
TE´$ id+id*id$ 𝐸 → 𝑇𝐸´
FT´E´$ id+id*id$ 𝑇 → 𝐹𝑇´
idT´E´$ id+id*id$ 𝐹 → 𝑖𝑑
id T´E´$ +id*id$ id
id E´$ +id*id$ T´→ λ

id + TE´$ +id*id$ E´→ + TE´

id+ TE´ id*id$ +


id+ FT´E´$ id*id$ T→FT´

id+ idT´E´$ id*id$ F→ id

id+ id T´E´$ *id$ id


* FT´E´$ *id$ T´→ *FT´

‫تطبیق داده شده‬ ‫پشته‬ ‫ورودی‬ ‫قاعده‬

id+id* FT´E´$ id$ *


id+id* idT´E´$ id$ 𝐹
id+id*id T´E´$ $ 𝑖𝑑
id+id*id E´$ $ T´→ λ

id+id*id $ $ E´→ λ

82
‫گرامر (‪LL )1‬‬

‫یک گرامر (‪ )1‬است برای هر توکن ورودی در اشتقاق چپ به راست بتوان غیر پایانه بعدی را برای گسترش‬

‫انتخاب نمود و در واقع عدد یک نشان دهنده این است که فقط با دیدن یک توکن کافیست تا قانون تولید‬

‫بعدی را انتخاب نمود ‪.‬‬

‫بطور کلی می توان گفت که گرامر (‪ LL )1‬مشخصات زیر را دارد‬

‫‪ First‬آن ها اشتراک داشته باشد ‪).‬‬ ‫‪ )1‬فاقد برخورد ‪ FIRST / FIRST‬است ( سمت راست‬

‫‪ )2‬فاقد برخورد ‪ FOLLOW / FIRST‬باشد‬

‫مثال ‪:‬‬

‫‪A→ 𝑎𝐵|λ‬‬

‫𝑎𝐴 → ‪B‬‬

‫‪a‬‬
‫‪A‬‬ ‫‪A→ Ab‬‬
‫‪A→ λ‬‬
‫این گرامر بدلیل برخورد ‪ LL )1( FOLLOW / FIRST‬نیست‬

‫مثال ‪:‬کدام گرامر (‪ LL )1‬است ؟‬

‫‪S→ 𝑎𝑆|𝐴|λ‬‬

‫𝑐𝑆𝑏 → ‪A‬‬ ‫𝑎 = )‪FIRST (𝑎s‬‬


‫𝑏 = )𝐴( ‪FIRST‬‬

‫این گرامر )‪ LL(1‬است‬ ‫‪FOLLOW(s)= c‬‬

‫‪FOLLOW (s) П FIRST (s) = ϕ‬‬

‫‪A→ 𝐵𝐶𝐷|𝑏|λ‬‬

‫𝐶‪B→ 𝑐𝐶|𝑒𝐵|d‬‬ ‫}‪FIRST (𝐵𝑆𝐷) = {e,d,c, λ‬‬

‫‪83‬‬
‫‪c→ 𝑐|λ‬‬

‫‪D→ 𝑑𝐷|λ‬‬

‫در گرامر یک قاعده به شکل‪ s→ α|β‬داریم که ‪ a‬و ‪ B‬و ‪ λ‬را تولید می کنند پس گرامر شرط (‪ LL)1‬بودن را ندارد‪.‬‬

‫}‪FIRST (𝐶𝐶 ) = {c, λ‬‬

‫)‪C ∈ FOLLOW(B‬‬

‫‪FIRST (𝐵) П FOLLOW(B)≠ϕ‬‬

‫مثال ‪ :‬برای گرامر زیر جدول تجزیه پیشگویی بازگشتی تشکیل دهید ؟‬

‫𝑏𝐶𝐵𝑎 →‪A‬‬

‫‪B → 𝑐𝐵𝑏 |λ‬‬

‫‪C→ 𝐶 |λ‬‬

‫𝑎‬ ‫‪b‬‬ ‫‪C‬‬ ‫‪$‬‬


‫‪A‬‬ ‫𝑏𝐶𝐵𝑎 →‪A‬‬
‫𝑏𝐵𝑐 → ‪B‬‬ ‫𝑏𝐵𝑐 → ‪B‬‬
‫‪B‬‬
‫‪B→ λ‬‬ ‫‪B→ λ‬‬
‫𝑐 →‪C‬‬
‫‪C‬‬ ‫‪C→ λ‬‬
‫‪C→ λ‬‬
‫برخورد ‪first/follow‬‬
‫این گرامر )‪ LL(1‬نیست‬

‫𝑇𝑆𝑅𝐼𝐹‬ ‫‪FOLLOW‬‬
‫‪A‬‬ ‫𝑎‬ ‫‪$‬‬
‫‪B‬‬ ‫‪c, λ, b‬‬ ‫‪Cc, b‬‬
‫‪C‬‬ ‫‪c, λ‬‬ ‫‪b‬‬

‫مثال‪ :‬در مورد گزاره های زیر اظهار نظر کنید‬

‫الف) گزاره های مبهم )‪ LL(1‬نیستند√‬

‫ب) گرامرهای دارای بازگشتی چپ )‪ LL(1‬نیستند√‬

‫‪84‬‬
‫نکته ‪ :‬هر گرامر که )‪ LL(1‬باشد مبهم نیست ‪.‬‬

‫𝑎|𝐵𝑎 →‪A‬‬ ‫گرامر مبهم‬ ‫)‪ LL(1‬نیست‬

‫‪B→ λ‬‬

‫‪A‬‬ ‫‪A‬‬ ‫برخورد ‪first/follow‬دارد‬

‫‪A‬‬ ‫‪B‬‬ ‫‪a‬‬

‫دو درخت اشتقاق دارد ‪λ‬‬

‫𝑏|𝑎‪A→ A‬‬ ‫) 𝑎‪b ∈ first (A‬‬

‫‪First (b) = b‬‬

‫𝐵|𝛼‪A→ A‬‬ ‫)𝛼‪b ∈ first (B ) ∈ first (A‬‬

‫‪First (B) П First (A𝛼 ) ≠ ϕ‬‬

‫شرط )‪ LL(1‬بودن را نقض می کند ( وقتی بازگشتی چپ داریم قطعا باید ‪λ‬باشد‪).‬‬

‫ایجاد گرامر )‪:LL(1‬‬

‫با اعمال زیر می توان گرامر غیر )‪ LL(1‬را به )‪ LL(1‬تبدیل نمود‬

‫‪ -1‬حذف بازگشتی چپ‬

‫‪ -2‬فاکتور گیری چپ‬

‫‪ -3‬رفع ابهام از گرامر مبهم‬

‫‪ -4‬نوشتن گرامر جدید برای زبان مربوط به گرامر غیر )‪LL(1‬‬

‫‪85‬‬
‫ تبدیل کنید ؟‬LL(1) ‫مثال گرامرهای زیر را به‬

A→ 𝐵𝐶𝐷|λ A→ A𝑎𝐶𝐷|𝑏𝑐𝐷|λ

B→ A𝑎|𝑏 A→ BCDA´|𝐴 A→ bc𝐷𝐴´|𝑏𝐷𝐴´|A´

c→ c|λ A→ 𝑎𝐶𝐷𝐴´|λ A→ A𝑎𝐶𝐷|𝑏𝑐𝐷|λ

D→ 𝑐𝑑 C→ C|λ D→ cd|𝑑

D→ 𝑐𝑑

A→ bB|𝐴´ A→ bB|𝐴´

B→ CDA´|𝐷𝐴´ B→ CCdA´|𝑐𝑑𝐴´|𝑑𝐴´

A→ aB|λ A´ → aB|λ

D → cd|d

A→ bB|𝐴´ A→ 𝑎𝐴

B→ cc|𝑑𝐴´ B→ bB|𝑎

c→ cdA´|dA´

A´ → aB|λ

A→ A𝑎1| A𝑎2|…. | A𝑎m|B1| B2|B333 33….|

A´ → 𝑎1A´| 𝑎2 A´|…. | 𝑎m A´| λ

A→ B1A´| B2 A´|…. | Bn A´

86
: ‫رسم جدول تجزیه‬

. ‫تجزیه کننده پیشگو بازگشتی بنویسید‬

A→ bB|𝐴´

B→ cc|𝑑𝐴´

c→ cdA´|dA´

A´ → aB|λ

𝐹𝐼𝑅𝑆𝑇 FOLLOW

A b,a,λ $

B c,d

C c,d

A´ a,λ $

$A
$Bb $A´ $A´d
$B $Ba $A´
$Cc $B $
$C $Cc
$ A´d $C

87
𝑎 b c d $

A A → A´ A→ 𝑏𝐵 𝐴 → A´

𝐵 𝐵 → 𝑐𝐶 B → 𝑑A´

C c → 𝑐𝑑A´ c → 𝑑A´

A´ A´ → aB A´ → λ

A→ 𝑎𝐴|𝐵 → A→ 𝑎𝐴|𝑏𝐵|𝑎 → 𝑎$

B→ bB|𝑎 B→ bB|𝑎 $A´ 𝑎

$A´
$

A→ 𝑎𝐴´|𝑏𝐵

A´ → 𝐴|λ

B→ 𝑏𝐵|𝑎

𝛼 b $

A A → 𝑎A´ A→ 𝑏𝐵 → A´𝐴
A´ A → 𝑎A´ A→ 𝑏𝐵 A´→ λ
B B→𝑎 B → 𝑏𝐵

88
‫مثال ‪:‬‬

‫𝑥| 𝑆 ‪S→ 𝑆 ∗ 𝑆 | 𝑆 +‬‬ ‫‪x+x*x‬‬

‫گرامر مبهم‬ ‫دو درخت تجزیه داره چون اولویت عملگرها در نظر گرفته نشده * مبهم است ‪.‬‬

‫‪S‬‬ ‫‪S‬‬

‫‪S‬‬ ‫*‬ ‫‪S‬‬ ‫‪S‬‬ ‫‪+‬‬ ‫‪S‬‬

‫‪S‬‬ ‫‪+‬‬ ‫‪S‬‬ ‫‪x‬‬ ‫‪x‬‬ ‫‪S‬‬ ‫*‬ ‫‪S‬‬

‫‪x‬‬ ‫‪x‬‬ ‫‪x‬‬ ‫‪x‬‬

‫𝐵|𝐵 ‪: A→ 𝐴 +‬رفع ابهام‬ ‫´𝐴𝐵 →‪A‬‬

‫𝐶|𝐶 ∗ 𝐵 →‪B‬‬ ‫‪A´→ +𝐵𝐴´|λ‬‬

‫𝑎 →‪C‬‬ ‫´𝐵𝐶 →‪B‬‬

‫گرامر )‪ LL(1‬نیست‬ ‫‪B´→∗ 𝐶𝐵´|λ‬‬ ‫گرامر )‪LL(1‬شد‬

‫𝑋 →‪C‬‬

‫‪+‬‬ ‫*‬ ‫‪X‬‬ ‫‪$‬‬

‫‪A‬‬ ‫´‪𝐴 → 𝐵A‬‬

‫´‪A‬‬ ‫´‪A´ → +𝐵A‬‬ ‫‪A´→ λ‬‬

‫‪B‬‬ ‫´‪𝐵 → CB‬‬

‫´‪B‬‬ ‫‪𝐵´ → λ‬‬ ‫´‪𝐵´ →∗ CB‬‬ ‫‪𝐵´ → λ‬‬


‫‪C‬‬ ‫‪𝐶→X‬‬

‫‪89‬‬
X+X*X$
$A
$A´B $A´B´
$ A´B´C $ A´B´C*
$ A´B´x $ A´B´C
$ A´B´ $ A´B´x
$ A´ $ A´B´
$ A´B + $ A´
$ A´B $
$ A´B´C
$ A´B´x

"‫ عطایی‬, ‫ قادری‬, ‫ فدائی‬: ‫"تهیه شده توسط دانشجویان‬

90

You might also like