یک (کامپایلر)
یَک، (به انگلیسی: Yacc) یکی از برنامههای کامپیوتری است که در سیستم عامل یونیکس به کار میرود. کلمهٔ یَک، از عبارت Yet AnotherCompiler Compiler گرفته شدهاست. این برنامه، توسط S.C.Johnson در آزمایشگاه Bell توسعه پیدا کرد.
یَک، در واقع بخشی از مراحل کامپایلر است که کد منبع را گرفته و آن را از دید قواعد صرف و نحو مورد بررسی قرار میدهد. میتوان اینطور بیان کرد که گرامر زبان منظم را به آن میدهیم و برنامهٔ آن را به زبان برنامه نویسی C میسازد که در آن ورودیها با توجه به نقششان در گرامر، تجزیه(parse) میشوند.
بایسون
یکی دیگر از برنامههایی که مشابه یَک عمل میکند، بایسون (به انگلیسی :Bison) است که سند (به انگلیسی:License) آن، رایگان و استفاده از آن برای عموم آزاد است.
استفاده از هر دو برنامهٔ لکس و یَک
عموماً Lex (فاز اول کامپایل کردن یک برنامه) و یَک در کنار یکدیگر مورد استفاده قرار میگیرند. چون لکس به ماشین تعیینپذیر حالات متناهی (به انگلیسی:DFA) محدود میشود، بنابراین آن رشتههای ورودی، که لکس با استفاده از عبارات منظم قادر به تجزیهٔ آنها نیست، یَک با استفاده از یک دستور زبان منظم، آنها را تجزیه میکند، با این حال، یَک قادر به دریافت رشته از ورودی نمیباشد و به مجموعهای از توکنها احتیاج دارد. غالباً لکس برای تأمین توکنهای مورد نیاز یَک، مورد استفاده قرار میگیرد.
ساختار یَک
برنامهٔ یَک شامل یک فایل ورودی به فورم زیر است:
خصوصیات تجزیه کننده
%%
نقشهای گرامر
%%
زیرروال برنامهٔ سی
- قسمت اول: شامل لیستی از توکن هاست که توسط تجزیهکننده و معیارهای نشانههای شروع گرامر پیشبینی شدهاست. شرکت پذیری عملگرها و اولویت آنها هم در این قسمت یَک گنجانده شدهاند. این خصیصه انعطافپذیری بیشتری به انتخاب گرامرهای منظم میدهد.
توجه:عملگرهای افزایشی و کاهشی (جمع و تفریق، ضرب و تقسیم)، شرکت پذیری چپ دارند و اولویت کمتری نسبت به توان دارند.
توجه:توان، شرکت پذیری راست و اولیت بیشتری دارد.
به عنوان مثال:
% start program
% token LET INTEGER IN
% token SKIP IF THEN ELSE END WHILE DO READ WRITE
% token NUMBER
% token IDENTIFIER
% left ’-’ ’+’
% left ’*’ ’/’
% right ’ˆ ’
%%
قسمت دوم
%%
قسمت سوم
- قسمت دوم :شامل دستور زبانهای منظم برای زبانهای مختلف است. هر قسمت، توسط سمی کالن از سایر قسمتها جدا میشود. نشانهٔ =.. (فرم بکوس-نائور- به انگلیسی:BNF) با : جایگزین میشود.
توجه : قسمتهای خالی، را خالی در نظر میگیریم.
توجه :متوجه میشویم ساده کردن گرامر منظم نیازمند جدا کردن اولویتها از گرامرها است.
برای مثال:
قسمت اول
%%
program : LET declarations IN commands END ;
declarations : /* empty */ | INTEGER id seq IDENTIFIER ’. ’ ;
id seq : /* empty */ | id seq IDENTIFIER ’,’ ;
commands : /*empty */ | commands command ’;’ ;
command : SKIP | READ IDENTIFIER | WRITE exp
|IDENTIFIER ASSGNOP exp
|IF exp THEN commands ELSE commands FI
| WHILE exp DO commands END ;
%%
قسمت سوم
- قسمت سوم: شامل کد زبان سی آن است.
باید تابع یکنواخت ()main وجود داشته باشد که تابع ()yyparse را صدا زند.
تابع ()yyerror برای گزارش خطاهای ایجاد شده به کار میرود.
نمونهٔ سادهای از استفادهٔ توابع ()main و ()yyerror را میبینیم:
قسمت اول
%%
قسمت دوم
%%
main(int argc, char *argv[])
{
extern FILE *yyin;
++argv; −−argc;
yyin = fopen(argv[۰], ”r”);
yydebug = 1;
errors = 0;
yyparse();
}
yyerror (char *s)
{
printf (”%s\n”, s);
}
کد برای اجرای یَک یا بایسون
بسته به اینکه از بایسون استفاده میکنید یا یَک، از کد پایین برای کامپایل برنامه استفاده میشود:
در یَک:
yacc -vd file.y
در بایسون:
bison -vd file.y
وقتی این کد را تایپ میکنید، در واقع دو فایل با پسوندهای file.tab.h و file.tab.c از فایلی که قبلاً نوشته بودید، ساخته میشود.
file.tab.h: شامل لیستی از توکنهایی است که اسکنر آنها را از فایل خوانده است.
file.tab.c: تابع ()yyparse را در برنامهٔ سی میخواند.