لکس

لکس در علوم کامپیوتر برنامه‌ای است که تحلیلگرهای لغوی را (اسکنرها یا لکسرها) تولید می‌کند. Lex معمولا با یک)تولید کننده پارسر) استفاده می‌شود.
Lex در اصل، توسط Eric Schmidt و Mike Lesk طراحی و نوشته شد و این تحلیلگر لغوی، بطور استاندارد تحت سیستم‌های یونیکس است و یک ابزار برای نمایش رفتار (که برگرفته از استاندارد پازیکس است) دارد.
Lex یک رشته را از ورودی می‌خواند و تحلیلگر لغوی را مشخص می‌کند و خروجی، سورس کد یک Lexer به زبان برنامه نویسی سی است.
بهرحال، نسخه‌های اختصاصی سنتی Lex، همچون اوپن‌سولاریس و پلان ۹ برپایه کد AT-T بصورت متن باز و جزئی از این سیستم‌ها موجود می‌باشند. همچنین نسخه دیگری از Lex نیز به صورت متن باز و با نام تحلیل‌گر واژگانی فلکس رایج می‌باشد.
ساختار یک فایل Lex
ساختار یک فایل Lex عمدا شبیه به یک فایل Yacc است. فایلها به سه بخش تقسیم می‌شوند که هر بخش با %% از بخش دیگر جدا می‌شود:
بخش تعریف
بخش قواعد
بخش کد زبان C
قسمت تعریف (definition section)، جایی برای تعریف ماکروها و وارد کردن فایلهای سرآمدی (header) است که به زبان C نوشته شده‌اند. همچنین امکان اینکه هر کدی از زبان C را در اینجا بنویسید، وجود دارد، و این کد بصورت کلمه به کلمه، در کد اصلی تولید شده خواهد آمد.
قسمت قواعد (rules section)، مهم‌ترین بخش است که الگوها (عبارات منظم ساده) را با استفاده از دستورهای زبان C با هم مرتبط می‌سازد. زمانی که لکسر، متون را از ورودی می‌گیرد، الگوی معینی را برایشان مشخص می‌کند و کد (به زبان C) مرتبط با آن الگو را نیز اجرا می‌کند. و این چرخه اصلی فعالیت Lex می‌باشد.
قسمت کد زبان C (C code section)، شامل دستورهای و توابع کد زبان C است که کلمه به کلمه به فایل سورس تولید شده، اضافه می‌شود. احتمالا این دستورهای حاوی کدهایی هستند که در قسمت قواعد، توسط قواعد مختلف، فراخوانی می‌گردند. بهتر است که در برنامه‌های بزرگ، این بخش بطور جداگانه در یک فایل دیگر قرار بگیرد و در زمان کامپایل، به فایل اصلی اضافه شود.
مثالی از فایل Flex
در ادامه یک فایل Lex از ویرایش Flex می‌آید. که یک رشته‌ای از اعداد صحیح را از ورودی، تشخیص داده و در خروجی نمایشش می‌دهد:
/*** Definition section ***/
/* C code to be copied verbatim */
include
/* This tells flex to read only one input file */
%option noyywrap
/*** Rules section ***/
/* 0-9+ matches a string of one or more digits */
0-9+ {
/* yytext is a string containing the matched text. */
printf("Saw an integer: %s\n", yytext);
.|\n { /* Ignore all other characters. */
/*** C Code section ***/
int main(void)
/* Call the lexer, then quit. */
yylex();
return 0;
اگر رشته ورودی به Flex ارسال شود، آنرا به فایل C (lex.yy.c) تبدیل می‌کند. و به فایل قابل اجرا، کامپایل می‌شود که رشته‌ای از اعداد صحیح را تشخیص داده و در خروجی نمایش می‌دهد. به‌عنوان مثال اگر رشته زیر را به‌عنوان ورودی بدهیم:
abc123z.!-*2gj6
برنامه، خروجی زیر را خواهد داشت:
Saw an integer: 123
Saw an integer: 2
Saw an integer: 6
استفاده از Lex به همراه Yacc
عموما Lex و Yacc(تولید کننده Parser) درکنار یکدیگر مورد استفاده قرار می‌گیرند. چون Lex به ماشینهای قطعی (DFA) محدود می‌شود بنابراین آن رشته‌های ورودی، که Lex با استفاده از عبارات منظم قادر به تجزیه آنها نیست، Yacc با استفاده از یک گرامر رسمی، آنها را تجزیه می‌کند، با این حال، Yacc قادر به دریافت رشته از ورودی نمی‌باشد و به مجموعه‌ای از توکنها احتیاج دارد. غالبا Lex برای تامین توکنهای مورد نیاز Yacc مورد استفاده قرار می‌گیرد.
Lex و ساختن
مزیت ساختن، برای حفظ و نگهداری برنامه‌هایی است که شامل Lex هستند. سازنده هر فایلی را که دارای پسوند.l باشد را فایل سورس Lex در نظر می‌گیرد. و چنین فایلی را به‌عنوان فایلی که باید به فایل مقصد تبدیل شود، می‌شناسد.
بطور مثال اجازه دهید تا فایلی با نام ex.l و فایل قابل اجرای EXE را در خروجی داشته باشیم. روش معمول بصورت زیر است:
$>lex ex.l
شما فایلی با نام lex.yy.c را خواهید داشت.
$>gcc -o EXE lex.yy.c -ll (or -lfl)
با این روش ما فایل EXE را تهیه می‌کنیم.
EXE: ex.o
gcc -o EXE ex.o –ll
قبل از تعریفات سازنده، مورد نیاز می‌باشد. یعنی در هر زمان فقط سازنده اجرا می‌شود:
$> make
این کار در اینجا بسیار سریع انجام شد اما اگر شما به ۱۰ فایل برای کامپایل، نیاز داشته باشید، آنگاه این روش واقعا مفید خواهد بود.