تجزیهکننده: تفاوت میان نسخهها
محتوای حذفشده محتوای افزودهشده
جز فرمول ها چپ چین شدند. |
اضافه کردن بلاک کد. |
||
خط ۱۸:
با حروف الفبا شروع و بهدنبال آن حرف ورقم قرار میگیرد A1 id
هرثابت عددی ۳٫۱۴ num
هر رشتهٔ کاراکتری که بین دو علامت " " قرار گیرد "book" literal<syntaxhighlight lang="text">
<<relation >=>= relation if if if
</syntaxhighlight>در بعضی وضعیتها اسکنر قبل از اینکه تصمیم بگیرد که چه توکنی را به پارسر بفرستد، نیاز دارد که چند کاراکتر دیگر را نیز، از ورودی بخواند. مثلاً اسکنر با دیدن علامت <در ورودی نیاز دارد که کاراکتر ورودی بعدی را نیز بخواند. در صورتیکه این کاراکتر = باشد، در نتیجه توکن '<=' و در غیر اینصورت توکن ' <' تشخیص داده میشود. در این مورد باید کاراکتر اضافی خوانده شده مجدداً به ورودی برگردد.▼
▲در بعضی وضعیتها اسکنر قبل از اینکه تصمیم بگیرد که چه توکنی را به پارسر بفرستد، نیاز دارد که چند کاراکتر دیگر را نیز، از ورودی بخواند. مثلاً اسکنر با دیدن علامت <در ورودی نیاز دارد که کاراکتر ورودی بعدی را نیز بخواند. در صورتیکه این کاراکتر = باشد، در نتیجه توکن '<=' و در غیر اینصورت توکن ' <' تشخیص داده میشود. در این مورد باید کاراکتر اضافی خوانده شده مجدداً به ورودی برگردد.
یکی دیگر از مشکلاتی که اسکنر با آن روبروست این است که در زبانهایی نظیر فرترن مثلاً محل خالی یا (space) بجز در رشتههای کاراکتری، نادیده گرفته میشود.
به عنوان مثال کلمهٔ Do در زبان فرترن را در دستور زیر در نظر بگیرید: do bi =۱٫۲۵ تا زمانیکه به نقطهٔ اعشار در ۱٫۲۵ نرسیده باشیم نمیتوان گفت که do در این دستور کلمه کلیدی نیست، بلکه بخشی از متغیری است که نام آن do bi است.
به همین ترتیب در دستور do bi=۱٬۲۵ تا زمانیکه علامت کاما دیده نشود، نمیتوان گفت که این دستور یک حلقهٔ do است.
در زبانهایی که کلمات کلیدی آن جزو کلمات رزرو شده نیستند، اسکنر نمیتواند کلمات کلیدی را از شناسههای همنام آنها تشخیص دهد. به عنوان مثال در دستور زیر:<syntaxhighlight lang="text">
IF Then THEN then=else;ELSE Else=Then;
</syntaxhighlight>جدا کردن کلمهٔ کلیدی THEN از متغیری که نام آن Then است بسیار مشکل است. در این موارد معمولاً پارسر تشخیص نهایی را خواهد داد.▼
▲جدا کردن کلمهٔ کلیدی THEN از متغیری که نام آن Then است بسیار مشکل است. در این موارد معمولاً پارسر تشخیص نهایی را خواهد داد.
۲–۲- خطاهای واژهای(Lexical Errors):
بطور کلی خطاهای محدودی را اسکنر میتواند بیابد، زیرا اسکنر تمام برنامهٔ ورودی را یکجا نمیبیند بلکه هر بار قسمت کوچکی از برنامهٔ منبع را. بهعنوان مثال هرگاه رشتهٔ fi در یک برنامهٔ C برای بار اول مشاهده شود، اسکنر قادر نیست تشخیص دهد که آیا fi یک املای غلط از کلمهٔ کلیدی if است یا نام یک متغیر است: fi (x==۳)
سطر ۵۵ ⟵ ۴۷:
در صورتیکه ورودی شامل تعداد کاراکترهای کمتر از n باشد، بعد از خواندن این کاراکترها یک کاراکتر خاصِ eof نیز وارد بافر میگردد.
کاراکتر eof بیانگر پایان فایل منبع بوده و با سایر کاراکترهای ورودی به نوعی تفاوت دارد.
<br /><syntaxhighlight lang="text">
C ** 2 eof E = M *▼
▲C ** 2 eof
</syntaxhighlight>در بافر ورودی از دو نشانه رو استفاده میشود. رشتهٔ کاراکتری بین این دو نشانه رو، معرف Lexem (واژه) جاری است. در ابتدا هر دو نشانه رو به اولین کاراکتر Lexem بعدی که باید پیدا شود اشاره میکنند.▼
▲ forward
▲ Lexam –beginning ابتدای واژه
▲در بافر ورودی از دو نشانه رو استفاده میشود. رشتهٔ کاراکتری بین این دو نشانه رو، معرف Lexem (واژه) جاری است. در ابتدا هر دو نشانه رو به اولین کاراکتر Lexem بعدی که باید پیدا شود اشاره میکنند.
نشانه رویِ forward پیش میرود تا اینکه یک توکن تشخیص داده شود.
این نحو استفاده از بافر در بیشتر موارد کاملاً خوب عمل میکند. با این وجود در مواردی که جهت تشخیص یک توکن، نشانه روِ forward ناچار است بیشتر از طول بافر جلو برود، این روش درست کار نمیکند.
بهعنوان مثال دستور declare (arg1،arg2، … ،arn n) را در یک برنامهٔ pl/1 در نظر بگیرید.
در این دستور تا زمانیکه کاراکتر بعد از پرانتز سمت راست را بررسی نکنیم، نمیتوان گفت که declare یک کلمهٔ کلیدی است یا اسم یک آرایهاست.
برای [[کنترل حرکت]] نشانه رویِ forward و همچنین کنترل بافر میتوان به صورت زیر عمل کرد:<syntaxhighlight lang="text">
If forward is at end of first half then Begin reload second-half;▼
▲If forward is at end of first half then
Begin reload second-half;▼
End Else▼
▲ Forward:=forward+1
End▼
▲Else
▲ If forward is at end of second-half then
Move forward
▲ End
Move forward to begin of first half▼
▲ Else forward:= forward+1;
</syntaxhighlight><br />
▲ ب) استفاده از نگهبانها (sentinels):
در حالت قبل، با جلو رفتن نشانهروِ forward باید چک میشد که آیا این نشانه رو به انتهای <nowiki>یک</nowiki> نیمه از بافر رسیدهاست یا خیر. درصورتیکه به انتهای <nowiki>یک</nowiki> نیمه از بافر رسیده باشد، باید نیمهٔ دیگر را دوباره بار میکردیم. در الگوریتم فوق، همانطور که مشاهده شد، برای هر جلورَویِ نشانه رویِ forward، دو بار عمل مقایسه انجام میشود. میتوان این دو را به یک بار تست تبدیل کرد.
برای این کار باید در انتهای هر نیمهٔ بافر، یک کاراکتر نگهبان قرار دهیم (نگهبان به عنوان قسمتی از برنامهٔ منبع نخواهد بود). به این ترتیب، برای کنترل حرکت نشانهروِ forward میتوانیم از الگوریتم زیر استفاده کنیم:
forward:=forward + 1 ;▼
if (forward = eof) then▼
begin▼
if (forward is at end of first half) then▼
begin▼
reload second half;▼
end▼
else▼
▲ reload first half;
end▼
else /* eof within a buffer signifying end of input */▼
terminate lexical analysis (آنالیز واژهای به پایان برسد)▼
end.▼
<syntaxhighlight lang="text">
forward:=forward + 1 ; if (forward = eof) then begin
▲ begin
▲end.
</syntaxhighlight>
{{علوم رایانه}}
|