কখন পার্সার কম্বিনেটর ব্যবহার করবেন? পার্সার জেনারেটর কখন ব্যবহার করবেন?


59

আমি সম্প্রতি নিজের প্রোগ্রামিং ভাষা তৈরি করতে চাইলে পার্সারদের বিশ্বে একটি গভীর ডুব নিয়েছি।

যাইহোক, আমি খুঁজে পেয়েছি যে পার্সার লেখার দুটি পৃথক পদ্ধতির উপস্থিতি রয়েছে: পার্সার জেনারেটর এবং পার্সার সম্মিলক।

মজার বিষয় হল, আমি কোনও সংস্থান খুঁজে পেতে অক্ষম হয়েছি যা কোন ক্ষেত্রে কোন পদ্ধতির চেয়ে ভাল তা ব্যাখ্যা করেছে; বরং, অনেক সম্পদ (এবং ব্যক্তি) আমি জানতে চাওয়া সম্পর্কে বিষয় অন্যান্য পদ্ধতির জানেন না, শুধুমাত্র ব্যাখ্যা তাদের হিসাবে পদ্ধতির পদ্ধতির এবং সব অন্য না উল্লেখ:

সাধারণ ওভারভিউ:

পার্সার জেনারেটর

পার্সার জেনারেটর একটি ডিএসএল-তে লিখিত একটি ফাইল নিয়ে যায় যা এক্সটেন্ডেড ব্যাকাস-নওর ফর্মের কিছু উপভাষা হয় এবং এটিকে উত্স কোডে পরিণত করে যা এই ডিএসএলে বর্ণিত ইনপুট ভাষার পার্সার হয়ে যেতে পারে।

এর অর্থ সংকলন প্রক্রিয়া দুটি পৃথক ধাপে সম্পন্ন হয়। মজার বিষয় হল, পার্সার জেনারেটরগুলি নিজেও সংকলক (এবং তাদের মধ্যে অনেকগুলি প্রকৃতপক্ষে স্ব-হোস্টিং )।

পার্সার সমন্বয়কারী

পার্সার সম্মিলক পার্সার নামক সাধারণ ফাংশনগুলি বর্ণনা করে যা সবাই প্যারামিটার হিসাবে একটি ইনপুট নেয় এবং যদি তারা মেলে তবে এই ইনপুটটির প্রথম অক্ষর (গুলি) কেড়ে নেওয়ার চেষ্টা করবে। তারা একটি টিপল ফেরত দেয় (result, rest_of_input), যেখানে পার্সার এই ইনপুট থেকে কোনও কিছু বিশ্লেষণ করতে অক্ষম হলে resultখালি (যেমন nilবা Nothing) হতে পারে । উদাহরণ একটি digitপার্সার হবে। অন্যান্য পার্সার অবশ্যই অবশ্যই তাদের যুক্ত করার জন্য প্রথম যুক্তি হিসাবে চূড়ান্ত যুক্তি (এখনও ইনপুট স্ট্রিংয়ের মধ্যে থাকা চূড়ান্ত যুক্তি) হিসাবে পার্সার নিতে পারে : যেমন many1অন্য পার্সারকে যতবার সম্ভব মিলানোর চেষ্টা করা (তবে কমপক্ষে একবার, বা এটি নিজেই ব্যর্থ হয়)।

আপনি এখন অবশ্যই একত্রিত করতে পারেন (রচনা করুন) digitএবং many1, একটি নতুন পার্সার তৈরি করতে, বলুন integer

এছাড়াও, একটি উচ্চ-স্তরের choiceপার্সার লেখা যেতে পারে যা পার্সারগুলির একটি তালিকা নেয়, প্রতিটি পরিবর্তে চেষ্টা করে।

এইভাবে, খুব জটিল লেক্সার / পার্সার তৈরি করা যায়। অপারেটর ওভারলোডিং সমর্থনকারী ভাষায়, এটি EBNF এর মতো দেখতে খুব বেশি লাগে, যদিও এটি এখনও সরাসরি লক্ষ্য ভাষায় লিখিত হয় (এবং আপনি যে টার্গেট ল্যাঙ্গুয়েজটি চান তার সমস্ত বৈশিষ্ট্য ব্যবহার করতে পারেন)।

সাধারণ পার্থক্য

ভাষা:

  • পার্সার জেনারেটরগুলি EBNF-ish DSL এবং কোডটির সংমিশ্রণে লিখিত হয় যা এই বিবৃতিগুলি যখন মিলবে তখন তা তৈরি করা উচিত।
  • পার্সার কম্বিনেটরগুলি সরাসরি লক্ষ্য ভাষায় লেখা হয়।

Lexing / পার্সিং:

  • পার্সার জেনারেটরগুলির 'লেক্সার' (যা কোন ধরণের স্ট্রোককে টোকনে বিভক্ত করে যা আমরা কী ধরণের মান নিয়ে কাজ করছি তা দেখানোর জন্য ট্যাগ করা যেতে পারে) এবং 'পার্সার' (যা লেক্সারের কাছ থেকে টোকেনের আউটপুট তালিকা গ্রহণ করে) এর মধ্যে খুব আলাদা পার্থক্য রয়েছে এবং একটি বিমূর্ত সিনট্যাক্স ট্রি গঠন করে এগুলি একত্রিত করার চেষ্টা করে)।
  • পার্সার সংযুক্তকারীদের এই পার্থক্য / প্রয়োজন নেই; সাধারণত, সরল পার্সাররা 'লেক্সার' এর কাজ সম্পাদন করে এবং আরও উচ্চ-স্তরের পার্সাররা এটিকে আরও সহজভাবে ডাকে কোন ধরণের এএসটি-নোড তৈরি করতে হবে তা নির্ধারণ করতে।

প্রশ্ন

যাইহোক, এমনকি এই পার্থক্যগুলি দেওয়া (এবং এটি পার্থক্যগুলির তালিকা সম্ভবত সম্পূর্ণরূপে অনেক দূরে!), কখন কোনটি ব্যবহার করবেন সে সম্পর্কে আমি শিক্ষিত পছন্দ করতে পারি না । এই পার্থক্যগুলির কী কী প্রভাব / পরিণতি হয় তা আমি দেখতে ব্যর্থ।

কোন সমস্যার বৈশিষ্ট্য ইঙ্গিত দেয় যে পার্সার জেনারেটর ব্যবহার করে কোনও সমস্যার সমাধান করা আরও ভাল? কোন সমস্যার বৈশিষ্ট্যগুলি বোঝায় যে কোনও সমস্যা এবং পার্সার কম্বিনেটর ব্যবহার করে আরও ভাল সমাধান করা হবে?


4
পার্সার প্রয়োগের কমপক্ষে আরও দুটি উপায় রয়েছে যা আপনি উল্লেখ করেন নি: পার্সার দোভাষী (পার্সার জেনারেটরের সাথে সমান, উদাহরণস্বরূপ সি বা জাভাতে পার্সার ভাষা সংকলন না করে, পার্সার ল্যাঙ্গুয়েজ সরাসরি সম্পাদন করা হয়), এবং কেবল লিখুন হাত দ্বারা পার্সার হাত দিয়ে পার্সার লেখা অনেকগুলি আধুনিক উত্পাদন-প্রস্তুত শিল্প-শক্তি ভাষার বাস্তবায়নের (যেমন জিসিসি, কলং javac, স্কেলা) বাস্তবায়নের পছন্দসই রূপ । এটি আপনাকে অভ্যন্তরীণ পার্সার রাজ্যের উপর সর্বাধিক নিয়ন্ত্রণ দেয় যা ভাল ত্রুটি বার্তাগুলি তৈরি করতে সহায়তা করে (যা সাম্প্রতিক বছরগুলিতে…
জার্গ ডব্লু মিট্টাগ

3
… ভাষা প্রয়োগকারীদের জন্য খুব উচ্চ অগ্রাধিকারে পরিণত হয়েছে)। এছাড়াও, প্রচুর বিদ্যমান পার্সার জেনারেটর / দোভাষী / সংযুক্তকারীরা আধুনিক ভাষার বাস্তবায়ন অবশ্যই পূরণ করতে হবে এমন বিভিন্ন ধরণের দাবীগুলি মোকাবিলার জন্য সত্যই ডিজাইন করা হয়নি। উদাহরণস্বরূপ অনেক আধুনিক ভাষার প্রয়োগগুলি ব্যাচের সংকলন, আইডিই ব্যাকগ্রাউন্ড সংকলন, সিনট্যাক্স হাইলাইটিং, অটোমেটেড রিফ্যাক্টরিং, বুদ্ধিমান কোড সমাপ্তি, স্বয়ংক্রিয় ডকুমেন্টেশন জেনারেশন, স্বয়ংক্রিয় ডায়াগ্রামিং ইত্যাদির জন্য একই টুকরা কোড ব্যবহার করে Sc । অনেক বিদ্যমান পার্সার…
Jörg ডব্লু মিট্টাগ

1
… ফ্রেমওয়ার্কগুলি এটি মোকাবেলায় যথেষ্ট নমনীয় নয়। এছাড়াও লক্ষ করুন যে এখানে পার্সার ফ্রেমওয়ার্কগুলি ইবিএনএফ ভিত্তিক নয়। এক্সপ্রেশন ব্যাকরণকে পার্সিংয়ের জন্য উদাহরণস্বরূপ প্যাক্র্যাট পার্সার
Jörg W Mittag

2
আমি মনে করি এটি আপনি যে ভাষার সংকলনের চেষ্টা করছেন তার উপর এটি প্রচুরভাবে নির্ভর করে। এটি কী ধরণের (এলআর, ...)?
qwerty_so

1
আপনার উপরের অনুমানটি বিএনএফ এর উপর ভিত্তি করে তৈরি করা হয় যা সাধারণত লেক্সার / এলআর পার্সার সংমিশ্রণ দিয়ে সংকলিত হয়। তবে ভাষাগুলি অগত্যা এলআর ব্যাকরণ ভিত্তিক নয়। সুতরাং আপনি যা আপনার সংকলনের পরিকল্পনা করছেন?
qwerty_so

উত্তর:


59

এই পৃথক প্রযুক্তি কেন বিদ্যমান এবং এর শক্তি এবং দুর্বলতাগুলি কী তা আরও ভাল করে বুঝতে, আমি গত কয়েক দিন প্রচুর গবেষণা করেছি।

ইতিমধ্যে বিদ্যমান উত্তরগুলির মধ্যে কয়েকটি তাদের পার্থক্যের ইঙ্গিত দিয়েছিল, তবে তারা সম্পূর্ণ চিত্র দেয়নি, এবং কিছুটা মতামত বলে মনে হয়েছিল, এই কারণেই এই উত্তরটি লেখা হয়েছিল।

এই প্রকাশ দীর্ঘ, তবে গুরুত্বপূর্ণ। আমার সাথে সহ্য করুন (বা যদি আপনি অধৈর্য হন তবে ফ্লোচার্ট দেখতে শেষে স্ক্রোল করুন)।


পার্সার কম্বিনেটর এবং পার্সার জেনারেটরগুলির মধ্যে পার্থক্য বুঝতে, প্রথমে যে বিভিন্ন ধরণের পার্সিং রয়েছে তার মধ্যে পার্থক্য বুঝতে হবে।

পদান্বয়

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

পার্সিং এমন একটি সমস্যা যা গণনাগতভাবে কঠিন। এই বিষয়ে পঞ্চাশ বছরেরও বেশি গবেষণা হয়েছে, তবে এখনও শিখতে হবে অনেক কিছুই।

মোটামুটিভাবে বলতে গেলে কম্পিউটারকে পার্স করার জন্য চারটি সাধারণ অ্যালগরিদম রয়েছে:

  • এলএল পার্সিং। (প্রসঙ্গমুক্ত, টপ-ডাউন পার্সিং))
  • এলআর পার্সিং। (প্রসঙ্গমুক্ত, নীচের অংশে পার্সিং।)
  • পিইজি + প্যাক্র্যাট পার্সিং।
  • আর্লি পার্সিং।

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

এলএল এবং এলআর কেবল প্রাসঙ্গিক-ব্যাকরণ ব্যাকরণগুলিতেই দেখতে পারে (এটি; টোকেনগুলির চারপাশের প্রসঙ্গটি কীভাবে ব্যবহৃত হয় তা বোঝার জন্য এটি কীভাবে ব্যবহৃত হয় তা গুরুত্বপূর্ণ নয়)।

পিইজি / প্যাক্র্যাট পার্সিং এবং আর্লি পার্সিংটি খুব কম ব্যবহৃত হয়: আর্লি-পার্সিংটি খুব ভাল যে এটি আরও অনেক বেশি ব্যাকরণ পরিচালনা করতে পারে (এটি প্রাসঙ্গিক-মুক্ত নয় এমনগুলি সহ) তবে এটি কম দক্ষ (ড্রাগনের দাবি অনুসারে) বই (বিভাগ ৪.১.১); এই দাবিগুলি এখনও সঠিক কিনা আমি নিশ্চিত নই)) পার্সিং এক্সপ্রেশন ব্যাকরণ + প্যাক্র্যাট-পার্সিং এমন একটি পদ্ধতি যা তুলনামূলকভাবে দক্ষ এবং এটি এলএল এবং এলআর উভয়ের চেয়ে বেশি ব্যাকরণ পরিচালনা করতে পারে তবে অস্পষ্টতা লুকায়, যেমনটি নীচে স্পর্শ করা হবে।

এলএল (বাম থেকে ডান, বাম দিকের ডেরাইভেশন)

পার্সিং সম্পর্কে চিন্তা করার এটি সম্ভবত সবচেয়ে প্রাকৃতিক উপায়। ধারণাটি হ'ল ইনপুট স্ট্রিংয়ের পরবর্তী টোকেনটি দেখুন এবং তারপরে সিদ্ধান্ত নেবেন যে কোনও গাছের কাঠামো তৈরি করতে কোনও একাধিক সম্ভাব্য পুনরাবৃত্তি কল গ্রহণ করা উচিত।

এই গাছটি 'টপ-ডাউন' নির্মিত, যার অর্থ আমরা গাছের গোড়া থেকে শুরু করি এবং ইনপুট স্ট্রিংয়ের মধ্য দিয়ে যেমন ভ্রমণ করি তেমনভাবে ব্যাকরণের নিয়মগুলিও ভ্রমণ করি। এটি 'ইনফিক্স' টোকন স্ট্রিমটি পড়া হচ্ছে এর সমপরিমাণ একটি 'পোস্টফিক্স' নির্মাণ হিসাবেও দেখা যেতে পারে।

এলএল-স্টাইলের পার্সিং সম্পাদনকারী পার্সারগুলিকে অনেকটা নির্দিষ্ট করে দেওয়া মূল ব্যাকরণের মতো দেখতে লেখা যেতে পারে। এটি এগুলি বোঝার, ডিবাগ করার এবং উন্নত করার তুলনামূলকভাবে সহজ করে তোলে। ক্লাসিকাল পার্সার কম্বিনেটরগুলি 'লেগো টুকরা' ছাড়া আর কিছু নয় যা এলএল-স্টাইলের পার্সার তৈরি করতে একসাথে রাখা যেতে পারে।

এলআর (বাম থেকে ডান, ডানদিকের ডেরাইভেশন)

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

একটি প্রোগ্রাম সঠিক হয় যদি শেষে আমরা স্ট্যাকের একক নোড দিয়ে শেষ করি যা আমাদের ব্যাকরণ থেকে শুরু হওয়া নিয়মকে উপস্থাপন করে।

সামনে দেখো

এই দুটি সিস্টেমে কোনও একটিতে, কোন পছন্দটি বেছে নিতে পারে তা সিদ্ধান্ত নেওয়ার আগে কখনও কখনও ইনপুট থেকে আরও টোকেনে উঁকি দেওয়া প্রয়োজন। এই (0), (1), (k)বা (*)-syntax আপনি যেমন এই দুটি সাধারণ আলগোরিদিম, নাম পর দেখতে LR(1) বা LL(k)kসাধারণত 'আপনার ব্যাকরণের যতটুকু প্রয়োজন' এর *জন্য দাঁড়িয়ে থাকে , তবে সাধারণত 'এই পার্সার ব্যাকট্র্যাকিং সম্পাদন করে' যা আরও কার্যকর / কার্যকর করা সহজ, তবে পার্সারের তুলনায় অনেক বেশি স্মৃতি এবং সময়ের ব্যবহার রয়েছে যা কেবল বিশ্লেষণ চালিয়ে যেতে পারে সুসংগত।

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

এলএল বনাম এলআর: অ্যামিগুটি

উপরের দুটি বিবরণ পড়ার সময়, কেউ ভাবতে পারেন যে এলআর-স্টাইলের পার্সিং কেন বিদ্যমান, কারণ এলএল-স্টাইলের পার্সিংকে অনেক বেশি প্রাকৃতিক মনে হয়।

তবে, এলএল-স্টাইল পার্সিংয়ের একটি সমস্যা রয়েছে: বাম রিক্রুশন

ব্যাকরণ লেখা খুব স্বাভাবিক:

expr ::= expr '+' expr | term term ::= integer | float

তবে, এই ব্যাকরণটিকে বিশ্লেষণ করার সময় একটি এলএল-স্টাইলের পার্সার একটি অসীম পুনরাবৃত্ত লুপের মধ্যে আটকে যাবে: exprনিয়মের বাম-সর্বাধিক সম্ভাবনাটি চেষ্টা করার সময় , কোনও ইনপুট ব্যয় না করে আবার এই নিয়মের পুনরাবৃত্তি করে।

এই সমস্যাটি সমাধান করার উপায় রয়েছে। সবচেয়ে সহজ হ'ল আপনার ব্যাকরণটি নতুন করে লিখুন যাতে এই ধরণের পুনরাবৃত্তি আর না ঘটে:

expr ::= term expr_rest expr_rest ::= '+' expr | ϵ term ::= integer | float (এখানে, ε 'খালি স্ট্রিং' ঘোরা)

এই ব্যাকরণ এখন ঠিক পুনরাবৃত্তি। দ্রষ্টব্য যে এটি অবিলম্বে পড়া আরও অনেক কঠিন।

অনুশীলনে, বাম-পুনরাবৃত্তি অপ্রত্যক্ষভাবে অন্য অনেক পদক্ষেপের মধ্যে হতে পারে । এটি সন্ধান করা একটি কঠিন সমস্যা করে তোলে। তবে এটি সমাধান করার চেষ্টা করা আপনার ব্যাকরণকে আরও শক্ত করে।

ড্রাগন বুকের ২.৪ অনুচ্ছেদে বলা হয়েছে:

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

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

দ্ব্যর্থহীনতা কীভাবে সমাধান করবেন

উপরের বাম-পুনরাবৃত্তি দ্বিখণ্ডিততাগুলি সমাধান করার জন্য আমরা দুটি পদ্ধতি দেখেছি: ১) সিনট্যাক্সটি পুনরায় লিখুন 2) একটি এলআর-পার্সার ব্যবহার করুন।

তবে অন্যান্য ধরণের দ্ব্যর্থ রয়েছে যা সমাধান করা শক্ত: যদি একই সাথে দুটি আলাদা বিধি একইভাবে প্রযোজ্য হয় তবে কী হবে?

কয়েকটি সাধারণ উদাহরণ হ'ল:

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

এর আর একটি 'সমাধান' পার্সার এক্সপ্রেশন ব্যাকরণ (পিইজি) ব্যবহার করা: এটি উপরের বিএনএফ-ব্যাকরণের সাথে সমান, তবে একটি অস্পষ্টতার ক্ষেত্রে সর্বদা 'প্রথমটি বেছে নিন'। অবশ্যই এটি সমস্যাটিকে 'সমাধান' করে না, বরং এটি লুকিয়ে রাখুন যে একটি অস্পষ্টতা আসলে বিদ্যমান: শেষ ব্যবহারকারীরা পার্সার কোন পছন্দটি পছন্দ করতে পারে তা জানেন না এবং এটি অপ্রত্যাশিত ফলাফলের দিকে নিয়ে যেতে পারে।

আপনার ব্যাকরণের কোনও অস্পষ্টতা নেই কিনা তা সাধারণভাবে জানা কেন অসম্ভব এবং এই বিষয়টির নিদর্শনগুলি প্রসঙ্গে একটি দুর্দান্ত ব্লগ আর্টিকেল এলএল এবং এলআর: কেন পার্সিং করছে তা সহ এই পোস্টের তুলনায় সম্পূর্ণ আরও গভীর এবং আরও বেশি তথ্য সরঞ্জাম শক্ত হয় । আমি এটির সুপারিশ করতে পারি; আমি এই মুহুর্তে যে বিষয়গুলি বলছি তা বুঝতে এটি আমাকে অনেক সহায়তা করেছে।

গবেষণা 50 বছর

কিন্তু জীবন চলমান. দেখা গেল যে 'নরমাল' এলআর-স্টাইল পার্সারদের সীমাবদ্ধ রাষ্ট্র অটোমেটন হিসাবে প্রায়শই প্রয়োগ করা হয় প্রায়শই হাজার হাজার রাজ্য প্রয়োজন + ট্রানজিশন যা প্রোগ্রাম আকারে সমস্যা ছিল। সুতরাং, সিম্পল এলআর (এসএলআর) এবং এলএলআর (লুক- ফরোয়ার্ড এলআর) এর মতো রূপগুলি লেখা হয়েছিল যা অটোমেটনকে ছোট করার জন্য অন্যান্য কৌশলগুলির সাথে একত্রিত হয়, পার্সার প্রোগ্রামগুলির ডিস্ক এবং মেমরির পদচিহ্ন হ্রাস করে।

এছাড়াও, উপরে তালিকাভুক্ত অস্পষ্টতাগুলি সমাধান করার আরেকটি উপায় হ'ল সাধারণ কৌশলগুলি ব্যবহার করা , যেখানে দ্বিপাক্ষিকতার ক্ষেত্রে উভয় সম্ভাবনা রাখা হয় এবং বিশ্লেষণ করা হয়: হয় কেউ লাইনটি বিশ্লেষণ করতে ব্যর্থ হতে পারে (অন্য ক্ষেত্রে সম্ভাবনাটি হ'ল 'সঠিক' এক), পাশাপাশি উভয়কেই ফিরিয়ে দেওয়া (এবং এইভাবে উভয়ই সঠিক হওয়ার ক্ষেত্রে একটি দ্ব্যর্থহীনতা দেখায়)।

মজার বিষয় হল, জেনারেলাইজড এলআর অ্যালগরিদম বর্ণিত হওয়ার পরে দেখা গেল যে জেনারালাইজড এলএল পার্সারগুলি প্রয়োগ করতে একই ধরণের পদ্ধতির ব্যবহার করা যেতে পারে , যা একইভাবে দ্রুত ($ O (n ^ 3) amb অস্পষ্ট ব্যাকরণগুলির জন্য সময়ের জটিলতা, $ O (n) completely সম্পূর্ণ দ্ব্যর্থহীন ব্যাকরণের জন্য, সাধারণ (এলএ) এলআর পার্সারের চেয়ে বেশি বুককিপিংয়ের অর্থ, যার অর্থ উচ্চতর ধ্রুবক-গুণক) তবে আবার কোনও পার্সারকে পুনরাবৃত্ত বংশোদ্ভূত (উপরে-ডাউন) স্টাইলে লেখার অনুমতি দিন যা অনেক বেশি প্রাকৃতিক is লিখতে এবং ডিবাগ করতে।

পার্সার কম্বিনেটর, পার্সার জেনারেটর

সুতরাং, এই দীর্ঘ প্রকাশের সাথে আমরা এখন প্রশ্নের মূল দিকে পৌঁছে যাচ্ছি:

পার্সার কম্বিনেটর এবং পার্সার জেনারেটরের পার্থক্য কী এবং কখন অন্যটির ব্যবহার করা উচিত?

তারা সত্যিই বিভিন্ন ধরণের জন্তু:

পার্সার সম্মিলকগুলি তৈরি করা হয়েছিল কারণ লোকেরা টপ-ডাউন পার্সার লিখছিল এবং বুঝতে পেরেছিল যে এর মধ্যে অনেকগুলিতে প্রচলিত রয়েছে

পার্সার জেনারেটর তৈরি করা হয়েছিল কারণ লোকেরা এমন পার্সার তৈরি করতে চেয়েছিল যা এলএল স্টাইলের পার্সারগুলির (যেমন এলআর-স্টাইল পার্সারগুলির) সমস্যা ছিল না, যা হাতে হাতে করা খুব কঠিন প্রমাণিত হয়েছিল। সাধারণগুলিতে ইয়্যাক / বাইসন অন্তর্ভুক্ত থাকে যা প্রয়োগ করে (এলএ) এলআর)।

মজার বিষয় হল, আজকাল ল্যান্ডস্কেপ কিছুটা গলে গেছে:

  • লিখতে করা সম্ভব পার্সার Combinators যে সঙ্গে কাজ GLL অ্যালগরিদম , অস্পষ্টতা-বিষয় শাস্ত্রীয় কলিজা-শৈলী পারজার, ছিল যখন ঠিক যেমন পাঠযোগ্য / টপ-ডাউন পার্স সব ধরণের যেমন বোধগম্য হচ্ছে সমাধানে।

  • পার্সার জেনারেটরগুলি এলএল-স্টাইলের পার্সারদের জন্যও লেখা যেতে পারে। এএনটিএলআর ঠিক তা করে এবং ক্লাসিকাল এলএল-স্টাইল পার্সারদের যে অস্পষ্টতা ছিল তা সমাধান করতে অন্যান্য হিউরিস্টিক্স (অ্যাডাপটিভ এলএল (*)) ব্যবহার করে।

সাধারণভাবে, একটি এলআর পার্সার জেনারেটর তৈরি করা এবং আপনার ব্যাকরণে চলমান একটি এলএ-স্টাইল পার্সার জেনারেটরের আউটপুট ডিবাগ করা কঠিন, কারণ আপনার মূল ব্যাকরণেরটি 'অভ্যন্তরীণ' এলআর ফর্মটিতে অনুবাদ করার কারণে। অন্যদিকে, Yacc / বাইসন মত সরঞ্জাম optimisations অনেক বছর ছিল, এবং বন্য, যার মানে অনেক মানুষ এখন হিসেবে বিবেচনা ব্যবহারের অনেক দেখেছি পথ পার্সিং করতে এবং নতুন পন্থা প্রতি সন্দিহান হয়ে থাকেন।

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

পার্শ্ব দ্রষ্টব্য: লেক্সিকাল বিশ্লেষণের বিষয়টিতে।

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

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

শেষে একটি লেক্সার হ'ল 'ঠিক' অন্য পার্সার এবং উপরের যে কোনও কৌশল ব্যবহার করে প্রয়োগ করা যেতে পারে। এর সরলতার কারণে, প্রায়শই অন্যান্য কৌশলগুলি মূল পার্সার ছাড়া ব্যবহৃত হয় এবং উদাহরণস্বরূপ অতিরিক্ত 'লেক্সার জেনারেটর' বিদ্যমান রয়েছে।


TL; ড:

এখানে বেশিরভাগ ক্ষেত্রে প্রযোজ্য একটি ফ্লোচার্ট দেওয়া হয়েছে: এখানে চিত্র বর্ণনা লিখুন


@ সোজার্ড এটি সত্যিই অনেকগুলি পাঠ্য, কারণ এটি খুব কঠিন সমস্যা হিসাবে দেখা গেছে। আপনি যদি এমন কোনও উপায় জানেন যা আমি চূড়ান্ত অনুচ্ছেদটিকে আরও স্পষ্ট করে তুলতে পারি, তবে আমি সমস্ত কান: "আপনার কোনটি ব্যবহার করা উচিত তা নির্ভর করে আপনার ব্যাকরণটি কতটা শক্ত এবং পার্সার কতটা দ্রুত হওয়া দরকার তার উপর নির্ভর করে the ব্যাকরণের উপর নির্ভর করে, এর মধ্যে একটি কৌশল (/ বিভিন্ন প্রযুক্তির বাস্তবায়ন) দ্রুততর হতে পারে, একটি ছোট মেমোরির পদচিহ্ন থাকতে পারে, একটি ছোট ডিস্কের পদচিহ্ন থাকতে পারে বা অন্যের তুলনায় আরও বেশি বর্ধিত বা ডিবাগ করা সহজ হতে পারে Your আপনার মাইলেজ মে মেশিনের পরিবর্তন হতে পারে। "
কিউকিউই

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

1
@ উত্তরটি এই উত্তরটি লেখার কারণটি হ'ল অন্য উত্তরগুলি হ'ল সমস্যাটির প্রতিবিম্বিত করছে, একটি আংশিক উত্তর পুরো উত্তর হিসাবে উপস্থাপন করছে এবং / অথবা উপাখ্যানটি ভুল ফাঁদে পড়েছিল । উপরের উত্তরটি হ'ল জার্গ ডব্লু মিটাগ, টমাস কিলিয়ান এবং আমি পূর্ববর্তী জ্ঞান না ধরেই তারা কী সম্পর্কে কথা বলছিল এবং উপস্থাপন করেছিল তা বোঝার পরে প্রশ্নের মন্তব্যে এই আলোচনার মূর্ত প্রতীক ।
কিউকিউই

যাই হোক না কেন, আমি প্রশ্নের সাথে একটি টিএল; ড ফ্লোচার্ট যুক্ত করেছি। এটি কি আপনাকে সন্তুষ্ট করে, @ সোজার্ড?
কিউকিউই

2
পার্সার সংযুক্তকারীরা যখন আপনি আসলে সেগুলি ব্যবহার করবেন না তখন সমস্যাটি সমাধান করতে ব্যর্থ হন। আরও কিছু কম্বিনেটর আছে কেবলমাত্র |, এটিই পুরো বিষয়টি। এর জন্য সঠিক পুনর্লিখনটি exprআরও বেশি সংক্ষেপণ expr = term 'sepBy' "+"(যেখানে এখানে একক উদ্ধৃতি ব্যাকটিক্স একটি ফাংশন ইনফিক্স ঘুরিয়ে আনার জন্য প্রতিস্থাপন করছে, কারণ মিনি-মার্কডাউন চরিত্রের অস্তিত্ব নেই)। আরও সাধারণ ক্ষেত্রে chainByকম্বিনেটরও রয়েছে। আমি বুঝতে পেরেছি যে পিসিগুলির পক্ষে উপযুক্ত নয় এমন উদাহরণ হিসাবে একটি সাধারণ পার্সিংয়ের কাজটি পাওয়া মুশকিল, তবে সত্যই তাদের পক্ষে একটি শক্ত যুক্তি রয়েছে।
স্টিভেন আর্মস্ট্রং

8

সিনট্যাক্স ত্রুটিমুক্ত থাকার গ্যারান্টিযুক্ত ইনপুটটির জন্য, বা যেখানে সিনট্যাকটিক নির্ভুলতার উপর সামগ্রিক পাস / ব্যর্থতা ঠিক আছে, পার্সার সংযুক্তকারীগুলি বিশেষত ফাংশনাল প্রোগ্রামিং ভাষাগুলিতে কাজ করার জন্য আরও সহজ। এগুলি প্রোগ্রামিং ধাঁধা, ডেটা ফাইল পড়া ইত্যাদির মতো পরিস্থিতি are

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

তবে স্বয়ংক্রিয় প্রজন্ম কেবলমাত্র এ পর্যন্ত আপনাকে পেতে পারে এবং বেশিরভাগ বাণিজ্যিক এবং দীর্ঘকালীন মুক্ত উত্স সংকলকগুলি তাদের পার্সারগুলি ম্যানুয়ালি লিখে শেষ করে। আমি মনে করি আপনি যদি এটি করতে স্বাচ্ছন্দ্য বোধ করেন তবে আপনি এই প্রশ্নটি জিজ্ঞাসা করবেন না, তাই আমি পার্সার জেনারেটরের সাথে যাওয়ার পরামর্শ দিই।


2
আপনার উত্তর করার জন্য আপনাকে ধন্যবাদ! পার্সার সংযোজকের চেয়ে পার্সার জেনারেটর ব্যবহার করে পঠনযোগ্য ত্রুটি-বার্তা তৈরি করা কেন সহজ হবে? ( আমরা কীভাবে বাস্তবায়নের বিষয়ে কথা বলছি তা নির্বিশেষে ) উদাহরণস্বরূপ, আমি জানি যে পার্সেক এবং স্পিরিট উভয়ই লাইন + কলামের তথ্য সহ ত্রুটি বার্তাগুলি মুদ্রণের জন্য কার্যকারিতা ধারণ করে, তাই পার্সার সংযুক্তকারীগুলিতেও এটি করা সম্ভব বলে মনে হয়।
কিউকিউই

এটি এমন নয় যে আপনি পার্সার সংযুক্তকারীগুলির সাথে ত্রুটি বার্তাগুলি মুদ্রণ করতে পারবেন না, আপনি যখন মিশ্রণে ত্রুটি বার্তা নিক্ষেপ করেন তখন তাদের সুবিধাগুলি কম স্পষ্ট হয়। উভয় পদ্ধতি ব্যবহার করে তুলনামূলকভাবে জটিল ব্যাকরণ করুন এবং আপনি কী বোঝাতে চাইবেন তা আপনি দেখতে পাবেন।
কার্ল বিলেফেল্ট

পার্সার সম্মিলনকারীর সাহায্যে সংজ্ঞা অনুসারে আপনি একটি ত্রুটি অবস্থায় যা কিছু পেতে পারেন তা হ'ল "এই মুহুর্তে শুরু করা, কোনও আইনি ইনপুট পাওয়া যায় নি"। এটি সত্যই আপনাকে জানায় না যে কী ভুল ছিল। তত্ত্ব অনুসারে, পৃথক পার্সাররা সেই মুহুর্তে ডেকে আনা যা আপনাকে প্রত্যাশা করেছিল তা কী বলতে পারে এবং কী খুঁজে পাবে না, তবে আপনি যা করতে পারেন তা হ'ল লুওউং ত্রুটির বার্তা তৈরি করে that
জন আর স্ট্রোহম

1
পার্সার জেনারেটরগুলি সত্যই সত্য হিসাবে তাদের ভাল ত্রুটির বার্তাগুলির জন্য সঠিকভাবে পরিচিত হয় না।
মাইলস রাউট

ডিফল্টরূপে নয়, না, তবে ভাল ত্রুটির বার্তা যুক্ত করার জন্য তাদের আরও সুবিধাজনক হুক রয়েছে।
কার্ল বিলেফেল্ট

4

এএনটিএলআর পার্সার জেনারেটরের অন্যতম রক্ষণাবেক্ষণকারী স্যাম হারওল সম্প্রতি লিখেছেন :

আমি খুঁজে পেয়েছি [সংযুক্তকারীরা] আমার চাহিদা মেটাচ্ছে না:

  1. এএনটিএলআর আমাকে অস্পষ্টতার মতো জিনিস পরিচালনার জন্য সরঞ্জাম সরবরাহ করে। বিকাশের সময় এমন সরঞ্জাম রয়েছে যা আমাকে দ্ব্যর্থক বিশ্লেষণের ফলাফলগুলি প্রদর্শন করতে পারে যাতে আমি ব্যাকরণে those অস্পষ্টতাগুলি দূর করতে পারি। রানটাইমের সময় আমি কোড সমাপ্তির মতো বৈশিষ্ট্যগুলিতে আরও সঠিক ফলাফল তৈরি করতে আইডিইতে অসম্পূর্ণ ইনপুট থেকে সৃষ্ট অস্পষ্টতা অর্জন করতে পারি।
  2. অনুশীলনে আমি দেখতে পেয়েছি পার্সার কম্বিনেটরগুলি আমার পারফরম্যান্সের লক্ষ্যগুলি পূরণের জন্য উপযুক্ত নয়। এর কিছু অংশ ফিরে যায়
  3. যখন পার্স ফলাফলগুলি রূপরেখা, কোড সমাপ্তি এবং স্মার্ট ইনডেন্টের মতো বৈশিষ্ট্যের জন্য ব্যবহৃত হয়, তখন ব্যাকরণে সূক্ষ্ম পরিবর্তনের পক্ষে সেই ফলাফলগুলির যথার্থতা প্রভাবিত করা সহজ। এএনটিএলআর এমন সরঞ্জাম সরবরাহ করে যা এই মিলগুলি মেলে সংকলন ত্রুটিতে রূপান্তর করতে পারে এমনকি এমন ধরণের ক্ষেত্রেও যখন প্রকারগুলি অন্যথায় সংকলন করে। আমি আত্মবিশ্বাসের সাথে একটি নতুন ভাষার বৈশিষ্ট্য প্রোটোটাইপ করতে পারি যা ব্যাকরণকে প্রভাবিত করে তা জেনে যে আইডিই গঠন করে এমন সমস্ত অতিরিক্ত কোড শুরু থেকেই নতুন বৈশিষ্ট্যের সম্পূর্ণ অভিজ্ঞতা সরবরাহ করবে। আমার এএনটিএলআর 4 এর কাঁটাচামচ (যা সি # টার্গেট ভিত্তিক) কেবলমাত্র এই সরঞ্জামটি সম্পর্কে জানার চেষ্টা করি যা এই বৈশিষ্ট্যটি সরবরাহ করার চেষ্টা করে।

মূলত, পার্সার কম্বিনেটরগুলি খেলতে একটি দুর্দান্ত খেলনা, তবে গুরুতর কাজ করার জন্য এগুলি সহজেই কাটা যায় না।


3

কার্ল যেমন উল্লেখ করেছেন, পার্সার জেনারেটরগুলির মধ্যে আরও ভাল ত্রুটির প্রতিবেদন রয়েছে। এছাড়াও:

  • এগুলি দ্রুততর হতে থাকে, যেহেতু উত্পন্ন কোডটি সিনট্যাক্সের জন্য বিশেষায়িত হতে পারে এবং লুক হেডের জন্য জাম্প টেবিল তৈরি করতে পারে।
  • অস্পষ্ট সিনট্যাক্স সনাক্ত করতে, বাম পুনরাবৃত্তি সরিয়ে ফেলতে, ত্রুটির শাখাগুলি পূরণ করতে, তাদের আরও ভাল সরঞ্জামাদি থাকে ing
  • তারা পুনরাবৃত্ত সংজ্ঞা ভাল পরিচালনা করতে ঝোঁক।
  • এগুলি আরও দৃ be় হতে থাকে, যেহেতু জেনারেটরগুলি দীর্ঘকাল ধরে চলেছে এবং আপনার জন্য বয়লারপ্লেটটি আরও অনেক কিছু করে, আপনার এটি চালিয়ে যাওয়ার সম্ভাবনা হ্রাস করে।

অন্যদিকে, সংযুক্তকারীদের নিজস্ব সুবিধা রয়েছে:

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

পার্সার জেনারেটরগুলির কাছে সত্যিকারের বিশ্বে ব্যবহৃত হাতের লিখিত এলএল পুনরাবৃত্ত-বংশদ্ভুত পার্সারগুলির সাথে সম্পর্কিত ভয়াবহ ত্রুটির প্রতিবেদন রয়েছে। পার্সার জেনারেটর খুব কমই দুর্দান্ত ডায়াগনস্টিক যুক্ত করতে স্টেট টেবিল ট্রানজিশন হুকগুলি সরবরাহ করে। এ কারণেই প্রায় প্রতিটি বাস্তব সংকলক পার্সার কম্বিনেটর বা পার্সার জেনারেটর ব্যবহার করে না। এলএল রিকার্সিভ-ডিসেন্ট পার্সারগুলি নির্মাণের জন্য তুচ্ছ, যদিও এটি "পরিষ্কার" পিসি / পিজি হিসাবে নয়, তারা আরও দরকারী।
hাচবিডি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.