تحلیل واژگانی
تحلیلگر واژگانی (لغوی)، یا اسکنر فاز اول کامپایل کردن یک برنامه است.
گرامر مورد استفاده در این بخش گرامر منظم (Regular) است.
در این مرحله برنامهٔ ورودی کاراکتر به کاراکتر خوانده شده و توکن بندی میشود. این توکنها (Token) در جدول نمادها (Symbol Table) به شکل خاصی ذخیره میشوند تا در مراحل بعدی مورد استفاده قرار گیرند.
این مرحله از کامپایل به نسبت تحلیلگر نحوی کندتر است، زیرا همواره با جریانی از کاراکترها سرورکار دارد.
در علم رایانه، تحلیل واژگانی پروسهای است که مجموعهای از کاراکترها را به مجموعهای از tokenها تبدیل میکند. برنامهای که تحلیل واژهای را انجام میدهد lexical analyzer یا lexers (تحلیلگر واژه) خوانده میشود. تحلیلگر واژه شامل scanner و tokenizer است.
کاربردها
یک تحلیلگر لغوی اولین فاز از قسمت front end یک کامپایلر را در پردازشهای مدرن تشکیل میدهد. آنالیزها معمولاً در یک مسیر به جلو میرود.
در سایر زبانها مانند ALGOL، گام نخست، دوبارهسازی خط (line reconstruction) است، که به صورت unstropping عمل میکرد و فضاهای خالی و کامنتها را حذف میکرد. (پارسر آن اسکنر نداشت و یک Lexer مجزا نیز نداشت). این گامها اکنون بهعنوان بخشی از lexer میباشند.
lexerها و پارسرها غالباً برای کامپایلرها استفاده میشوند، ولی میتوانند به عنوان ابزار برای سایر زبانهای کامپیوتر مورد استفاده قرار گیرند، مانند prettyprinters و linters.
عمل تحلیل لغوی میتواند به دو مرحله تقسیم شود: اسکن، که رشتهٔ ورودی را به گروههایی تقسیمبندی میکند و آنها را به کلاسهای توکن دستهبندی میکند؛ و ارزیابی، که کاراکترهای ورودی خام را به مقادیر پردازش شده تبدیل میکند.
واژه (lexeme)
کلمهٔ واژه در علوم کامپیوتر متفاوت از تعریف آن در زبانشناسی است. یک واژه در علوم کامپیوتر معمولاً مربوط است به چیزی که ممکن است در زبانشناسی یک کلمه نامیده شود. (معنای کلمهٔ word در علوم کامپیوتر از معنای آن در زبانشناسی متفاوت است)، و همچنین در برخی موارد ممکن است بسیار شبیه به تکواژ (کوچترین واحد معنادار لغوی) باشد.
واژه رشتهای از کاراکترهاست که یک واحد نحوی را شکل میدهد.
برخی از نویسندگان آن را توکن مینامند، از واژهٔ توکن استفاده میکنند تا
رشتهای که tokenize شده و ساختار دادهٔ توکنی که از قرار گرفتن آن رشته در فرایند توکنسازی حاصل شده را نمایش دهند.
توکن
یک توکن دستهای از متن هستند که به اسم lexemes شناخته میشوند. تحلیلگر واژهای lexemsها را پردازش میکند تا آنها را با توجه به کاربردشان دستهبندی کنند و به آنها معنا دهند. این انتساب معنا tokenization نامیده میشود. به این خط دستور در زبان C توجه کنید: ;sum=۳+۲ که به این صورت توکن بندی شدهاست:
lexeme | token type |
sum | IDENT |
= | ASSIGN_OP |
3 | NUMBER |
+ | ADD_OP |
2 | NUMBER |
; | SEMICOLON |
توکنها معمولاً توسط عبارات با قاعده تعریف میشوند، که توسط تحلیلگر واژهای به lex شناخته میشوند. تحلیلگر واژهای جریانی از lexemها را میخواند و آنها را به توکنهایی دستهبندی میکند. این کار tokenization خوانده میشود. در ادامه tokenizing، تجزیه قرار دارد. اطلاعات تفسیر شده ممکن است در ساختمانهای داده به منظور استفاده کلی، تفسیر یا کامپایل، قرار بگیرند.
گرامر واژهای
هر زبان برنامهنویسی شامل مجموعهای از قوانین خواهد بود، گرامر نحوی (واژهای) که syntax نحوی را تعیین کی کند. syntax نحوی معمولاً یک زبان منظم است، که به همراه قوانین گرامری شامل عبارات منظم مجموعهای از sequenceهای کاراکترهای ممکن که استفاده میشوند تا واژهها را شکل دهند را تعریف میکنند. یک تحلیل گر نحوی رشتهها را تشخیص میدهد و برای هر نوع رشتهای که برنامهٔ نحو پیدا کرده، کاری را انجام میدهد، سادهتر از همه یک توکن ایجاد میکند.
دو دسته از واژههای رایج و مهم فضای خالی(white space) و commentها هستند. آنها هم در گرامر تعریف شده و تحلیل نحوی نیز روی آنها نجام میشودف ولی ممکن است دورانداخته شوند (توکنی ایجاد نمیکنند) و از آنها صرف نظر میشود، مانند؛
if x
که توکنهای آن عبارت اند از: if و x
در اینجا دو مورد استثنا ی مهم وجود دارد. مورد اول: در زبانهای off-side rule که بلاکها را با تورفتگی محدود میکنند، white spaceهای اولیه مهم اند، چرا که ساختار بلاکها را تعیین میکنند و عموماً در سطح تحلیل گر لغوی کنترل میشوند.
مورد دوم: در برخی از کاربردهای تحلیل گر لغوی، commentها و فضاهای خالی باید حفظ شوند. به عنوان مثال، یک prettyprinter نیز نیاز دارد که به عنوان خروجی کامنتها و برخی ابزار debugging را که ممکن است پیامی را برای برنامهنویس داشته باشد (با نمایش سورس کد اصلی) نمایش دهد.
در سالها ی ۱۹۶۰ به ویژه برای زبان ALGOL، فضاهای خالی و commentها به عنوان بخشی از فاز نوسازی خط (فاز ابتدایی بخش frontend کامپایلر)، حذف میشدند، ولی این فاز جدا، حذف شد و اکنون توسط تحلیل گر لغوی (lexer) کنترل میشود.
توکنسازی (Tokenization)
توکنسازی، فرایند علامتگذاری و کلاس بندی بخشهایی از رشتهٔ کاراکترهای ورودی است. سپس توکنهای حاصله به فرمهای دیگر پردازش عبور میکنند. این فرایند میتواند به عنوان زیر وظیفهٔ ورودی parsing در نظر گرفته شود.
توکنسازی در رشتهٔ امنیت کامپیوتر معنای متفاوتی دارد.
به عنوان مثال، در یک رشتهٔ متنی:
The quick brown fox jumps over the lazy dog
این رشته بهطور ضمنی بر روی فضاها بخشبندی نشده، همان کاری که یک گویندهٔ طبیعی زبان انجام میدهد. ورودی خام که ۴۳ کاراکتر است باید بهطور ضمنی به وسیله جداکنندهٔ فاصله (فضای خالی یا " "
یا عبارت منظم /\s{1}/
) به ۹ تا توکن تقسیم شود.
توکنها میتوانند در XML نمایش داده شوند،
<sentence>
<word>The</word>
<word>quick</word>
<word>brown</word>
<word>fox</word>
<word>jumps</word>
<word>over</word>
<word>the</word>
<word>lazy</word>
<word>dog</word>
</sentence>
یا به صورت یک s-expression نمایش داده میشوند،
(sentence
(word The)
(word quick)
(word brown)
(word fox)
(word jumps)
(word over)
(word the)
(word lazy)
(word dog))
وقتی یک کلاس توکن بیش از یک واژهٔ ممکن را نمایش میدهد، تحلیل گر لغوی غالباً اطلاعات کافی را ذخیره میکند تا بتواند وتژهٔ اصلی را از نو تولید کند، بنابراین میتواند در تحلیل معنایی مورد استفاده قرار گیرد. پارسر معمولاً این اطلاعات را از Lexer فراخوانی میکند و آن را در درخت نحو انتزاع ذخیره یم کند. این کار برای جلوگیری از، از دست رفتن اطلاعات در مورد اعدا و شناسه(identifier)ها الزامی است.
توکنها براساس قوانین مشخصی از Lexer معرفی (شناسایی) میشوند. برخی از متدهایی که برای شناسایی توکنها به کاربرده میشوند، شامل: عبارات منظم، توالی مشخصی از کاراکترها که flag نامیده میشوند، کاراکترهای جداکنندهٔ خاصی که جداکننده (delimiters) نامیده میشوند، و تعریف صریح به وسیلهٔ یک دیکشنری. کاراکترهای خاص مانند کاراکترهای علامت گذاری، به خاطر استفادهٔ طبیعی آنها در نوشتن و زبانهای برنامهسازی، معمولاً توسط lexer برای شناسایی توکنها استفاده میشوند.
توکنها معمولاً به وسیلهٔ محتوای کاراکتر یا محتویات درون یه جریان داده دستهبندی میشوند. این دستهها به وسیلهٔ قوانین lexer تعریف میشوند. این دستهها معمولاً شامل عناصر گرامر زبان استفاده شده در جریان داده میشوند. زبانهای برنامهسازی غالباً توکنها را به عنوان identifierها، عملگرها، گروه نمادها، یا به وسیلهٔ نوع دادهٔ آنها، دستهبندی میکنند. زبانهای نوشتاری معمولاً توکنها را به عنوان اسم، فعل، صفت، یا علائم نشانهگذاری دستهبندی میکنند. دستهها برای پس پردازش (post-processing) توکنها چه توسط پارسر چه توسط توابع دیگر در برنامه، استفاده میشوند. تحلیلگر لغوی معمولاً کاری برای ترکیب توکنها انجتم نمیدهد، این وظیفهٔ پارسر است. به عنوان مثال، یک تحلیل گر لغوی معمولی، پرانتزها را به عنوان توکن تشخیص میدهد، ولی کاری را برای اطمینان از اینکه هر پرانتز باز با یک پرانتز بسته تطابق داده شود انجام نمیدهد.
زمانی که یک lexer توکنها را به parser میدهد، نمایشی که استفاده میشود، معمولاً لیستی از نمایش اعداد است. به عنوان مثال، "identifier" با عدد ۰ نمایش داده میشود، "عملگر انتساب" با عدد ۱ و "عملگر جمع" با عدد ۲ نمایش داده میشود و ….
توکنها معمولاً با عبارات منظم تعریف میشوند، که توسط مولد تحلیلگر لغوی مانند lex فهمیده میشوند. تحلیگر لغوی (که به صوزت خودکار توسط ابزاری مانند lex یا به صورت دستی تولید میشوند) جریان کاراکترها را میخواند، واژههای این جراین را شناسایی میکند، و آنها را به توکنهایی دستهبندی میکند. به این عمل توکنسازی میگویند. اگر lexer توکن نادرستی (invalid) بیابد، خطایی را گزارش میکند.
به دنبال عمل توکنسازی parsing میآید. از آنجا، دادهٔ تفسیر شده ممکن است، برای استفادهٔ عمومی، تفسیر، یا ترجمه (کامپایل) در ساختمان دادههایی بارگذاری شود.
اسکنر
در مرحله اول، اسکنر، معمولاً مبتنی بر یک ماشین حالت متناهی است که با استفاده از اطلاعات کاراکترهایی با توالی ممکن کدگذاری شدهاست که این کاراکترها میتوانند هر یک از توکنها مورد استفاده باشد. به عنوان مثال، یک توکن عدد صحیح میتواند دارای هر توالی از ارقام باشد. در بسیاری از نمونهها اولین کاراکتری که فضای خالی نباشد، میتواند برای استنباط نوع توکن بعدی مورد استفاده قرار گیرد و زیردنبالهٔ کارکترهای ورودی بعد از آن در یک زمان پردازش میشوند تاوقتی که به کاراکتری برسد که که در مجموعهٔ کاراکترهای قابل قبول برای توکنها نباشد (که اصطلاحاً این عمل، قانون حداکثر جویدن یا طولانیترین تطبیق نامیده میشود). در بسیاری از زبانها قانین تولید واژه بسیار پیچیدهتر است و ممکن است درگیر عقبگرد بر روی کاراکترهای خوانده شدهٔ قبلی شود. به عنوان مثال در C تنها یک کاراکتر 'L' برای تمایز قائل شدن بین یک شناسه که با 'L' شروع میشود و یک کاراکتر از یک رشته کافی نیست.
ارزیابیکننده
یک واژه، اگرچه یک رشتهای از کاراکترهاست، باید به شکل خاصی (مثلاً رشتهای از لیترالها، دنبالهای از حروف) باشند. به منظور ساختن یک توکن، تحلیل گر لغوی گام دومی هم نیاز دارد، ارزیابیکننده، که کارکترهای یک وازه را بررسی میکند تا یک مقداری را تولید کند. ترکیب نوع واژه با مقدارش چیزی است که یک توکن را میسازد، که میتوان آن را به پارسر (تجزیهکننده) داد. برخی از توکنها مانند پرانتزها درحقیقت مقداری ندارند، بنابراین تابع ارزیابیکننده برای آن میتواند چیزی برنگرداند: فقط نوع آن لازم است. بهطور مشابه، گاهی اوقات ارزیابیکننده کل یک واژه را نادیده میگیرد، آن را از پارسر حذف میکند، که برای فضاهای خالی و commentها مفید است. ارزیابیکننده برای شناسهها عموماً سادهاند (عینا خود شناسه را نمایش میدهند). ارزیابیکنندههای لیترالهای اعداد صحیح ممکن است رشته را عبور دهند (ارزیابی را برای فاز تحلیل معنایی به تعویق میاندازد)، یا ممکن است ارزیابی آنها را انجام دهندف که میتوانند درگیر مبناهای مختلف یا اعداد اعشاری شوند. برای لیترالهای رشتهٔ نقل قول شدهٔ ساده، لازم است که ارزیابیکننده فقط نقل قولها را حذف کند.
به عنوان مثال ف در این کد منبع یک برنامهٔ کامپیوتری، رشتهٔ
;(net_worth_future= (assets - liabilities
ممکن است به جریان توکنهای lexical زیر تبدیل شود؛ فضاهای خالی نادیده گرفته شدهاند و کاراکترهای خاص مقداری ندارند:
NAME net_worth_future
EQUALS
OPEN_PARENTHESIS
NAME assets
MINUS
NAME liabilities
CLOSE_PARENTHESIS
SEMICOLON
هر چند ممکن و گاهی اوقات لازم است که، به دلیل محدودیتهای صدور مجوز پارسرهای موجود یا اگر لیست توکنهای کوچک باشد، تحلیل گر لغوی به صورت دستی نوشته شود، تحلیل گران لغوی غالباً به صورت ابزار خودکار تولید میشوند. این ابزار بهطور کلی عبارات منظم را که نشانههای مجاز در جریان ورودی را توصیف میکنند، دریافت میکند. هر عبارت منظم با یک قانون تولید در گرامر تحلیل گر لغوی آن زبان برنامهنویسی همراه میشود، که واژههایی را تولید میکند که با آن عبارت منظم تطبیق داده شوند. این ابزار ممکن است کدهای منبعی تولید کنند که کامپایل و اجرا شوند یا یک جدول انتقال حالت برای یک ماشین حالت متناهی ایجاد کنند (که برای تدوین و اجرا به کد الگو متصل میشود).
عبارات منظم الگوهایی را که ممکن است کاراکترها در واژهها دنبال کنند به صورت فشرده نمایش میدهند. به عنوان مثال، برای یک زبان مبتنی بر زبان انگلیسی، یک توکن NAME ممکن است هر یک از کاراکترهای الفبای انگلیسی باشد یا یک underscore (_) و به دنبال آن هر تعدادی از نمونههای کدهای alphanumeric اسکی و underscoreهای دیگر باشد. میتوان به صورت مختصر این گونه نمایش داد؛ *[a-zA-Z_][a-zA-Z_0-9]
. به این معنی است که "هر تعداد از کاراکترهای a-z ،A-Z یا _، و به دنبال آن صفر یا تعداد بیشتری از a-z, A-Z, _ یا ۰–۹.
عبارات منظم و ماشینهای حالت متناهی ای که آنها تولید میکنند به اندازه کافی برای کنترل الگوهای بازگشتی، مانند "nتا پرانتز باز، به دنبال آن یک سری عبارت و پس از آن nتا پرانتز بسته "، قوی نیستند. آنها نمیتوانند تعداد را ذخیره کنند، و بررسی کنند که n در دوطرف یکسان است، مگر این که یک مجموعهٔ متناهی از مقادیر مجاز برای n موجود باشد. طول میکشد تا یک تجزیهکنندهٔ کامل چنین الگوهایی را در کلیت کامل خود تشخیص دهد. یک پارسر میتواند پرانتزها را به داخل پشته push کند و سپس سعی کند که آنها را pop کند تا ببیند که آیا در آخر پشته خالی میشود یا خیر.
موانع
معمولاً توکنسازی در سطح کلمه (word) انجام میگیرد. اگرچه، گاهی اوقات
تعیین معنای آن با یک کلمه دشوار است. اغلب توکن ساز بر اساس تخمینهای سادهای عمل میکند، به عنوان مثال:
- نشانهگذاری و فضای خالی ممکن است در لیست توکنهای حاصل به حساب آیند یا خیر.
- تمام رشتههای به هم پیوسته کاراکترهای الفبا، بخشی از توکن هستند؛ به همین ترتیب اعداد.
- توکنها با کاراکترهای فضای خالی جدا میشوند، مانند space یا line break، یا کاراکترهای نشانه گذاری.
در زبانهایی که از spaceهای بین کلمهای استفاده میکنند (مانند بسیاری از زبانها که از الفبای لاتین استفاده میکنند و بیشتر زبانهای برنلمه نویسی)، این روند به صورت منصفانهای سر راست است. اگرچه، حتی در اینجا نمونههای حاشیهای مانند انقباضات، کلمات hyphenated(با خط پیوند نوشته شده)، شکلکها، و سازههای بزرگتری مانند URLها (که برای بعضی اهداف ممکن است به عنوان تک توکن شمرده شوند). به عنوان یک مثال کلاسیک "New York-based" را درنظربگیرید، که یک توکن ساز ساده، ممکن است حتی در یک space شکسته شود اگرچه یک شکست بهتر مسلماً در خط پیوند نوشته شده(hyphen) است.
توکنسازی خصوصاً برای زبانهای نوشته شده در scriptio continua دشوار است، که محدودیتهای کلمه را نمایش نمیدهند، مانند یونانی باستان، چینی، یا تایلندی. زبانهای ترکیبی مانند کرهای نیز توکنسازی را دشوار میکنند.
برخی از راهها برای آدرس دهی به مسائل دشوارتر شامل توسعهٔ تخمینهای پیچیدهٔ بیشتر، پرس جوی یک جدول از موارد خاص متداول، یا مناسب کردن توکنها برای یک مدل زبان که ترتیب را در گامهای پردازش بعدی تشخیص میدهد.
نرمافزار
Apache OpenNLP شامل قوانین پایه و آماری توکنسازی است که زبانهای زیادی را پشتیبانی میکند.
U-Tokenizer یک API روی HTTP است که میتواند جملات ژاپنی و ماندرین را در محدودهٔ کلمه قطع کند.
HPE Haven OnDemand Text Tokenization API (یک محصول تبلیغاتی با دسترسی رایگان) از مدلسازی مفهوم احتمالات پیشرفته استفاده میکند تا وزنی که جمله در شاخص متن مشخص شده، دارد را تعیین کند.
ابزار Lex و کامپایلر آن طراحی شدهاند تا کد را برای تحلیل لغوی سریعتر بر مبنای یک توصیف رسمی از نحو لغوی تولید کنند؛ که این عموماً برای برنامههایی که مجموعهای پیچیده از قوانین نحوی و نیازمندیهای عملکردی شدید دارند، ناکافی در نظر گرفته میشود. به عنوان مثال، (GNU Compiler Collection (GCC از تحلیل گران لغوی دست نوشته استفاده میکند.
مولد تحلیل گر لغوی (Lexer Generator)
تحلیل گرهای لغوی اغلب توسط مولد تحلیل گر لغوی تولید میشوند، مشابه مولد تجزیهکننده (parser)، و چنین ابزارهایی اغلب گرد هم میآیند. پابرجاترین آنها Lex میباشد، به همراه مولد پارسر Yaccو ابزار معادل رایگان آن Flex.
این مولد شکلی از دامنهٔ خاص زبان است، مشخصات واژگانی رامی گیرد-بهطور کلی عبارت منظم با نشانه گذاری- و lexer را به عنوان خروجی تولید میکند.
ابزار عملکرد توسعهٔ سریع، که در توسعهٔ اولیه بسیار مهم اند، هر دو lexer میگیرند زیرا خصوصیات زبان اغلب ممکن است تغییر کند. در ادامه، آنها اغلب ویژگیهای پیشرفتهای را فراهم میکنند، از جمله شرایط قبل و بعد که برنامهنویسی دستی آنها سخت میباشد. با این حال مولد lexer اتوماتیک ممکن است عدم انعطافپذیری داشته باشد، در نتیجه نیاز به تغییر کاربر، یا یک lexer که کاملاً دستی نوشته شده باشد دارد.
عملکرد lexer دارای اهمیت است و بهینهسازی آن ارزشمند و نیازمند صرف وقت میباشد، به ویژه در زبانهای پایدار که lexer در آنها غالباً اجرا میشود (مانند C و Lexer.(HTMLهای تولید شده با lex/flex، منطقا سریع هستند، اما بیشتر از دو تا سه بار، بهبود آن، امکانپذیر است. گاهی lexerهای دستنویس استفاده میشدند، اما مولد lexer مدرن اغلب lexerهایی تولید میکنند که سریع تر از lexerهای با دست کدگذاری شده هستند. خانوادهٔ lex/flex جدول محورند که کارایی کمتری نسب به مولدهای مستقیماً کدگذاری شده دارند. با روش دوم مولد با دستور goto مستقیماً به جلو میرود. ابزاری مانندre2c موتورهایی که دو تا سه برابر سریع تر از موتورهای flex میباشد تولید میکند. بهطور کلی تجزیه و تحلیل دستنویس دشوار است که روش دوم برای تولید موتورها بهتر است.
لیستی از مولدهای lexer
- ANTLR: میتواند تحلیل گر لغوی و تجزیهکننده تولید کند.
- DFASTAR: تحلیل گر لغوی مبتنی بر جدول ماتریس DFA، در ++C تولید میکند.
- Flex: نوعی دیگر از lex کلاسیک برای C و++C
- Ragel: مولد ماشین حالت و lexer با خروجی در C و C++ ,C# ،Objective-C، D, Java , Go و Ruby
- Re2c: مولد تحلیلگر لغوی در C و++C
تحلیلگران لغوی زیل، میتوانند با Unicode هم کار کنند:
- JavaCC: تولید تحلیل گرهای لغوی نوشته شده در جاوا
- JFLex: مولد تحلیل گر لغوی برای جاوا
- RE/flex: نوعی سریع از lex/flex برای ++C که اسکنرها را با جداول یا کدزنی مستقیم تواید میکند.
- Quex: مولد تحلیل گر لغوی سریع جهانی برای C و ++C
- FsLex: مولد تحلیل گر لغوی برای ورودی بایت و کاراکتر یونیکد در#F
ساختار عبارت
تحلیل لغوی جریان ورودی از کاراکترها را به توکن تبدیل میکند، به سادگی کاراکترها را به بخشهایی گروهبندی میکند و آنها را طبقهبندی میکند. با این حال ممکن است که توکنها حذف میکنند یا اضافه میکنند. در حذف توکنها، از جمله فضای خالی وCommentها زمانی که کامپایلر هیچ احتیاجی به آنها ندارد، بسیار رایج هستند. معمولاً کمتر، توکنهای اضافه شده ممکن است قرار گرفته شوند. این کار انجام میشود تا توکنها را به عبارات، یا عبارات را به بلاکها گروهبندی کنند، تا عمل تجزیه را سادهتر کند.
ادامهٔ خط (Line continuation)
ادامهٔ خط یکی از ویژگیهای برخی زبان هاست که خط جدید معمولاً بعد از پایان جمله است. گاهی اوقات پایان خط با backslash (فورا به خط جدید میرود) نشان داده میشود که خط قبلی را به این خط متصل میکند. در تحلیل لغوی این کار انجام میشود: backslash و خط جدید دور انداخته میشوند، نسبت به خط جدید که توکنسازی میشود.
درج نقطه ویرگول (Semicolon insertion)
بسیاری از زبانها از نقطه ویرگول برای پایان جمله استفاده میکنند؛ که اغلب اجباری است، اما در بعضی زبانها استفاده از نقطه ویرگول در متن اختیاری است. این کار در مرحله lexerصورت میگیرد. جایی که lexer یک نقطه ویرگول را به جریانی از توکنها تبدیل میکند، با این وجود در جریان ورودی کاراکترها آماده نیست ف که درج نقطه ویرگول یا درج خودکار نقطه ویرگول نامیده میشود. در این مورد، نقطه ویرگول یک عبارت نرمال گرامی از زبان هست، اما ممکن است که به عنوان ورودی نباشد که تحلیل گر لغوی آن را اضافه میکند. نقطه ویرگول اختیاری است یا پایان دهنده یا این که بعضی اوقات به عنوان جداکننده از مرحلهٔ تجزیه به کار میرود، به ویژه در مورد کامای انتهایی(trailing commas) یا نقطه ویرگول.
درج نقطه ویرگول یکی از خصوصیات BCPL و یکی از نسلهای دور در Go میباشد. هر چند در B یا C وجود ندارد. درج نقطه ویرگول در JavaScript وجود دارد، اگر قوانین پیچیده و مورد انتقاد قرار بگیرند، برای جلوگیری از مشکلات، استفاده از نقطه ویرگول توصیه میشود، در حالی که دیگران نقطه ویرگول اولیه، نقطه ویرگول دفاعی، را عمدتاً در عبارات مبهم به کار میبرند.
درج نقطه ویرگول (در زبانهایی که نقطه ویرگول به معنای پایان عبارت است) و ادامهٔ خط (در زبانهایی که خط جدید به معنای پایان عبارت است) مکمل یکدیگرند. درج نقطه ویرگول به عنوان یک توکن اضافه میشود، اگرچه خط جدید بهطور کلی توکن ایجاد نکند، یا ادامهٔ خط مانع از ایجاد توکن شود و حتی اگر خط جدید بهطور کلی توکن ایجاد کند.
قوانین off-side
قوانین off-side (بلوکهای تعیین شده توسط تورفتگی) را در lexer میتوان پیادهسازی کرد، مانند پایتون، که افزایش فرورفتگیها نتیجهٔ بیرون ریختن INDENT توکنها در lexer است، و کاهش فرورفتگیها نتیجهٔ بیرون ریختن DEDENT توکنها در lexer میباشد. این توکنها مربوط به باز کردن آکولاد {
و بستن آکولاد }
در زبانهایی است که از آکولاد برای بلاکها استفاده میکنند. این بدان معناست که عبارت دستور زبان به این که آکولاد یا فرورفتگی استفاده میشود بستگی ندارد. مستلزم آن است که حالت lexer را نگه دارد، یعنی سطح تورفتگی فعلی، در نتیجه میتواند زمانی که تغییرات فرورفتگی شناسایی شود تغییر دهد، در نتیجه دستورزبان واژگانی مستقل از متن نیست :INDENT-DEDENT، به اطلاعات متن که از فررفتگی قبلی میگیرد بستگی دارد.
تحلیل لغوی حساس به متن
بهطورکلی گرامرهای لغوی، مستقل از متن هستند، یا تقریباً مستقل از متن هستند، که نیازی به نگاه به عقب یا جلو، یا برگشت به عقب(backtracking) هستند، که پیادهسازی ساده، تمیز و کارآمد را امکانپذیر میکند. هم چنین یک ارتباط یک طرفه از تحلیل گر لغوی به تجزیهکننده، بدون نیاز به برگشت اطلاعات را ممکن میسازد.
با این حال استثناهایی وجود دارد. مثالهایی ساده شامل: درج نقطه ویرگول در Go، که به نگاه کردن به توکن قبلی نیاز دارد، الحاق رشتهٔ متوالی در پایتون که نیازدارد قبل از خروج یک توکن محتوای آن در بافرنگه داری شود (برای اینکه ببیند آیا توکن بعدی یکی literal است یا نه)؛ ونقش off-side در پایتون، که به نگهداری تعدادی از سطوح فرورفتگی نیاز دارد (در واقع پشتهای از هر سطوح فرورفتگی)، این نمونهها فقط نیاز به زمینهٔ لغوی دارند، و در حالی که تحلیل گر لغوی تا حدی آنها را پیچیده میکند، برای تجزیهکننده و مراحل بعد قابل دیدن نیستند.
یک مثال پیچیدهتر هک تحلیل گر لغوی در C است، که کلاس توکن دنبالهای از کاراکترها تا فاز تحلیل گر معنایی، نمیتواند تعیین شود. اگرچه نامهای نوع متغیر از لحاظ لغوی یکسان اند اما کلاسهای توکن مختلفی را تشکیل میدهد؛ بنابراین در این هک، تحلیل گر لغوی تجزیه و تحلیل معنایی را صدا میزند (جدول نمادها) و بررسی میکند که آیا دنباله به یک نام نوع متغیر نیاز دارد یا خیر. در این مورد نباید اطلاعات فقط از تجزیهکننده بازگردد بلکه باید از تحلیلگر معنایی به تحلیل گر لغوی برگردد، که طراحی را پیچیده میکند.
یادداشتها
منابع
لینک های خارجی
- Yang, W.; Tsay, Chey-Woei; Chan, Jien-Tsai (2002). "On the applicability of the longest-match rule in lexical analysis". Computer Languages, Systems and Structures. Elsevier Science. 28 (3): 273–288. doi:10.1016/S0096-0551(02)00014-0. NSC 86-2213-E-009-021 and NSC 86-2213-E-009-079.
- Trim, Craig (Jan 23, 2013). "The Art of Tokenization". Developer Works. IBM.
- Word Mention Segmentation Task, an analysis