منظور از یک پشته، یک لیست ات که تنها میتوانیم عنصری را به انتهای آن اضافه کنیم (که به این عمل push میگویند)، و یا عنصری را از انتهای آن برداریم (به این عمل نیز Pop گفته میشود). به عبارت دیگر، پشته، ساختاری است که هرگاه بخواهیم از داخل آن عنصری را برداریم، آخرین عنصری که به آن وارد شده است، برداشته میشود.
یک ماشین PDA، به این صورت تعریف میشود: ماشین دارای یک پشته است و بر اساس یک برنامه، از ورودی رشتهای را دریافت میکند و عملیاتی را انجام میدهد. رشتهی ورودی ماشین، دنبالهای از یک مجموعهی متناهی است که به آن الفبا میگوییم. در این مسئله، فرض کنید که الفبایی که ماشین با آن کار میکند، مجموعهی A={0,1,+,∗,(,),$} است. البته فرض کنید که رشتهی ورودی هیچگاه شامل حرف $ نیست. برنامهای که ماشین بر اساس آن عمل میکند، از تعدادی «دستور» تشکیل شده است. هر دستوری دارای یک شماره است. (شمارهی دو دستور نمیتواند یکسان باشد.) اجرای برنامه از دستور شمارهی ۱ شروع میشود و هر دستور مشخص میکند که چه دستوری پس از خودش اجرا شود. اگر دستوری که قرار است اجرا شود در برنامه وجود نداشته باشد، اجرای برنامه متوقف میشود.
ماشین سه دستور زیر را میشناسد:
l:Push[x,n]
این دستور، x را روی پشته Push میکند ( x میتواند هر یک از اعضای A بهجز حرف $ باشد.) و پس از آن دستور شمارهی n را اجرا میکند.
l:Pop[x1,n1][x2,n2]…
این دستور، یک عنصر را از روی پشته Pop میکند. اگر این عنصر x1 بود، پس از این دستور، دستور شمارهی n1 اجرا میشود، اگر x2 بود، دستور شمارهی n2 اجرا میشود و … . در صورتی که عنصری که از روی پشته Pop شده است، مساوی با هیچ یک از xi ها نبود، اجرای برنامه خاتمه مییابد.
l:Read[x1,n1][x2,n2]…
این دستور، عنصر بعدی رشتهی ورودی را میخواند و بسته به این که مقدار این عنصر برابر با کدام یک از xi ها باشد، دستور با شمارهی ni متناظر را پس از این دستور اجرا میکند. اگر عنصر خوانده شده، مساوی با هیچ یک از xi ها نبود، اجرای برنامه خاتمه مییابد.
برای مشخص کردن انتهای رشتهی ورودی، قرارداد میکنیم که هر گاه به پایان رشتهی ورودی رسیدیم و دوباره دستور Read اجرا شد، حرف $ از ورودی خوانده میشود.
همچنین اگر پشته خالی باشد و دستور Pop اجرا شود (برا مثال اگر در ابتدای کار، قبل از این که چیزی را به پشته Push کرده باشیم، عمل Pop را انجام دهیم)، حرف $ از روی پشته خوانده میشود.
حرف $ فقط به این منظور در الفبا قرار داده شده است و همانطور که گفته شد، این حرف در رشتهی ورودی وجود ندارد و همچنین حق نداریم این حرف را به پشته Push کنیم.
به مثال زیر توجه کنید. در این مثال، برنامه یک رشته که تنها از حروف ( و ) تشکیل شده است را به عنوان ورودی میگیرد و چک میکند که آیا این پرانتزها درست قرار گرفتهاند یا خیر. در صورتی که پرانتزها درست قرار گرفته بودند، پس از پایان اجرای برنامه، تنها حرف ۱ و در غیر این صورت تنها حرف ۰ روی پشته وجود دارد.
1:Read[(,2][),3][$ ,4]
2:Push[(,1]
3:Pop[(,1][$ ,7]
4:Pop[(,5][$ ,6]
5:Pop[(,5][$ ,7]
6:Push[1,8]
7:Push[0,8]
الف) فرض کنید ورودی رشتهای از حروف 0، ۱، + و * است که یک عبارت محاسباتی ساده را مشخص میکند؛ یعنی رشته با یکی از حروف 0 یا ۱ شروع میشود، پس از آن با یکی از عملگرهای + یا *، سپس یکی از حروف 0 یا ۱ و به همین صورت یکدرمیان ادامه مییابد و آخرین حرف رشته نیز یکی از حرف 0 یا ۱ است. مقدار این رشته، مانند عبارتهای محاسباتی جبری حساب میشود، تنها با این تفاوت که مقدار 1+1 برابر با ۱ است. (یعنی در حقیقت عمل + مانند عمل «یا» ی منطقی است.) بنابراین مقدار چنین عبارتی 0 یا ۱ است. همچنین عملگر * نسبت به عملگر + اولویت دارد؛ یعنی برای مثال مقدار عبارت 1+0∗0 برابر با ۱ است.
برنامهای برای ماشین PDA بنویسید که یک رشتهی ورودی به صورت فوق را به طور کامل خوانده، به گونهای عمل کند که زمانی که متوقف میشود، تنها یک عدد 0 یا ۱ که برابر مقدار عبارت ورودی است، روی پشته باشد. برنامهی شما نباید شامل بیش از ۱۵ دستور باشد.
ب) در این قسمت فرض کنید که رشتهی ورودی ماشین، عبارتی محاسباتی است که میتواند شامل پرانتز هم باشد. اهمیت پرانتز در این است که ترتیب محاسبهی عملگرها را تغییر میدهد. برای مثال مقدار عبارت (1+0)∗0 برابر با 0 است؛ در حال که اگر پرانتزها وجود نداشتند، مقدار این عبارت برابر با ۱ بود. برنامهای بنویسید که چنین عبارتی را به عنوان رشتهی ورودی بگیرد و به گونهای عمل کند که زمانی که متوقف میشود، مقدار عبارت روی پشته قرار گرفته باشد. برنامهی شما نباید شامل بیش از ۲۵ دستور باشد.