কেন কোনও লেক্সার 2 ডি অ্যারে এবং জায়ান্ট সুইচ হিসাবে প্রয়োগ করবেন?


24

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

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

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

তাহলে চুক্তি কী? বিষয়টির সুনির্দিষ্ট বই কেন এভাবে বলছে?

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

( দ্রষ্টব্য: সম্ভাব্য সদৃশ "" জায়ান্ট স্যুইচ স্টেটমেন্টের পরিবর্তে কেন ওও পদ্ধতির ব্যবহার করবেন? "নিকটবর্তী, তবে আমি ওও সম্পর্কে যত্ন নিই না stand স্ট্যান্ডার্ডোন ফাংশন সহ একটি কার্যকরী পদ্ধতির বা এমনকি স্যানার অপরিহার্য পদ্ধতিও ভাল হবে))

এবং উদাহরণস্বরূপ, এমন একটি ভাষা বিবেচনা করুন যা কেবল সনাক্তকারী থাকে এবং সেই শনাক্তকারীরা [a-zA-Z]+। ডিএফএ বাস্তবায়নে আপনি এমন কিছু পাবেন:

private enum State
{
    Error = -1,
    Start = 0,
    IdentifierInProgress = 1,
    IdentifierDone = 2
}

private static State[][] transition = new State[][]{
    ///* Start */                  new State[]{ State.Error, State.Error (repeat until 'A'), State.IdentifierInProgress, ...
    ///* IdentifierInProgress */   new State[]{ State.IdentifierDone, State.IdentifierDone (repeat until 'A'), State.IdentifierInProgress, ...
    ///* etc. */
};

public static string NextToken(string input, int startIndex)
{
    State currentState = State.Start;
    int currentIndex = startIndex;
    while (currentIndex < input.Length)
    {
        switch (currentState)
        {
            case State.Error:
                // Whatever, example
                throw new NotImplementedException();
            case State.IdentifierDone:
                return input.Substring(startIndex, currentIndex - startIndex);
            default:
                currentState = transition[(int)currentState][input[currentIndex]];
                currentIndex++;
                break;
        }
    }

    return String.Empty;
}

(যদিও এমন কিছু যা ফাইলের শেষটি সঠিকভাবে পরিচালনা করবে)

আমি যা আশা করব তার তুলনায়:

public static string NextToken(string input, int startIndex)
{
    int currentIndex = startIndex;
    while (currentIndex < startIndex && IsLetter(input[currentIndex]))
    {
        currentIndex++;
    }

    return input.Substring(startIndex, currentIndex - startIndex);
}

public static bool IsLetter(char c)
{
    return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
}

NextTokenডিএফএ শুরু হওয়ার পরে আপনার একাধিক গন্তব্য হয়ে গেলে কোডটি তার নিজের ফাংশনে রিফ্যাক্টরেড করে।


5
একটি প্রাচীন (1977) এর ঐতিহ্য কম্পাইলার ডিজাইন মূলনীতি ? 40 বছর আগে, কোডিং শৈলী অনেক ভিন্ন ছিল
মশা

7
আপনি কীভাবে ডিএফএ রাজ্যের রূপান্তরগুলি বাস্তবায়ন করবেন? টার্মিনাল এবং নন-টার্মিনালগুলির সম্পর্কে এটি কী, "নন-টার্মিনালগুলি" সাধারণত ব্যাকরণে উত্পাদনের নিয়মকে বোঝায় যা লেক্সিকাল বিশ্লেষণের পরে আসবে ।

10
এই টেবিলগুলি মানুষের কাছে পঠনযোগ্য নয়, সেগুলি সংকলক দ্বারা ব্যবহারযোগ্য এবং খুব দ্রুত সম্পাদন করার জন্য বোঝানো হয়েছিল। ইনপুটটিতে এগিয়ে তাকানোর সময় কোনও টেবিলের চারপাশে ঝাঁপিয়ে পড়া সহজ (উদাহরণস্বরূপ, বেশিরভাগ ভাষাগুলি এড়াতে নির্মিত)।

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

7
এর সহজ উত্তর হ'ল লেক্সার সাধারণত একটি সীমাবদ্ধ রাষ্ট্রের মেশিন হিসাবে প্রয়োগ করা হয় এবং ব্যাকরণ থেকে স্বয়ংক্রিয়ভাবে উত্পন্ন হয় - এবং একটি রাষ্ট্রীয় টেবিল আশ্চর্যজনকভাবে নয়, সবচেয়ে সহজে এবং সংক্ষিপ্তভাবে একটি টেবিল হিসাবে উপস্থাপিত হয়। অবজেক্ট কোড হিসাবে, যে এটি সহজ সাথে কাজ করার জন্য মানুষের জন্য নয় কারণ মানুষের অপ্রাসঙ্গিক হবে না এটা দিয়ে কাজ; তারা উত্স পরিবর্তন করে এবং একটি নতুন উদাহরণ উত্পন্ন করে।
কেশলাম 22

উত্তর:


16

অনুশীলনে এই টেবিলগুলি নিয়মিত প্রকাশ থেকে উত্পন্ন হয় যা ভাষার টোকেন সংজ্ঞায়িত করে:

number := [digit][digit|underscore]+
reserved_word := 'if' | 'then' | 'else' | 'for' | 'while' | ...
identifier := [letter][letter|digit|underscore]*
assignment_operator := '=' | '+=' | '-=' | '*=' | '/=' 
addition_operator := '+' | '-' 
multiplication_operator := '*' | '/' | '%'
...

১৯ 197৫ সাল থেকে লেক্সটি লেখার সময় থেকেই আমাদের কাছে লেজিকাল বিশ্লেষক তৈরির উপযোগিতা রয়েছে ।

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


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

1
@ টেলাস্টিন: টেবিল চালিত ডিএফএর চেয়ে দ্রুত গতিতে যাওয়া প্রায় অসম্ভব: পরবর্তী চরিত্রটি পান, রূপান্তর টেবিলের পরবর্তী অবস্থানে সন্ধান করুন, রাষ্ট্র পরিবর্তন করুন। নতুন রাজ্যটি যদি টার্মিনাল হয় তবে একটি টোকেন নির্গত করুন। সি # বা জাভাতে কোনও অস্থায়ী স্ট্রিং তৈরির সাথে জড়িত যে কোনও পদ্ধতির ধীর গতি হবে।
কেভিন cline

@ কেভিঙ্কলাইন - নিশ্চিত, তবে আমার উদাহরণে অস্থায়ী স্ট্রিং নেই। এমনকি সিতে এটি কেবল একটি সূচক বা স্ট্রিংয়ের মধ্য দিয়ে পদক্ষেপের সূচক হবে।
টেলাস্টিন

6
@ জিমি হোফা: হ্যাঁ, সংকলকগুলিতে পারফরম্যান্স অবশ্যই প্রাসঙ্গিক। সংকলকগুলি দ্রুত কারণ তারা জাহান্নাম এবং পিছনে অনুকূলিত হয়েছে। মাইক্রো-অপ্টিমাইজেশান নয়, তারা কেবল অপ্রয়োজনীয় অস্থায়ী বস্তু তৈরি এবং তা ছাড়ার মতো অপ্রয়োজনীয় কাজ করে না। আমার অভিজ্ঞতার সাথে বেশিরভাগ বাণিজ্যিক পাঠ্য প্রক্রিয়াকরণ কোড একটি আধুনিক সংকলকটির দশমাংশ কাজ করে এবং এটি করতে দশ বার সময় লাগে। আপনি যখন একটি গিগাবাইট পাঠ্য প্রক্রিয়াকরণ করছেন তখন পারফরম্যান্স বিশাল।
কেভিন cline

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

7

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

আপনার কোডটি কারও হাতে লিখিত ডিএফএ বজায় রাখার জন্য পরিষ্কার, তবে শেখানো ধারণাগুলি থেকে কিছুটা দূরে সরিয়ে দেওয়া হয়েছে।


7

এর অভ্যন্তরীণ লুপ:

                currentState = transition[(int)currentState][input[currentIndex]];
                currentIndex++;
                break;

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

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


5

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

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


2

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

অনেক মন্তব্য সত্ত্বেও, 40 এর দশকে, 50 এর দশকে, 60 এর দশকের কোডের স্টাইলের সাথে এর কোনও সম্পর্ক নেই, এটি সরঞ্জামগুলি আপনার জন্য কী করছে এবং আপনার কী আছে তার ব্যবহারিক বোঝাপড়া অর্জনের সাথে এটি করতে হবে তাদের কাজ করতে করতে। তাত্ত্বিক এবং ব্যবহারিক দৃষ্টিকোণ থেকে সংকলকরা কীভাবে কাজ করে তা মৌলিক বোঝার সাথে এর সবকিছু করার আছে।

আশা করি, আপনার প্রশিক্ষক আপনাকে লেকস এবং ইয়্যাকও ব্যবহার করতে দেবেন (যদি না এটি স্নাতক স্তরের শ্রেণি না হয় এবং আপনি লেক্স এবং ইয়্যাক লিখতে না পারেন)।


0

পার্টিতে দেরীতে :-) টোকেনগুলি নিয়মিত প্রকাশের সাথে মিলছে। যেহেতু তাদের মধ্যে অনেকগুলি রয়েছে, আপনার কাছে মাল্টি রিজেেক্স ইঞ্জিন রয়েছে, যার ফলস্বরূপ দৈত্য ডিএফএ।

"আরও খারাপ কথা, ভাষাটি ইউটিএফ সক্ষম হলে এটি কীভাবে দূরবর্তী বাস্তব হতে পারে তা আমি দেখতে পাচ্ছি না।"

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

সুতরাং, পুরো লেসারের জন্য আপনার একক ডিএফএ (যা মাল্টি-রেজেক্স)। 2d অ্যারের চেয়ে এটি আরও কত ভাল লিখবেন?

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