یک الگوریتم یا برنامهی کامپیوتری از دو قسمت ضروری تشکیل میشود:
کارها توسط statement ها و دیتاها توسط declaration ها و definition ها توصیف میشوند.
برنامه به heading و body (بلاک) تقسیم میشود. heading به برنامه یک اسم میدهد و پارامترهای آن را لیست میکند.
These are (file) variables and represent the arguments and results of the computation.
body یا block از ۶ بخش تشکیل میشود که بجز بخش آخری بقیهی بخشها میتوانند خالی باشند و باید به ترتیب زیر بیایند:
Block = LabelDeclarationPart
ConstantDefinitionPart
TypeDefinitionPart
VariableDeclarationPart
ProcedureAndFunctionDeclarationPart
StatementPart.
طرح کلی یک برنامه را به صورت راحتتر میتوان با syntax diagram نشان داد. هر مستطیل نشان دهندهی دیاگرامی با نام داده شده است که معنی آن را تعریف میکند. symbol های پایانی، یعنی آنهایی که واقعا در برنامههای پاسکال نوشته میشوند، در چهاردیواریهای دور گرد نشان داده شدهاند. برای دیدن مجموعهی کامل این دیاگرامها به پیوست D (صفحهی ۲۳۰ و به بعد) مراجعه کنید.

هر کدی که در syntax diagram مربوط به Program بتواند از نقطهی شروع آغاز کند و با طی کردن مسیر به نقطهی پایانی دیاگرام برسد از نظر سینتکسی یک برنامهی درست است.
⬅ مثال: محاسبه تورم با نرخهای متعدد در طی ۱۰ سال
⬅ مثالی از وجود قسمت Label در برنامه
روش دیگر برای توصیف سینتکس Extended Backus-Naur Form یا EBNF است. در این روش ساختارهای سینتکسی با کلمات انگلیسی و ثوابت (literals) نشان داده میشوند. کلمات نشان دهندهی ماهیت یا معنی ساختار هستند در حالیکه ثابتها symbol هایی هستند که مستقیما در زبان (برنامه) نوشته میشوند. ثوابت در quotation mark نشان داده میشوند.
محصور شدن یک توالی از ساختارها و ثوابت در میان { و } تصریح به رخداد
صفر یا چند بار آن توالی میکند. alternative ها نیز توسط | نشان داده
میشوند. به این ۳ کاراکتر metasymbol میگویند. ( و ) برای
گروهبندی کردن به کار میروند و metasymbol های [ و ]
میگویند که ساختارها و ثوابت محصور شده بین آنها اجباری نیستند و
یا به عبارت دیگر optional هستند.
توضیحات کامل در مورد EBNF و EBNF پاسکال در پیوست D (صفحهی ۲۱۳ و به بعد) ارائه شده است.
به عنوان مثال ساختار Program که در شکل 0.a بالا syntax diagram آن را نشان دادهایم با فرمولهای EBNF زیر که productions نامیده میشوند نشان داده میشود:

هر اعلان function و precedure ساختاری شبیه به program دارد یعنی هر کدام از یک heading و یک block تشکیل شدهاند. با وجود این function ها و preocedure ها میتوانند به صورت تو در تو نوشته شوند.
⬅ مثال از تعریف یک procedure در داخل precedure دیگر
Label ها، constant ها، type ها، variable ها، procedure ها و function های تعریف شده نسبت به تابع یا پروسیجری که در داخل آن تعریف شدهاند محلی یا local هستند، یعنی این identifier ها فقط در متن برنامهای که block را تشکیل میدهد قابل دسترسی هستند. به محدودهی program text حوزه یا scope این identifier ها میگوییم و از آنجایی که میتوان بلاکهای تو در تو داشت لذا مفهوم حوزهها و یا scope ها را نیز خواهیم داشت. در مثال قبلی سعی کردهایم بلاکهای تو در تو را با کامنت نشان دهیم.
متوجه شدیم که بلاکها میتواند با اعلان تابعها و یا پروسیجرها به صورت تو در تو یا nested دربیایند به همین خاطر میتوانیم به هر یک از بلاکها بر حسب موقعیت قرارگیریاش نسبت به بلاک اصلی برنامه یک عدد نسبت دهیم. اگر به خارجیترین بلاک یا همان بلاک اصلی برنامه عدد ۰ را اختصاص دهیم در این صورت اگر بلاکی در این بلاک اصلی تعریف شود بلاکی از سطح ۱ خواهد بود و به همین ترتیب ادامه خواهد یافت. به طور کلی هر بلاکی که در سطح i تعریف شود متعلق به سطح i+1 خواهد بود.
📝 در مورد اعتبار یا قابل دسترس بودن یا scope یک identifier مانند X باید بگوییم که X در بلاکی که در آن تعریف شده است قابل دسترسی است. این موضوع شامل بلاکهایی نیز میشود که در داخل همان بلاک X تعریف شدهاند.
object هایی که در برنامهی اصلی تعریف میشوند، یعنی نسبت به هیچ تابع یا پروسیجری local نیستند، global یا سراسری نامیده میشوند و در سرتاسر برنامه دارای اهمیتند.
🤔 در مورد مطالب بالا باید در نظر داشت که identifier ها باید یکتا باشند و با identifier دیگری در یک بلاک داخلیتر همان بلاک، همنام نباشند. در این مورد بعدا صحبت میکنیم.
طرح یک برنامه به صورت زیر را در نظر بگیرید:

این ساختار میتواند بیانگر برنامهای به صورت زیر باشد:
PROGRAM M;
PROCEDURE P;
PROCEDURE A;
PROCEDURE B;
BEGIN
END; { B }
BEGIN
END; { A }
BEGIN
END; { P }
PROCEDURE Q;
PROCEDURE R;
BEGIN
END; { R }
PROCEDURE S;
BEGIN
END; { S }
BEGIN
END; { Q }
BEGIN
END. { M }
بر مبنای برنامهی بالا میتوانیم جدول زیر را رسم کنیم. هر سطر این جدول میگوید که هر بلاک به object های تعریف شده در کدام بلاکهای دیگر دسترسی دارد:
| block | may access objects in blocks |
|---|---|
| M | M |
| P | P, M |
| A | A, P, M |
| B | B, A, P, M |
| Q | Q, M |
| R | R, Q, M |
| S | S, Q, M |
🔔 توجه کنید که در توضیحات بالا مساله را از دو زاویه نگاه کردهایم:
شاید برای برنامهنویسانی که با Algol، PL/I، یا Fortran آشنایی دارند مقایسهی پاسکال با این زبانها مفید باشد. به همین خاطر بعضی ویژگیهای پاسکال را در زیر بیان میکنیم:
اعلان (declaration) متغیرها در پاسکال اجباریست.
بعضی کلمات کلیدی (مثل begin، end و repeat) رزرو شده هستند و نمیتوانند به عنوان identifier استفاده شوند. قاعدهی کلی این است که همهی کلمات کلیدی رزرو شده نیستند. هر چند اگر همهی آنها رزرو شده باشند.
; به عنوان جداکنندهی statement ها به کار میرود.
انواع دادهای استاندارد عبارتند از:
ساختمان دادههای پایهای شامل آرایه، رکورد
(معادل structure در زبانهای PL/I و Cobol)، set، و sequential file. این
ساختارها میتواند با هم ترکیب شوند و آرایهای از مجموعهها
و فایلهایی از رکوردها و چیزهایی مشابه اینها را ایجاد کنند.
دادهها میتوانند به صورت داینامیک allocate شوند و از طریق
اشارهگر به آنها دسترسی پیدا کرد.
This pointers allow the full generality of list processing. There is a facility
to declare new, basic data types with sumbolic constants
ساختماندادهی set امکاناتی شبیه bit string در PL/I فراهم میکند.
آرایهها میتوانند ابعاد (dimension) دلخواه داشته باشند و هر بعد میتواند حد (bound) مخصوص به خود را دارا باشد. حد آرایهها ثابت است یعنی چیزی به نام آرایهی داینامیک نداریم.
مانند هر سه زبان Algol، Fortran و PL/I در پاسکال هم goto statement وجود دارد. Label ها unisigned integer هستند و باید اعلان شده باشند.
statement های ترکیبی یا مرکب مانند زبان Algol و معادل گروه DO در PL/I است.
امکانی که در زبان Algol توسط switch و در Fortran توسط computed goto وجود دارد در پاسکال با case statement فراهم شده است.
for statement که معادل حلقهی DO در Fortran است step یا گام ۱ (to) و یا -1 (downto) دارد و فقط تا زمانی اجرا میشود که متغیر کنترل بین حدود قرار داشته باشد، به همین خاطر ممکن است بدنهی حلقه اصلا اجرا نشود.
در پاسکال conditional expression و multiple assignment وجود ندارد. [منظور از conditional expression چیزی است که در زبان C و بسیاری زبانهای دیگر به آن عملکر سه تایی یا ternary operator میگویند.]
max = (a > b) ? a : b; // in C but not in pascal
IF a > b THEN { | Pascal equivalent of
max = a { | conditional expression
ELSE { | (ternary operator) in
max = b; { | C
پروسیجرها و توابع میتوانند به صورت بازگشتی (recursive) فراخوانی شوند.
برخلاف Algol در پاسکال متغیرها ویژگی own ندارند. [own چیزی معادل static در زبان C است که باعث میشود متغیر در فراخوانیهای متعدد تابع مقدار قبلیش را حفظ کند.]
پارامترها یا با مقدار ارسال میشوند و یا با ارجاع (call by value or call by reference). چیزی به نام call by name وجود ندارد.
ساختار block با آن چیزی که در Algol و PL/I وجود دارد فرق میکند تا جایی که در پاسکال چیزی به نام بلکهای بینام یا anonymous block وجود ندارد یعنی به هر بلاک باید نامی اختصاصی داد و بنابراین آن را به یک تابع و یا پروسیجر تبدیل کرد.
❗ چیزی که مثلا بعد از دستور IF بین دو کلمهی BEGIN و END میآید در ادبیات زبان پاسکال compound statement نامیده میشود و بلاک نیست. بلاک در پاسکال میتواند شامل قسمتهای LABEL و TYPE و غیره باشد.
در پاسکال بلاک فرمی به صورت زیر دارد و همیشه بدنهی یک procedure، program و یا function را تشکیل میدهد.
Block =
declaration-part
compound-statement
تمام object ها، constant ها، variable ها و ...، همگی باید قبل از دسترسی به آنها تعریف شده باشند (کتاب میگوید declare که به نظر دقیق نیست) ولی دو استثنا اجازه دارند که از این قانون تخطی کنند:
conformant-array parameter امکانی شبیه به adjustable dimension array argument در زبان Fortran فراهم میکند. conformant-array parameter روشی در پاسکال استاندارد است که اجازه میدهد یک رویه، آرایههایی با طول مختلف را بپذیرد، بدون اینکه برای هر طول نوع جداگانهای تعریف شود:
procedure Print(
A: array[L..U: Integer] of Integer
);
💡
امروزه
کامپایلرها پشتیبانی دقیقی از این روش فراهم نمیکنند و بهتر است از
قابلیت open array برای کار با آرایههای با طول متفاوت استفاده کنید.
⬅ مثال از open array
بعضی برنامهنویسان در اولین برخورد با پاسکال از عدم وجود بعضی قابلیتهای محبوب، ابراز ناخشنودی میکنند. مثلا:
از این موارد غفلت نشده و نادیده گرفته نشدهاند، بلکه حذفهایی آگاهانهاند. در بعضی موارد وجود این قابلیتها باعث دعوت به «راهحلهای برنامهنویسی» ناکارآمد میشود و در موارد دیگر احساس شده است که وجود آنها مخالف هدفِ شفافیت و قابلیت اطمینان و «شیوهی برنامهنویسی خوب» است. به اضافه، برای این که کامپایلر پاسکال را نسبتا کوچک و کارآمد نگه داریم باید یک انتخاب تیزبینانه از میان حجم انبوهی از قابلیتهای برنامهنویسی موجود ـ هم برای کاربری که با استفاده از تعداد محدودی ساختار زبان، برنامههای کوچک مینویسد و هم کاربری که برنامههای بزرگ مینویسد و تمایل دارد تا از همهی امکانات زبان استفاده کندـ صورت میگرفت.