বাম পুনরাবৃত্তি কেন খারাপ?


20

সংকলক ডিজাইনে, ব্যাকরণগুলিতে বাম পুনরাবৃত্তি কেন মুছে ফেলা উচিত? আমি পড়ছি যে এটি কারণ এটি একটি অসীম পুনরাবৃত্তি ঘটায়, তবে এটি কি সঠিক পুনরাবৃত্তি ব্যাকরণের জন্যও সত্য নয়?


2
সাধারণত, সংকলকরা টপ-ডাউন পার্সিং ব্যবহার করে। আপনার যদি বাম-পুনরাবৃত্তি হয় তবে পার্সারটি অসীম পুনরাবৃত্তিতে যায়। যাইহোক, ডান-পুনরাবৃত্তিতে, পার্সার এটির স্ট্রিংয়ের উপসর্গটি দেখতে পারে। সুতরাং, এটি পরীক্ষা করতে পারে যে অনুপাতটি "খুব দূরে" গেছে কিনা। আপনি অবশ্যই ভূমিকাটি অদলবদল করতে পারেন এবং ডান থেকে ভাবগুলি ব্যাখ্যা করতে পারেন, ডান-পুনরাবৃত্তিটিকে খারাপ এবং বাম-পুনরাবৃত্তি সূক্ষ্ম করে তুলতে পারেন।
শাল

6
বাম পুনরাবৃত্তি খারাপ কারণ পুরানো দিনগুলিতে যখন কম্পিউটারগুলির মধ্যে 16 কেবি র‌্যাম ছিল সর্বাধিক ব্যবহৃত পার্সার জেনারেটর এটি মোকাবেলা করতে পারেনি।
আন্দ্রেজ বাউয়ার

উত্তর:


15

বাম রিকার্সিভ ব্যাকরণগুলি অগত্যা কোনও খারাপ জিনিস নয়। এই ব্যাকরণগুলি সহজেই পার্সড বাক্যাংশগুলি ট্র্যাক করতে স্ট্যাক ব্যবহার করে পার্স করা হয়, যেমনটি এলআর পার্সারের ক্ষেত্রে ।

স্মরণ করুন যে সিএফ ব্যাকরণ একটি বাম রিকার্সিভ রুলটি হ'ল:G=(V,Σ,R,S)

ααβ

সঙ্গে একটি উপাদান ভী এবং β একটি উপাদান ভী Σ । (Tuple জন্য সম্পূর্ণ আনুষ্ঠানিক সংজ্ঞা দেখুন ( ভী , Σ , আর , এস ) সেখানে )।αVβVΣ(V,Σ,R,S)

βαα

যখনই ব্যাকরণ পার্সার (লেক্সার থেকে) একটি নতুন টার্মিনাল গ্রহণ করা হচ্ছে তখনই এই টার্মিনালটিকে স্ট্যাকের শীর্ষে চাপ দেওয়া হয়: এই ক্রিয়াকলাপটিকে শিফট বলা হয় ।

প্রতিটি বার যখন কোনও নিয়মের ডান হাতটি স্ট্যাকের শীর্ষে একটানা উপাদানগুলির একটি গ্রুপের সাথে মিলে যায়, এই গোষ্ঠীটি নতুন মিলিত বাক্যটি উপস্থাপন করে এমন একটি উপাদান দ্বারা প্রতিস্থাপিত হয়েছে। এই প্রতিস্থাপনকে হ্রাস বলা হয় ।

ডান রিকার্সিভ ব্যাকরণগুলির সাথে, হ্রাস হ্রাস না হওয়া পর্যন্ত স্ট্যাকটি অনির্দিষ্টকালের জন্য বৃদ্ধি পেতে পারে, সুতরাং নাটকীয়ভাবে পার্সিং সম্ভাবনাগুলি সীমিত করে দেয়। তবে, বাম পুনরাবৃত্তকারীরা সংকলকটি এর আগে হ্রাস তৈরি করতে দেবে (বাস্তবে, যত তাড়াতাড়ি সম্ভব)। দেখুন উইকিপিডিয়া এন্ট্রি আরও তথ্যের জন্য।


আপনি যদি আপনার ভেরিয়েবলগুলি সংজ্ঞায়িত করেন এটি সাহায্য করবে help
অ্যান্ড্রু এস

12

এই নিয়মটি বিবেচনা করুন:

example : 'a' | example 'b' ;

এখন 'b'এই নিয়মের মতো কোনও মিল না করা স্ট্রিংয়ের সাথে মিল করার চেষ্টা করে একটি এলএল পার্সার বিবেচনা করুন । যেহেতু 'a'মিলছে না, এটি মিলানোর চেষ্টা করবে example 'b'। তবে এটি করার জন্য, এটি মিলতে হবে example... যা এটি প্রথম স্থানে করার চেষ্টা করছিল। এটি মিলতে পারে কিনা তা দেখার জন্য চিরতরে চেষ্টা আটকে যেতে পারে, কারণ এটি সর্বদা টোকেনের একই ধারাটিকে একই নিয়মের সাথে মেলে দেওয়ার চেষ্টা করে।

এটি রোধ করার জন্য, আপনাকে হয় ডান দিক থেকে পার্স করতে হবে (যা বেশ অস্বাভাবিক, যতদূর আমি দেখেছি, এবং এর পরিবর্তে সমস্যাটি সঠিক পুনরাবৃত্তি করতে হবে), কৃত্রিমভাবে বাসা বাঁধার পরিমাণ সীমিত করে বা ম্যাচ করে পুনরাবৃত্তি শুরুর আগে একটি টোকেন যাতে সর্বদা একটি বেস কেস থাকে (যথা, যেখানে সমস্ত টোকেন গ্রাস হয়ে গেছে এবং এখনও কোনও সম্পূর্ণ মিল নেই)। যেহেতু একটি ডান-রিকার্সি বিধি ইতিমধ্যে তৃতীয়টি করে, তাই এটির একই সমস্যা নেই।


3
আপনি এক ধরণের অন্ধভাবে ধরে ধরেছেন যে পার্সিং অগত্যা নির্বোধ শীর্ষ-ডাউন পার্সিং।
পুনরায় পোস্টার

আমি পার্সিংয়ের পরিবর্তে সাধারণ পদ্ধতির একটি সমস্যাটি হাইলাইট করছি - এমন সমস্যা যা সহজেই এড়ানো যায়। বাম-পুনরাবৃত্তি পরিচালনা করা অবশ্যই সম্ভব , তবে এটি ধরে রাখা পার্সার ধরণের ক্ষেত্রে প্রায় সর্বদা-অপ্রয়োজনীয় সীমাবদ্ধতা তৈরি করে।
সিএওও

হ্যাঁ, এটি রাখার আরও গঠনমূলক এবং দরকারী উপায়।
পুনরায় পোস্টার

4

(আমি জানি এখনই এই প্রশ্নটি বেশ পুরানো, তবে অন্য লোকের ক্ষেত্রেও যদি একই প্রশ্ন থাকে ...)

আপনি পুনরাবৃত্তি বংশদ্ভুত পার্সারদের প্রসঙ্গে জিজ্ঞাসা করছেন? উদাহরণস্বরূপ, ব্যাকরণের জন্য expr:: = expr + term | termকেন এমন কিছু (বাম রিকার্সিভ):

// expr:: = expr + term
expr() {
   expr();
   if (token == '+') {
      getNextToken();
   }
   term();
}

সমস্যাযুক্ত, তবে এটি না (ডান পুনরাবৃত্তি)?

// expr:: = term + expr
expr() {
   term();
   if (token == '+') {
      getNextToken();
      expr();
   }
}

এটি উভয় সংস্করণের expr()কল বলে মনে হয়। তবে গুরুত্বপূর্ণ পার্থক্যটি প্রসঙ্গ - অর্থাত্ বর্তমান টোকেন যখন সেই পুনরাবৃত্তি কল করা হয়।

বাম পুনরাবৃত্তির ক্ষেত্রে expr()ক্রমাগত একই টোকেনের সাথে নিজেকে কল করে এবং কোনও অগ্রগতি হয় না। ডান পুনরাবৃত্তির ক্ষেত্রে, এটি কলটিতে term()পৌঁছানোর আগে কলটিতে কিছু ইনপুট এবং প্লাস টোকেন গ্রাস করে expr()। সুতরাং এই মুহুর্তে, পুনরাবৃত্তি কলটি কল করতে পারে এবং তারপরে আবার পরীক্ষায় পৌঁছানোর আগে শেষ হতে পারে।

উদাহরণস্বরূপ, 2 + 3 + 4 পার্সিংয়ের expr()বিষয়টি বিবেচনা করুন first প্রথম টোকেনটিতে আটকে থাকার সময় বাম রিকার্সিভ পার্সার কলকে অসীম কল করে, যখন ডান রিকার্সিভ পার্সার expr()আবার কল করার আগে "2 +" গ্রাস করে । expr()"3 +" মেলে এবং দ্বিতীয় কলটি কেবল expr()4 টি বামে কল করে। একটি শর্তের সাথে 4 টি মিল এবং পার্সিং এর আর কোনও কল ছাড়াই শেষ হয় expr()


2

বাইসন ম্যানুয়াল থেকে:

"যে কোনও ধরণের ক্রমকে বাম পুনরাবৃত্তি বা ডান পুনরাবৃত্তি ব্যবহার করে সংজ্ঞায়িত করা যেতে পারে, তবে আপনার সর্বদা বাম পুনরাবৃত্তি ব্যবহার করা উচিত , কারণ এটি সীমিত স্ট্যাক স্পেস সহ যে কোনও সংখ্যক উপাদানের অনুক্রমকে পার্স করতে পারে Right ডান পুনরাবৃত্তি বাইসন স্ট্যাকের উপর স্থান ব্যবহার করে অনুক্রমের উপাদানগুলির সংখ্যার অনুপাত, কারণ নিয়ম একবারে প্রয়োগ করার আগে সমস্ত উপাদান অবশ্যই স্ট্যাকের উপরে স্থানান্তরিত করতে হবে this এর আরও ব্যাখ্যার জন্য বাইসন পার্সার অ্যালগরিদম দেখুন ""

http://www.gnu.org/software/bison/manual/html_node/Recursion.html

সুতরাং এটি পার্সারের অ্যালগরিদমের উপর নির্ভর করে তবে অন্যান্য উত্তরে যেমন বলা হয়েছে, কিছু পার্সার কেবল বাম পুনরাবৃত্তি নিয়ে কাজ করতে পারে না

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.