خب یه مرور کلی داشته باشیم:
ما اول اومدیم یه فایل lex نوشتیم که در کلی ترین حالت این فایل دو تا ستون داشت. ستون سمت چپ و ستون سمت راست. ستون سمت چپ یه «الگو» رو مشخص میکرد و ستون سمت راست یه «دستور» رو. هر جایی که اون الگو از توی ورودی تشخیص داده میشد، دستوری که جلوش نوشته شده هم اجرا میشد. مثلا دیدیم که اگر الگوی "stop" دیده میشد، دستور printf ای که جلوش بود اجرا میشد و پیغام Stop command received چاپ میشد. حالا توی این پست میخوایم کارهای پیشرفته تری انجام بدیم.
خب مثال پیشرفته تر بعدی، برنامه ای هست که یه فایل ورودی رو میگیره، تعداد کاراکترهای این فایل رو به همراه تعداد خطوط این فایل چاپ میکنه:
%{
#include <stdio.h>
int num_lines = 0, num_chars = 0;
%}
%%
\n ++num_lines; ++num_chars;
. ++num_chars;
%%
main()
{
yylex();
printf( "# of lines = %d, # of chars = %d\n",
num_lines, num_chars );
}
خب تفاوت این مثال رو با مثال قبل مرور میکنیم. توی این مثال ما توی قسمت اول فایل دو تا متغیر تعریف کردیم num_lines و num_chars که هر دو برابر صفر مقدار دهی شدند. توی قسمت دوم فایل ما دو تا الگو تعریف کردیم. الگوی اول (n\) کاراکتر خط جدید رو شناسایی میکنه. و ما از این کاراکتر برای شمارش تعداد خطوط استفاده میکنیم. به محض اینکه این کاراکتر توی فایل ورودی پیدا شد، متغیرهای num_chars و num_lines افزایش پیدا میکنند. توی خط بعد ما یه الگو (.) تعریف کردیم که همونطور که میدونید این الگو با تمام کاراکتر ها منطبق میشه و بنابراین به ازای هر کاراکتر متغیر num_chars یکی بیشتر میشه.
توی همه مثالهای قبلی ما از تابع main از قبل تعریف شده استفاده کردیم. اما این مثال ما یه تابع main مجزا نوشتیم و دیگه از تابع پیشفرض استفاده نکردیم. نکته اینکه توی این تابع main باید تابع yylex صدا زده بشه. این خیلی مهم هست که این تابع فراخوانی بشه.
توی دو خط بعدی هم ما به آسانی محتویات متغیرهای num_chars و num_lines رو چاپ کردیم.
امیدوارم همه این مثالها دید کلی نسبت به lex رو به شما داده باشه. البته lex به همینجا محدود نمیشه و گسترده تر از این حرفاست اما من هدفم فقط یه آشنایی مختصر خوانندگان عزیز هست و توی دنیای واقعی شما باید از flex به جای lex استفاده کنید.