|
Qiymat qaytarish asosidagi rekursiv kamayish usuli
|
bet | 65/131 | Sana | 16.06.2024 | Hajmi | 1,92 Mb. | | #264063 |
Bog'liq Tiplarni dinamik tarzdaQiymat qaytarish asosidagi rekursiv kamayish usuli. Shunday qilib, qiymat qaytarish asosidagi rekursiv kamayish usulini qo‘llash uchun grammatikani FIRST to‘plamlar kesishmaydigan shaklga aylantirish kerak. Bu murakkab va ko‘p vaqt talab qiladigan jarayondir. Shuning uchun, amaliyotda, tez-tez ishlatiladigan ibora bor, qiymat qaytarish asosidagi rekursiv kamayish hodisa deb ataladi.
Buning uchun leksik analizator anʻanaviy usullarni to‘laligicha, scan va next anaʻnaviy usullar va nusxalash konstruktoriga ega bo‘lgan obʻyekt sifatida namoyon bo‘ladi. Keyin, noaniqlik yuzaga kelishi mumkin bo‘lgan barcha holatlarda, tahlil qilishni boshlashdan oldin leksik analizatorning hozirgi holatini aniqlaymiz (yaʻni, leksik analizatorning nusxasini boshlaymiz) va matnni tahlil qilishni davom ettirishga harakat qilamiz. Bu tahlil muvaffaqiyatsiz bo‘lsa, leksik analizator holatini tiklaymiz va shunday qilib, keyingi grammatika variantni yordamida yana shu zanjirni tahlil qilishga harakat qilinadi va tugaguncha davom ettiriladi. Barcha tahlil imkoniyatlari muvaffaqiyatsiz bo‘lsa, xatolar haqida xabar beramiz.
Bu tahlillovchini bu usul qiymat qaytarmaydigan rekursiv kamayish usuli ko‘ra potensiali sekin ekanligini ochiq-oydin ko‘riy mumkin, lekin evaziga uning
asl shaklida grammatikada qolishi va dasturchi uchun harakat saqlab qolish uchun boshqarish osondir.
Xuddi shu sintaktik tahlil S – bemoll kompilyatorida sintaktik tahlil uchun joriy qilingan. Masalan, quyidagi fragmentda tahlil paytida konstruksiya ifoda operatori yoki izoh ekanligini aniqlovchi usul amalga oshiradi. Ikkala konstruksiya nuqta bilan ajratilgan va ehtimol kvadrat qavslarni o‘z ichiga olgan identifikatorlar ketma-ketligi bilan boshlanishi mumkin.
-
AST.Stmt stmt_or_decl ()
{Lexer saved = new Lexer (lexer); try {
AST.Type t = type_opt ();
if (lexer.Is (Token.Tag.Ident))
return decl_tail (saved.Curr.coor, t);}
catch (ParseFailed) { lexer = saved;
AST.Expr expr = this.expr (); return new AST.Stmt.Expr (compiler,
saved.Curr.coor|lexer.req (Token.Tag.Semicolon).coor, expr);}}
|
try blokida uni tavsif deb hisoblab, konstruksiyani ajratishga harakat qilamiz. Bu muvaffaqiyatsiz bo‘lsa, tahlillovchi istisno chaqiradi va keyin catch blokda tahlil boshlanadi va shu konstruksiya ifoda sifatida tahlil qilinadi.
|
| |