تجزیه‌کننده: تفاوت میان نسخه‌ها

محتوای حذف‌شده محتوای افزوده‌شده
جز فرمول ها چپ چین شدند.
اضافه کردن بلاک کد.
خط ۱۸:
با حروف الفبا شروع و به‌دنبال آن حرف ورقم قرار می‌گیرد A1 id
هرثابت عددی ۳٫۱۴ num
هر رشتهٔ کاراکتری که بین دو علامت " " قرار گیرد "book" literal<syntaxhighlight lang="text">
<<relation >=>= relation if if if
{{چپ‌چین}}
</syntaxhighlight>در بعضی وضعیتها اسکنر قبل از اینکه تصمیم بگیرد که چه توکنی را به پارسر بفرستد، نیاز دارد که چند کاراکتر دیگر را نیز، از ورودی بخواند. مثلاً اسکنر با دیدن علامت <در ورودی نیاز دارد که کاراکتر ورودی بعدی را نیز بخواند. در صورتی‌که این کاراکتر = باشد، در نتیجه توکن '<=' و در غیر اینصورت توکن ' <' تشخیص داده می‌شود. در این مورد باید کاراکتر اضافی خوانده شده مجدداً به ورودی برگردد.
<<relation
>=>= relation
if if if
{{پایان چپ‌چین}}
 
در بعضی وضعیتها اسکنر قبل از اینکه تصمیم بگیرد که چه توکنی را به پارسر بفرستد، نیاز دارد که چند کاراکتر دیگر را نیز، از ورودی بخواند. مثلاً اسکنر با دیدن علامت <در ورودی نیاز دارد که کاراکتر ورودی بعدی را نیز بخواند. در صورتی‌که این کاراکتر = باشد، در نتیجه توکن '<=' و در غیر اینصورت توکن ' <' تشخیص داده می‌شود. در این مورد باید کاراکتر اضافی خوانده شده مجدداً به ورودی برگردد.
یکی دیگر از مشکلاتی که اسکنر با آن روبروست این است که در زبان‌هایی نظیر فرترن مثلاً محل خالی یا (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 *
 
forward
C ** 2 eof
Lexam –beginning ابتدای واژه
E = M *
</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
Forward:=forward+1
Begin reload second-half;
End Else
Forward:=forward+1
 
End
If forward is at end of second-half then
Else
Begin reload first half;
If forward is at end of second-half then
Move forward Beginto reloadbegin of first half;
End
Move forward to begin of first half
Else forward:= forward+1;
End
ب) استفاده از نگهبان‌ها (sentinels):
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;
forward := forward+1 ;
end
else
if (forward at end of second half) then
begin
reload first half;
move forward to beginning of 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
 
if (forward is at end of first half) then
begin
Begin reload second- half;
forward :=forward forward+ 1 ;
end
else
if (forward =at eofend of second half) then
begin
reload secondfirst half;
Move move forward to beginbeginning of first half
end
else /* eof within a buffer signifying end of input */
terminate lexical analysis (آنالیز واژه‌ای به پایان برسد)
end.
</syntaxhighlight>
{{علوم رایانه}}