موضوع مقاله: تحلیل واژگانی | مخاطب: عمومی | لحن: دانشنامه‌ای | ساختار: عنوان، مقدمه، 3 بخش، جمع‌بندی | مقاله: | # تحلیل واژگانی | مقدمه: این مرحله از کامپایل به نسبت تحلیل‌گر نحوی کندتر است، زیرا همواره با جریانی از کاراکترها سروکار دارد. | ## بخش 1: تحلیل واژگانی | در علم رایانه، تحلیل واژگانی پروسه‌ای است که مجموعه‌ای از کاراکترها را به مجموعه‌ای از tokenها تبدیل می‌کند. کاربردها یک تحلیل‌گر لغوی اولین فاز از قسمت front end یک کامپایلر را در پردازش‌های مدرن تشکیل می‌دهد. عمل تحلیل لغوی می‌تواند به دو مرحله تقسیم شود: اسکن، که رشتهٔ ورودی را به گروه‌هایی تقسیم‌بندی می‌کند و آن‌ها را به کلاس‌های توکن دسته‌بندی می‌کند؛ و ارزیابی، که کاراکترهای ورودی خام را به مقادیر پردازش شده تبدیل می‌کند. یک واژه در علوم کامپیوتر معمولاً مربوط است به چیزی که ممکن است در زبان‌شناسی یک کلمه نامیده شود. (معنای کلمهٔ word در علوم کامپیوتر از معنای آن در زبان‌شناسی متفاوت است)، و همچنین در برخی موارد ممکن است بسیار شبیه به تکواژ (کوچترین واحد معنادار لغوی) باشد. برخی از نویسندگان آن را توکن می‌نامند، از واژهٔ توکن استفاده می‌کنند تا رشته‌ای که tokenize شده و ساختار دادهٔ توکنی که از قرار گرفتن آن رشته در فرایند توکن‌سازی حاصل شده را نمایش دهند. تحلیلگر واژه‌ای lexemsها را پردازش می‌کند تا آن‌ها را با توجه به کاربردشان دسته‌بندی کنند و به آن‌ها معنا دهند. تحلیلگر واژه‌ای جریانی از lexemها را می‌خواند و آن‌ها را به توکنهایی دسته‌بندی می‌کند. اطلاعات تفسیر شده ممکن است در ساختمان‌های داده به منظور استفاده کلی، تفسیر یا کامپایل، قرار بگیرند. گرامر واژه‌ای هر زبان برنامه‌نویسی شامل مجموعه‌ای از قوانین خواهد بود، گرامر نحوی (واژه‌ای) که syntax نحوی را تعیین کی کند. syntax نحوی معمولاً یک زبان منظم است، که به همراه قوانین گرامری شامل عبارات منظم مجموعه‌ای از sequenceهای کاراکترهای ممکن که استفاده می‌شوند تا واژه‌ها را شکل دهند را تعریف می‌کنند. یک تحلیل گر نحوی رشته‌ها را تشخیص می‌دهد و برای هر نوع رشته‌ای که برنامهٔ نحو پیدا کرده، کاری را انجام می‌دهد، ساده‌تر از همه یک توکن ایجاد می‌کند. آن‌ها هم در گرامر تعریف شده و تحلیل نحوی نیز روی آن‌ها نجام می‌شود، ولی ممکن است دور انداخته شوند (توکنی ایجاد نمی‌کنند) و از آن‌ها صرف نظر می‌شود، مانند؛if xکه توکن‌های آن عبارت اند از: if و x در این‌جا دو مورد استثنا ی مهم وجود دارد. ورودی خام که ۴۳ کاراکتر است باید به‌طور ضمنی به وسیله جداکنندهٔ فاصله (فضای خالی یا " " یا عبارت منظم /\s{1}/) به ۹ تا توکن تقسیم شود. پارسر معمولاً این اطلاعات را از Lexer فراخوانی می‌کند و آن را در درخت نحو انتزاع ذخیره یم کند. برخی از متدهایی که برای شناسایی توکن‌ها به کاربرده می‌شوند، شامل: عبارات منظم، توالی مشخصی از کاراکترها که flag نامیده می‌شوند، کاراکترهای جداکنندهٔ خاصی که جداکننده (delimiters) نامیده می‌شوند، و تعریف صریح به وسیلهٔ یک دیکشنری. کاراکترهای خاص مانند کاراکترهای علامت گذاری، به خاطر استفادهٔ طبیعی آن‌ها در نوشتن و زبان‌های برنامه‌سازی، معمولاً توسط lexer برای شناسایی توکن‌ها استفاده می‌شوند. توکن‌ها معمولاً به وسیلهٔ محتوای کاراکتر یا محتویات درون یه جریان داده دسته‌بندی می‌شوند. زبان‌های برنامه‌سازی غالباً توکن‌ها را به عنوان identifierها، عملگرها، گروه نمادها، یا به وسیلهٔ نوع دادهٔ آن‌ها، دسته‌بندی می‌کنند. زبان‌های نوشتاری معمولاً توکن‌ها را به عنوان اسم، فعل، صفت، یا علائم نشانه‌گذاری دسته‌بندی می‌کنند. تحلیلگر لغوی معمولاً کاری برای ترکیب توکن‌ها انجام نمی‌دهد، این وظیفهٔ پارسر است. به عنوان مثال، یک تحلیل گر لغوی معمولی، پرانتزها را به عنوان توکن تشخیص می‌دهد، ولی کاری را برای اطمینان از اینکه هر پرانتز باز با یک پرانتز بسته تطابق داده شود انجام نمی‌دهد. به عنوان مثال، "identifier" با عدد ۰ نمایش داده می‌شود، "عملگر انتساب" با عدد ۱ و "عملگر جمع" با عدد ۲ نمایش داده می‌شود و …. توکن‌ها معمولاً با عبارات منظم تعریف می‌شوند، که توسط مولد تحلیلگر لغوی مانند lex فهمیده می‌شوند. تحلیلگر لغوی (که به صورت خودکار توسط ابزاری مانند lex یا به صورت دستی تولید می‌شوند) جریان کاراکترها را می‌خواند، واژه‌های این جریان را شناسایی می‌کند، و آن‌ها را به توکن‌هایی دسته‌بندی می‌کند. | ## بخش 2: تحلیل واژگانی | از آنجا، دادهٔ تفسیر شده ممکن است، برای استفادهٔ عمومی، تفسیر، یا ترجمه (کامپایل) در ساختمان داده‌هایی بارگذاری شود. اسکنر در مرحله اول، اسکنر، معمولاً مبتنی بر یک ماشین حالت متناهی است که با استفاده از اطلاعات کاراکترهایی با توالی ممکن کدگذاری شده‌است که این کاراکترها می‌توانند هر یک از توکن‌ها مورد استفاده باشد. در بسیاری از نمونه‌ها اولین کاراکتری که فضای خالی نباشد، می‌تواند برای استنباط نوع توکن بعدی مورد استفاده قرار گیرد و زیردنبالهٔ کارکترهای ورودی بعد از آن در یک زمان پردازش می‌شوند تا وقتی که به کاراکتری برسد که که در مجموعهٔ کاراکترهای قابل قبول برای توکن‌ها نباشد (که اصطلاحاً این عمل، قانون حداکثر جویدن یا طولانی‌ترین تطبیق نامیده می‌شود). در بسیاری از زبان‌ها قوانین تولید واژه بسیار پیچیده‌تر است و ممکن است درگیر عقب‌گرد بر روی کاراکترهای خوانده شدهٔ قبلی شود. به عنوان مثال در C تنها یک کاراکتر 'L' برای تمایز قائل شدن بین یک شناسه که با 'L' شروع می‌شود و یک کاراکتر از یک رشته کافی نیست. ارزیابی‌کننده یک واژه، اگرچه یک رشته‌ای از کاراکترهاست، باید به شکل خاصی (مثلاً رشته‌ای از لیترال‌ها، دنباله‌ای از حروف) باشند. به منظور ساختن یک توکن، تحلیل گر لغوی گام دومی هم نیاز دارد، ارزیابی‌کننده، که کارکترهای یک واژه را بررسی می‌کند تا یک مقداری را تولید کند. ترکیب نوع واژه با مقدارش چیزی است که یک توکن را می‌سازد، که می‌توان آن را به پارسر (تجزیه‌کننده) داد. برخی از توکن‌ها مانند پرانتزها درحقیقت مقداری ندارند، بنابراین تابع ارزیابی‌کننده برای آن می‌تواند چیزی برنگرداند: فقط نوع آن لازم است. به‌طور مشابه، گاهی ارزیابی‌کننده کل یک واژه را نادیده می‌گیرد، آن را از پارسر حذف می‌کند، که برای فضاهای خالی و commentها مفید است. ارزیابی‌کننده‌های لیترال‌های اعداد صحیح ممکن است رشته را عبور دهند (ارزیابی را برای فاز تحلیل معنایی به تعویق می‌اندازد)، یا ممکن است ارزیابی آن‌ها را انجام دهند، که می‌توانند درگیر مبناهای مختلف یا اعداد اعشاری شوند. برای لیترال‌های رشتهٔ نقل قول شدهٔ ساده، لازم است که ارزیابی‌کننده فقط نقل قول‌ها را حذف کند. این ابزار به‌طور کلی عبارات منظم را که نشانه‌های مجاز در جریان ورودی را توصیف می‌کنند، دریافت می‌کند. هر عبارت منظم با یک قانون تولید در گرامر تحلیل گر لغوی آن زبان برنامه‌نویسی همراه می‌شود، که واژه‌هایی را تولید می‌کند که با آن عبارت منظم تطبیق داده شوند. این ابزار ممکن است کدهای منبعی تولید کنند که کامپایل و اجرا شوند یا یک جدول انتقال حالت برای یک ماشین حالت متناهی ایجاد کنند (که برای تدوین و اجرا به کد الگو متصل می‌شود). عبارات منظم الگوهایی را که ممکن است کاراکترها در واژه‌ها دنبال کنند به صورت فشرده نمایش می‌دهند. به این معنی است که "هر تعداد از کاراکترهای a-z ،A-Z یا _، و به دنبال آن صفر یا تعداد بیشتری از a-z, A-Z, _ یا ۰–۹. عبارات منظم و ماشین‌های حالت متناهی ای که آن‌ها تولید می‌کنند به اندازه کافی برای کنترل الگوهای بازگشتی، مانند "nتا پرانتز باز، به دنبال آن یک سری عبارت و پس از آن nتا پرانتز بسته "، قوی نیستند. آن‌ها نمی‌توانند تعداد را ذخیره کنند، و بررسی کنند که n در دوطرف یکسان است، مگر این که یک مجموعهٔ متناهی از مقادیر مجاز برای n موجود باشد. یک پارسر می‌تواند پرانتزها را به داخل پشته push کند و سپس سعی کند که آن‌ها را pop کند تا ببیند که آیا در آخر پشته خالی می‌شود یا خیر. اغلب توکن ساز بر اساس تخمین‌های ساده‌ای عمل می‌کند، به عنوان مثال: نشانه‌گذاری و فضای خالی ممکن است در لیست توکن‌های حاصل به حساب آیند یا خیر. تمام رشته‌های به هم پیوسته کاراکترهای الفبا، بخشی از توکن هستند؛ به همین ترتیب اعداد. در زبان‌هایی که از spaceهای بین کلمه‌ای استفاده می‌کنند (مانند بسیاری از زبان‌ها که از الفبای لاتین استفاده می‌کنند و بیشتر زبان‌های برنامه نویسی)، این روند به صورت منصفانه‌ای سر راست است. اگرچه، حتی در اینجا نمونه‌های حاشیه‌ای مانند انقباضات، کلمات hyphenated(با خط پیوند نوشته شده)، شکلک‌ها، و سازه‌های بزرگتری مانند URLها (که برای بعضی اهداف ممکن است به عنوان تک توکن شمرده شوند). برخی از راه‌ها برای آدرس دهی به مسائل دشوارتر شامل توسعهٔ تخمین‌های پیچیدهٔ بیشتر، پرس جوی یک جدول از موارد خاص متداول، یا مناسب کردن توکن‌ها برای یک مدل زبان که ترتیب را در گام‌های پردازش بعدی تشخیص می‌دهد. | ## بخش 3: تحلیل واژگانی | ابزار Lex و کامپایلر آن طراحی شده‌اند تا کد را برای تحلیل لغوی سریعتر بر مبنای یک توصیف رسمی از نحو لغوی تولید کنند؛ که این عموماً برای برنامه‌هایی که مجموعه‌ای پیچیده از قوانین نحوی و نیازمندی‌های عملکردی شدید دارند، ناکافی در نظر گرفته می‌شود. این مولد شکلی از دامنهٔ خاص زبان است، مشخصات واژگانی رامی گیرد-به‌طور کلی عبارت منظم با نشانه گذاری- و lexer را به عنوان خروجی تولید می‌کند. ابزار عملکرد توسعهٔ سریع، که در توسعهٔ اولیه بسیار مهم اند، هر دو lexer می‌گیرند زیرا خصوصیات زبان اغلب ممکن است تغییر کند. در ادامه، آن‌ها اغلب ویژگی‌های پیشرفته‌ای را فراهم می‌کنند، از جمله شرایط قبل و بعد که برنامه‌نویسی دستی آن‌ها سخت می‌باشد. با این حال مولد lexer اتوماتیک ممکن است عدم انعطاف‌پذیری داشته باشد، در نتیجه نیاز به تغییر کاربر، یا یک lexer که کاملاً دستی نوشته شده باشد دارد. خانوادهٔ lex/flex جدول محورند که کارایی کمتری نسب به مولدهای مستقیماً کدگذاری شده دارند. ابزاری مانندre2c موتورهایی که دو تا سه برابر سریع تر از موتورهای flex می‌باشد تولید می‌کند. به‌طور کلی تجزیه و تحلیل دست‌نویس دشوار است که روش دوم برای تولید موتورها بهتر است. Quex: مولد تحلیل گر لغوی سریع جهانی برای C و ++C FsLex: مولد تحلیل گر لغوی برای ورودی بایت و کاراکتر یونیکد در#F ساختار عبارت تحلیل لغوی جریان ورودی از کاراکترها را به توکن تبدیل می‌کند، به سادگی کاراکترها را به بخش‌هایی گروه‌بندی می‌کند و آن‌ها را طبقه‌بندی می‌کند. در حذف توکن‌ها، از جمله فضای خالی وCommentها زمانی که کامپایلر هیچ احتیاجی به آن‌ها ندارد، بسیار رایج هستند. این کار انجام می‌شود تا توکن‌ها را به عبارات، یا عبارات را به بلاک‌ها گروه‌بندی کنند، تا عمل تجزیه را ساده‌تر کند. در تحلیل لغوی این کار انجام می‌شود: backslash و خط جدید دور انداخته می‌شوند، نسبت به خط جدید که توکن‌سازی می‌شود. جایی که lexer یک نقطه ویرگول را به جریانی از توکن‌ها تبدیل می‌کند، با این وجود در جریان ورودی کاراکترها آماده نیست ف که درج نقطه ویرگول یا درج خودکار نقطه ویرگول نامیده می‌شود. در این مورد، نقطه ویرگول یک عبارت نرمال گرامی از زبان هست، اما ممکن است که به عنوان ورودی نباشد که تحلیل گر لغوی آن را اضافه می‌کند. درج نقطه ویرگول در JavaScript وجود دارد، اگر قوانین پیچیده و مورد انتقاد قرار بگیرند، برای جلوگیری از مشکلات، استفاده از نقطه ویرگول توصیه می‌شود، در حالی که دیگران نقطه ویرگول اولیه، نقطه ویرگول دفاعی، را عمدتاً در عبارات مبهم به کار می‌برند. درج نقطه ویرگول (در زبان‌هایی که نقطه ویرگول به معنای پایان عبارت است) و ادامهٔ خط (در زبان‌هایی که خط جدید به معنای پایان عبارت است) مکمل یکدیگرند. درج نقطه ویرگول به عنوان یک توکن اضافه می‌شود، اگرچه خط جدید به‌طور کلی توکن ایجاد نکند، یا ادامهٔ خط مانع از ایجاد توکن شود و حتی اگر خط جدید به‌طور کلی توکن ایجاد کند. این توکن‌ها مربوط به باز کردن آکولاد { و بستن آکولاد } در زبان‌هایی است که از آکولاد برای بلاک‌ها استفاده می‌کنند. این بدان معناست که عبارت دستور زبان به این که آکولاد یا فرورفتگی استفاده می‌شود بستگی ندارد. مستلزم آن است که حالت lexer را نگه دارد، یعنی سطح تورفتگی فعلی، در نتیجه می‌تواند زمانی که تغییرات فرورفتگی شناسایی شود تغییر دهد، در نتیجه دستورزبان واژگانی مستقل از متن نیست :INDENT-DEDENT، به اطلاعات متن که از فرورفتگی قبلی می‌گیرد بستگی دارد. تحلیل لغوی حساس به متن به‌طورکلی گرامرهای لغوی، مستقل از متن هستند، یا تقریباً مستقل از متن هستند، که نیازی به نگاه به عقب یا جلو، یا برگشت به عقب (backtracking) هستند، که پیاده‌سازی ساده، تمیز و کارآمد را امکان‌پذیر می‌کند. هم چنین یک ارتباط یک طرفه از تحلیل گر لغوی به تجزیه‌کننده، بدون نیاز به برگشت اطلاعات را ممکن می‌سازد. مثال‌هایی ساده شامل: درج نقطه ویرگول در Go، که به نگاه کردن به توکن قبلی نیاز دارد، الحاق رشتهٔ متوالی در پایتون که نیازدارد قبل از خروج یک توکن محتوای آن در بافر نگه داری شود (برای اینکه ببیند آیا توکن بعدی یک literal است یا نه)؛ و نقش off-side در پایتون، که به نگهداری تعدادی از سطوح فرورفتگی نیاز دارد (در واقع پشته‌ای از هر سطوح فرورفتگی)، این نمونه‌ها فقط نیاز به زمینهٔ لغوی دارند، و در حالی که تحلیل گر لغوی تا حدی آن‌ها را پیچیده می‌کند، برای تجزیه‌کننده و مراحل بعد قابل دیدن نیستند. یک مثال پیچیده‌تر هک تحلیل گر لغوی در C است، که کلاس توکن دنباله‌ای از کاراکترها تا فاز تحلیل گر معنایی، نمی‌تواند تعیین شود. اگرچه نام‌های نوع متغیر از لحاظ لغوی یکسان اند اما کلاس‌های توکن مختلفی را تشکیل می‌دهد؛ بنابراین در این هک، تحلیل گر لغوی تجزیه و تحلیل معنایی را صدا می‌زند (جدول نمادها) و بررسی می‌کند که آیا دنباله به یک نام نوع متغیر نیاز دارد یا خیر. | ## جمع‌بندی | در این مورد نباید اطلاعات فقط از تجزیه‌کننده بازگردد بلکه باید از تحلیلگر معنایی به تحلیل گر لغوی برگردد، که طراحی را پیچیده می‌کند.