নিজস্ব ভাষায় একটি সংকলক লিখছেন


204

স্বজ্ঞাতভাবে মনে হয়, ভাষার একটি সংকলক Fooনিজেই ফুতে লেখা যায় না। আরও সুনির্দিষ্টভাবে বলতে গেলে ভাষার জন্য প্রথম সংকলক Fooফুতে লেখা যায় না, তবে পরবর্তী কোনও সংকলকও এর জন্য লেখা যেতে পারে Foo

তবে এটি কি সত্য? এমন একটি ভাষা সম্পর্কে আমার কিছু অস্পষ্ট স্মৃতি আছে যাঁর প্রথম সংকলক "নিজেই" লেখা হয়েছিল। এটি কি সম্ভব, আর যদি হয় তবে কীভাবে?



এটি খুব পুরানো প্রশ্ন, তবে বলুন আমি জাভা ভাষায় ফু ভাষার জন্য একজন অনুবাদক লিখেছিলাম। তারপরে ভাষা ফু দিয়ে আমি লিখেছিলাম এটির নিজস্ব অনুবাদক। ফু এখনও জেআরই ঠিক লাগবে?
জর্জ জাভিয়ার

উত্তর:


231

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

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

এর উদাহরণ হ'ল স্কেলা। এর প্রথম সংকলক মার্টিন ওডারস্কির একটি পরীক্ষামূলক ভাষা পিজ্জাতে তৈরি হয়েছিল। সংস্করণ ২.০ হিসাবে, সংকলকটি সম্পূর্ণরূপে স্কালায় পুনরায় লেখা হয়েছিল। সেদিক থেকে, নতুন স্কালা সংকলক ভবিষ্যতের পুনরাবৃত্তির জন্য নিজেকে সংকলন করতে ব্যবহৃত হতে পারার কারণে পুরানো পিজা সংকলকটি পুরোপুরি ফেলে দেওয়া যেতে পারে।


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

2
@ পিয়ারটনি সাধারণত নতুন মাইক্রোপ্রসেসরের কাছে কেবল কম্পাইলার ব্যাকএন্ড পুনরুদ্ধার করা সহজ হবে।
bstpierre


76

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


জেনেসিস ট্রানজিস্টর থেকে প্রচুর হাত দিয়ে সবকিছু বুটস্ট্র্যাপ করা আছে

47

পূর্বের উত্তরে কৌতূহল যোগ করা।

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

make bootstrap

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

'বুটস্ট্র্যাপ' টার্গেটের সেই ব্যবহারটি এই লক্ষ্য দ্বারা অনুপ্রাণিত হয় যে টার্গেট সিস্টেমের সরঞ্জামচেইনটি তৈরি করতে যে সংকলকটি ব্যবহার করে তা লক্ষ্য সংকলকটির খুব একই সংস্করণ নাও থাকতে পারে। সেই পথে অগ্রসর হওয়া নিশ্চিত লক্ষ্য লক্ষ্য সিস্টেমে একটি সংকলক যা নিজেই সংকলন করতে পারে।


12
"আপনাকে টার্গেট সিস্টেমের প্রতিটি বাইনারি সত্যই সংকলন করতে হবে" এবং তবুও আপনাকে কোথাও থেকে পাওয়া একটি সিসি বাইনারি দিয়ে শুরু করতে হবে, কারণ উত্স নিজেই সংকলন করতে পারে না। আমি অবাক হয়েছি আপনি যদি প্রতিটি জিসিসি বাইনারি ব্যবহার করেন যা প্রতিটি ধারাবাহিক জিসিসি পুনরায় সংকলনের জন্য ব্যবহৃত হয়, আপনি কি কে ও আর এর মূল সি সংকলকটি ফিরে পাবেন?
রব্রু

43

আপনি যখন সি এর জন্য প্রথম সংকলক লিখেন, আপনি এটি অন্য কোনও ভাষায় লিখবেন। এখন, আপনার কাছে সি-এর জন্য একটি সংকলক রয়েছে, বলুন, এসেম্বেলার। অবশেষে, আপনি সেই জায়গায় এসে পৌঁছে যাবেন যেখানে স্ট্রিংগুলি বিশ্লেষণ করতে হবে, বিশেষত ক্রমগুলি এড়ানোর জন্য। \nদশমিক কোড 10 (এবং \r13, ইত্যাদি) দিয়ে অক্ষরে রূপান্তর করতে আপনি কোড লিখবেন ।

এই সংকলক প্রস্তুত হওয়ার পরে, আপনি এটিকে পুনরায় সিদ্ধ করতে শুরু করবেন এই প্রক্রিয়াটিকে " বুটস্ট্র্যাপিং " বলা হয় " ।

স্ট্রিং পার্সিং কোডটি হয়ে যাবে:

...
if (c == 92) { // backslash
    c = getc();
    if (c == 110) { // n
        return 10;
    } else if (c == 92) { // another backslash
        return 92;
    } else {
        ...
    }
}
...

যখন এটি সংকলন করে, আপনার একটি বাইনারি থাকে যা '\ n' বোঝে। এর অর্থ আপনি উত্স কোডটি পরিবর্তন করতে পারেন:

...
if (c == '\\') {
    c = getc();
    if (c == 'n') {
        return '\n';
    } else if (c == '\\') {
        return '\\';
    } else {
        ...
    }
}
...

সুতরাং 13 for n এর কোডটি \ n 'র তথ্যটি কোথায়? এটা বাইনারি হয়! এটি ডিএনএর মতো: এই বাইনারি সহ সি উত্স কোড সংকলন এই তথ্যের উত্তরাধিকারী হবে। যদি সংকলক নিজেই সংকলন করে, তবে এটি এই জ্ঞানটিকে তার বংশে পৌঁছে দেবে। এই দিক থেকে, সংকলকটি কী করবে তা উত্স থেকে একা দেখার কোনও উপায় নেই।

আপনি যদি কোনও প্রোগ্রামের উত্সটিতে কোনও ভাইরাস আড়াল করতে চান তবে আপনি এটি এটি করতে পারেন: একটি সংকলকটির উত্স পান, ফাংশন সংকলন করে এমন ফাংশনটি সন্ধান করুন এবং এটির সাথে এটি প্রতিস্থাপন করুন:

void compileFunction(char * name, char * filename, char * code) {
    if (strcmp("compileFunction", name) == 0 && strcmp("compile.c", filename) == 0) {
        code = A;
    } else if (strcmp("xxx", name) == 0 && strcmp("yyy.c", filename) == 0) {
        code = B;
    }

    ... code to compile the function body from the string in "code" ...
}

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

আমাদের ফাংশনটি আমরা আমাদের ভাইরাস দ্বারা প্রতিস্থাপন করতে চাই তার জন্য বি একই is উদাহরণস্বরূপ, এটি উত্স ফাইল "login.c" এ "লগইন" ফাংশন হতে পারে যা সম্ভবত লিনাক্স কার্নেলের থেকে। আমরা এটিকে এমন একটি সংস্করণ দিয়ে প্রতিস্থাপন করতে পারি যা সাধারণ পাসওয়ার্ডের পাশাপাশি রুট অ্যাকাউন্টের জন্য "জোশুয়া" পাসওয়ার্ড গ্রহণ করবে।

যদি আপনি এটি সংকলন করেন এবং এটি বাইনারি হিসাবে ছড়িয়ে দেন তবে উত্সটি দেখে ভাইরাসটি খুঁজে পাওয়ার কোনও উপায় থাকবে না।

ধারণার মূল উত্স: https://web.archive.org/web/20070714062657/http://www.acm.org/classics/sep95/


1
ভাইরাস সংক্রামিত সংকলক লেখার বিষয়ে দ্বিতীয়ার অর্ধেকটি কী? :)
mhvelplund

3
@ এমভেলপ্লুন্ড কীভাবে বুটস্ট্র্যাপিং আপনাকে মারতে পারে তা এই জ্ঞানটি ছড়িয়ে দিন।
অ্যারন দিগুল্লা

19

আপনি নিজেই একটি সংকলক লিখতে পারবেন না কারণ আপনার প্রারম্ভিক উত্স কোডটি সংকলন করার মতো কিছুই আপনার কাছে নেই। এটি সমাধান করার জন্য দুটি পন্থা রয়েছে।

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

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

একটি সামান্য পরিচিত ঘটনাটি হ'ল জিএনইউ সি ++ সংকলকটির একটি বাস্তবায়ন রয়েছে যা কেবল সি সাবসেট ব্যবহার করে। এটির কারণটি সাধারণত একটি নতুন টার্গেট মেশিনের জন্য সি সংকলক সন্ধান করা সহজ যা আপনাকে এর থেকে সম্পূর্ণ GNU সি ++ সংকলক তৈরি করতে দেয় allows আপনি এখন টার্গেট মেশিনে সি ++ কম্পাইলার লাগানোর জন্য নিজেকে বুট করেছেন।


14

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

"মনো" থেকে আমি যা মনে করি, সেগুলি থেকে সম্ভবত এটির কাজটি করার জন্য তাদের কয়েকটি জিনিসকে প্রতিবিম্বিত করার প্রয়োজন হবে: মনো দলটি ইশারা করে বলে যে কিছু জিনিস সহজেই সম্ভব নয় Reflection.Emit; অবশ্যই, এমএস দল তাদের ভুল প্রমাণ করতে পারে।

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

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


আপডেট 1

আমি স্রেফ পিডিসিতে অ্যান্ডারসের এই ভিডিওটি দেখেছি এবং (প্রায় এক ঘন্টার মধ্যে) সে আরও অনেক বেশি বৈধ কারণ দেয় - সমস্ত পরিষেবা হিসাবে সংকলক সম্পর্কে। শুধু মাত্র নথির জন্য.


4

এখানে একটি ডাম্প (আসলে অনুসন্ধান করা কঠিন বিষয়):

এই ধারণা হয় PyPy এবং Rubinius :

(আমি মনে করি এটি ফোরথের ক্ষেত্রেও প্রযোজ্য হতে পারে তবে আমি ফোর্থ সম্পর্কে কিছুই জানি না))


একটি স্মৃতিসৌধ সম্পর্কিত সম্পর্কিত একটি নিবন্ধের প্রথম লিঙ্কটি আপাত দরকারী এবং তাত্ক্ষণিক তথ্য ছাড়াই বর্তমানে কোনও পৃষ্ঠায় নির্দেশ করছে।
এনবিরো

1

জিএনএটি, জিএনইউ অ্যাডা সংকলক, পুরোপুরি নির্মিত হওয়ার জন্য একটি অ্যাডা সংকলক প্রয়োজন। প্ল্যাটফর্মে পোর্ট করার সময় এটি কোনও ব্যথা হতে পারে যেখানে কোনও জিএনএটি বাইনারি সহজেই পাওয়া যায় না।


1
আমি দেখছি না কেন? আপনার একবারে একাধিকবার বুটস্ট্র্যাপ করতে হবে এমন কোনও নিয়ম নেই (প্রতিটি নতুন প্ল্যাটফর্মের মতো), আপনি একটি বর্তমানের সাথে ক্রসকমপাইলও করতে পারেন।
মার্কো ভ্যান ডি ভুর্ট

1

প্রকৃতপক্ষে, বেশিরভাগ সংকলক উপরে বর্ণিত কারণগুলির জন্য তারা সংকলিত ভাষায় লিখিত।

প্রথম বুটস্ট্র্যাপ সংকলক সাধারণত সি, সি ++ বা সমাবেশে লেখা হয়।


1

মনো প্রকল্প সি # সংকলক দীর্ঘদিন ধরে "স্ব-হোস্টেড" হয়ে আসছে, এর অর্থ কী এটি নিজে সি # তে লিখিত হয়েছে।

আমি জানি যে সংকলকটি খাঁটি সি কোড হিসাবে শুরু হয়েছিল, তবে ইসিএমএর "বেসিক" বৈশিষ্ট্যগুলি প্রয়োগ করার পরে তারা সি # তে সংকলকটি পুনরায় লিখতে শুরু করেছিল।

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

আপনি এখানে আরও তথ্য পেতে পারেন ।


1

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

  • সিনট্যাক্স পার্সার প্রোগ্রামিং ল্যাঙ্গুয়েজ পিপিএল
  • জেনারেটর এলআইএসপি 2 ভিত্তিক ট্রি ক্রলিং পিএসইউডো কোড উত্পন্ন ভাষা
  • আইএসও ইন সিকোয়েন্স, পিএসইউডো কোড, অনুকূলিতকরণের ভাষা
  • পিএসইউডো ম্যাক্রোর মতো এসেম্বলি কোড উত্পাদনকারী ভাষা।
  • ভাষা নির্ধারণকারী MACHOP সমাবেশ-মেশিনের নির্দেশ।

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

এলআইএসপি 2 টি গাছ এবং তালিকা

এলআইএসপি 2 ভিত্তিক জেনারেটর ভাষার গতিশীল মেমরি পরিচালন ব্যবস্থা একটি মূল উপাদান। বর্গাকার বন্ধনীতে অন্তর্ভুক্ত ভাষায় তালিকা প্রকাশ করা হয়, এর উপাদানগুলি কমা দ্বারা পৃথক করা হয়েছে অর্থাৎ একটি তিনটি উপাদান [ক, খ, সি] তালিকা।

গাছ:

     ADD
    /   \
  MPY     3
 /   \
5     x

তালিকা দ্বারা প্রতিনিধিত্ব করা হয় যার প্রথম এন্ট্রি নোড অবজেক্ট:

[ADD,[MPY,5,x],3]

গাছগুলি সাধারণত শাখাগুলির পূর্ববর্তী নোডের সাথে প্রদর্শিত হয়:

ADD[MPY[5,x],3]

এলআইএসপি 2 ভিত্তিক জেনারেটর ফাংশনগুলির সাথে আনপারসিং করা

একটি জেনারেটর ফাংশন হ'ল (আনপারস) => ক্রিয়া> জোড়গুলির একটি নামযুক্ত সেট ...

<NAME>(<unparse>)=><action>;
      (<unparse>)=><action>;
            ...
      (<unparse>)=><action>;

আনপারস এক্সপ্রেশন হ'ল টেস্টগুলি যা গাছের নিদর্শনগুলির সাথে মেলে এবং / অথবা অবজেক্টের ধরণের সাথে তাদের আলাদা করে দেয় এবং সেই অংশগুলি স্থানীয় ভেরিয়েবলগুলিকে এর পদ্ধতিগত ক্রিয়া দ্বারা প্রক্রিয়াভুক্ত করার জন্য নির্ধারণ করে assign বিভিন্ন ধরনের আর্গুমেন্টের ধরণের ওভারলোড হওয়া ফাংশনের মতো। () => ... ব্যতীত কোডগুলি অর্ডারে পরীক্ষার চেষ্টা করা হয়। এর সাথে সম্পর্কিত ক্রিয়াকলাপ সম্পাদন করে প্রথম সফল আনসারস করা। অপসারণমূলক এক্সপ্রেশনগুলি পরীক্ষাগুলিকে বিচ্ছিন্ন করে দিচ্ছে। ADD [x, y] একটি দুটি শাখা ADD ট্রি এর সাথে মিলে যা তার শাখাগুলি স্থানীয় ভেরিয়েবলগুলিতে x এবং y প্রদান করে। ক্রিয়াটি একটি সাধারণ অভিব্যক্তি বা একটি .BEGIN ... .end সীমিত কোড ব্লক হতে পারে। আমি আজ সি স্টাইল {...} ব্লক ব্যবহার করব। গাছের সাথে মিলে যাওয়া, [], আনপসার করা নিয়মগুলি জেনারেটরকে কলমে ফিরে আসা ফলাফল (গুলি) পাস করতে কল করতে পারে:

expr_gen(ADD[expr_gen(x),expr_gen(y)])=> x+y;

বিশেষত উপরের expr_gen আনসারস দুটি শাখা ADD গাছের সাথে মেলে। পরীক্ষার প্যাটার্নের মধ্যে একটি শাখার সাথে একটি গাছের শাখায় রাখা একক যুক্তি জেনারেটরকে ডাকা হবে। এটির আর্গুমেন্ট তালিকা যদিও স্থানীয় ভেরিয়েবলগুলি নির্ধারিত ফেরত বস্তু। আনপার্সের উপরে একটি দুটি শাখা নির্দিষ্ট করে যা গাছের বিযুক্তি বিচ্ছিন্ন করে, প্রতিটি শাখাকে এক্সপ্র_জেনে পুনরাবৃত্ত করে। বাম শাখাটি স্থানীয় ভেরিয়েবলের মধ্যে রেখে দেওয়া হবে x একইভাবে ডান শাখাটি y রিটার্ন অবজেক্টের সাথে expr_gen এ চলে গেছে। উপরেরটি একটি সংখ্যার এক্সপ্রেশন মূল্যায়নের অংশ হতে পারে। শর্টকাট বৈশিষ্ট্যগুলি ছিল যা ভেক্টরগুলি নোড স্ট্রিংয়ের পরিবর্তে উপরেরটিতে ছিল নোডের একটি ভেক্টর সংশ্লিষ্ট ক্রিয়াকলাপের ভেক্টরের সাথে ব্যবহার করা যেতে পারে:

expr_gen(#node[expr_gen(x),expr_gen(y)])=> #action;

  node:   ADD, SUB, MPY, DIV;
  action: x+y, x-y, x*y, x/y;

        (NUMBER(x))=> x;
        (SYMBOL(x))=> val:(x);

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

প্রতীক এবং প্রতীক বৈশিষ্ট্য

প্রতীকগুলির বৈশিষ্ট্যগুলির নাম থাকতে পারে। ভাল: (x) এক্স মধ্যে থাকা প্রতীক অবজেক্টের ভাল বৈশিষ্ট্য অ্যাক্সেস করুন। একটি সাধারণীকৃত প্রতীক টেবিল স্ট্যাক এসএলিকের অংশ। SYMBOL টেবিলটি ধাক্কা দেওয়া এবং ফাংশনগুলির জন্য স্থানীয় প্রতীকগুলি সরবরাহ করে পপ করা যেতে পারে। সদ্য নির্মিত প্রতীক শীর্ষ প্রতীক সারণীতে ক্যাটালোজ করা হয়েছে। সিম্বল সন্ধানটি শীর্ষ সারণী থেকে প্রথমে স্ট্যাকের নিচে পিছনে প্রতীক টেবিল স্ট্যাকটি সন্ধান করে।

উত্পাদনের মেশিন স্বাধীন কোড

এস এল আই সি এর জেনারেটর ল্যাঙ্গুয়েজ PSEUDO নির্দেশিক বস্তু উত্পাদন করে, সেগুলি একটি বিভাগ কোড তালিকায় যুক্ত করে। .FLUSH তার পিএসইউডো কোড তালিকাটি প্রতিটি পিএসইউডো নির্দেশকে তালিকা থেকে সরানো এবং কল করার জন্য চালিত করে। মৃত্যুদন্ড কার্যকর করার পরে একটি পিএসইইউডো অবজেক্ট মেমরি প্রকাশিত হয়। পিএসইইউডিও এবং জেনেরেটর ক্রিয়াকলাপগুলির মূল সংস্থাটি তাদের আউটপুট বাদে মূলত একই ভাষা। পিএসইইউডো বলতে মেশিনকে স্বতন্ত্র কোড সিক্যুয়ালাইজেশন সরবরাহকারী সমাবেশ ম্যাক্রো হিসাবে কাজ করা বোঝায়। তারা গাছের ক্রলিং জেনারেটরের ভাষার বাইরে নির্দিষ্ট লক্ষ্য মেশিনের আলাদাকরণ সরবরাহ করে। পিএসইউডোগুলি আউটপুট মেশিন কোডে MACHOP ফাংশন কল করে। ম্যাকপগুলি এসেম্বলি সিউডো অপ্স (যেমন ডিসি, ধ্রুবক ইত্যাদি সংজ্ঞায়িত) সংজ্ঞায়িত করতে ব্যবহৃত হয় এবং মেশিনের নির্দেশাবলী বা ভেক্টর এন্ট্রি ব্যবহার করে ফর্ম্যাটেড নির্দেশের মতো একটি পরিবার। তারা কেবল তাদের পরামিতিগুলি নির্দেশাবলী তৈরি করে বিট ফিল্ডগুলির ক্রমে রূপান্তরিত করে। ম্যাকপ কলগুলি এসেম্বলির মতো দেখতে এবং ক্ষেত্রগুলির মুদ্রণ ফর্ম্যাটিং প্রদানের জন্য যখন সংকলন তালিকাতে সমাবেশ প্রদর্শিত হয় assembly উদাহরণ কোডে আমি সি স্টাইল মন্তব্য ব্যবহার করছি যা সহজেই যুক্ত হতে পারে তবে মূল ভাষায় ছিল না। ম্যাকপগুলি কিছুটা ঠিকানার যোগ্য মেমরিতে কোড তৈরি করছে। এসএলিক লিঙ্কার সংকলকটির আউটপুট পরিচালনা করে। ভেক্টর এন্ট্রি ব্যবহার করে DEC-10 ব্যবহারকারী মোডের নির্দেশাবলীর জন্য একটি ম্যাচপপ: ম্যাকপগুলি কিছুটা ঠিকানার যোগ্য মেমরিতে কোড তৈরি করছে। এসএলিক লিঙ্কার সংকলকটির আউটপুট পরিচালনা করে। ভেক্টর এন্ট্রি ব্যবহার করে DEC-10 ব্যবহারকারী মোডের নির্দেশাবলীর জন্য একটি ম্যাচপপ: ম্যাকপগুলি কিছুটা ঠিকানার যোগ্য মেমরিতে কোড তৈরি করছে। এসএলিক লিঙ্কার সংকলকটির আউটপুট পরিচালনা করে। ভেক্টর এন্ট্রি ব্যবহার করে DEC-10 ব্যবহারকারী মোডের নির্দেশাবলীর জন্য একটি ম্যাচপপ:

.MACHOP #opnm register,@indirect offset (index): // Instruction's parameters.
.MORG 36, O(18): $/36; // Align to 36 bit boundary print format: 18 bit octal $/36
O(9):  #opcd;          // Op code 9 bit octal print out
 (4):  register;       // 4 bit register field appended print
 (1):  indirect;       // 1 bit appended print
 (4):  index;          // 4 bit index register appended print
O(18): if (#opcd&&3==1) offset // immediate mode use value else
       else offset/36;         // memory address divide by 36
                               // to get word address.
// Vectored entry opcode table:
#opnm := MOVE, MOVEI, MOVEM, MOVES, MOVS, MOVSI, MOVSM, MOVSS,
         MOVN, MOVNI, MOVNM, MOVNS, MOVM, MOVMI, MOVMM, MOVMS,
         IMUL, IMULI, IMULM, IMULB, MUL,  MULI,  MULM,  MULB,
                           ...
         TDO,  TSO,   TDOE,  TSOE,  TDOA, TSOA,  TDON,  TSON;
// corresponding opcode value:
#opcd := 0O200, 0O201, 0O202, 0O203, 0O204, 0O205, 0O206, 0O207,
         0O210, 0O211, 0O212, 0O213, 0O214, 0O215, 0O216, 0O217,
         0O220, 0O221, 0O222, 0O223, 0O224, 0O225, 0O226, 0O227,
                           ...
         0O670, 0O671, 0O672, 0O673, 0O674, 0O675, 0O676, 0O677;

.MORG 36, O (18): $ / 36; অক্টালে 18 বিটের শব্দ ঠিকানা printing / 36 শব্দ ঠিকানা মুদ্রণ করে একটি 36 বিট সীমানায় অবস্থানটি সারিবদ্ধ করে। 9 বিট অপসিডি, 4 বিট রেজিস্টার, পরোক্ষ বিট এবং 4 বিট সূচক রেজিস্ট্রার একত্রিত হয়ে মুদ্রিত হয় যেন একক 18 বিট ক্ষেত্র। 18 বিটের ঠিকানা / 36 বা তাত্ক্ষণিক মানটি আউটপুট এবং অষ্টালে মুদ্রিত। একটি মুভি উদাহরণ r1 = 1 এবং r2 = 2 দিয়ে মুদ্রণ করে:

400020 201082 000005            MOVEI r1,5(r2)

সংকলক সমাবেশ বিকল্পের সাহায্যে আপনি সংকলনের তালিকায় উত্পন্ন সমাবেশ কোড পাবেন।

এটি একসাথে লিঙ্ক করুন

SLIC লিঙ্কারটি একটি লাইব্রেরি হিসাবে সরবরাহ করা হয় যা লিঙ্কিং এবং প্রতীক রেজোলিউশনগুলি পরিচালনা করে। টার্গেট নির্দিষ্ট আউটপুট লোড ফাইল ফর্ম্যাটিং যদিও লক্ষ্য মেশিনের জন্য লিখিত এবং লিঙ্কার লাইব্রেরি লাইব্রেরির সাথে লিঙ্ক করা আবশ্যক।

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

কোড উত্পন্নকরণ এবং উত্সগুলির সংক্ষিপ্তসার

আমি প্রথমে কোড জেনারেশনটি পেরিয়ে গিয়েছি তা বোঝার জন্য যে এসএলআইসি একটি সত্য সংকলক সংকলক ছিল। এসআইএলসি 1960 এর দশকের শেষদিকে সিস্টেম ডেভলপমেন্ট কর্পোরেশনে সিডব্লিউআইসি (লেখার জন্য রচনা ও প্রয়োগকারী সংকলক) দ্বারা অনুপ্রাণিত হয়েছিল। সিডব্লিউআইসির কেবল জেনেরেটর ভাষার বাইরে সাইনট্যাক্স এবং জেনেরেটর ভাষার সংখ্যা ছিল by বাইট কোডটি নামযুক্ত বিভাগগুলির সাথে সম্পর্কিত এবং একটি .FLUSH বিবৃতি দ্বারা লিখিত মেমরি বাফারগুলিতে (CWICs ডকুমেন্টেশনে ব্যবহৃত শব্দটি) লাগানো বা লাগানো হয়েছিল। সিডব্লিউআইসিতে একটি এসিএম পেপার এসিএম সংরক্ষণাগার থেকে পাওয়া যায়।

একটি বড় প্রোগ্রামিং ভাষা সফলভাবে প্রয়োগ করা হয়েছে

১৯ 1970০ এর দশকের শেষের দিকে এসএলিক একটি কোবল ক্রস সংকলক লিখতে ব্যবহৃত হত। প্রায় এক মাসে বেশিরভাগ একক প্রোগ্রামার দ্বারা সম্পন্ন। আমি প্রোগ্রামারটির সাথে প্রয়োজন মতো কিছুটা কাজ করেছি। অন্য একজন প্রগতিবিদ লক্ষ্য টিআই -990 মিনি-কম্পিউটারের জন্য রানটাইম লাইব্রেরি এবং ম্যাকপস লিখেছিলেন। এই COBOL সংকলকটি প্রতি সেকেন্ডে উল্লেখযোগ্য পরিমাণে আরও বেশি লাইন সংকলন করে তারপর ডিসি -10 নেটিভ COBOL সংকলকটি সমাবেশে লিখিত।

একটি সংকলক আরও সাধারণত সম্পর্কে কথা বলা

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

আমি মনে করি যে আমি প্রতিষ্ঠিত করেছি যে এগুলি পার্সার জেনারেটর ছিল না। সুতরাং এখন পিছনের প্রান্তটি সম্পর্কে কিছুটা বোঝার সাথে আমি পার্সার প্রোগ্রামিং ভাষাটি ব্যাখ্যা করতে পারি।

পার্সার প্রোগ্রামিং ভাষা

পার্সারটি সাধারণ সমীকরণের আকারে লিখিত সূত্র ব্যবহার করে লেখা হয়।

<name> <formula type operator> <expression> ;

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

/*  Character Class Formula                                    class_mask */
bin: '0'|'1';                                                // 0b00000010
oct: bin|'2'|'3'|'4'|'5'|'6'|'7';                            // 0b00000110
dgt: oct|'8'|'9';                                            // 0b00001110
hex: dgt|'A'|'B'|'C'|'D'|'E'|'F'|'a'|'b'|'c'|'d'|'e'|'f';    // 0b00011110
upr:  'A'|'B'|'C'|'D'|'E'|'F'|'G'|'H'|'I'|'J'|'K'|'L'|'M'|
      'N'|'O'|'P'|'Q'|'R'|'S'|'T'|'U'|'V'|'W'|'X'|'Y'|'Z';   // 0b00100000
lwr:  'a'|'b'|'c'|'d'|'e'|'f'|'g'|'h'|'i'|'j'|'k'|'l'|'m'|
      'n'|'o'|'p'|'q'|'r'|'s'|'t'|'u'|'v'|'w'|'x'|'y'|'z';   // 0b01000000
alpha:  upr|lwr;                                             // 0b01100000
alphanum: alpha|dgt;                                         // 0b01101110

Skip_class 0b00000001 পূর্বনির্ধারিত তবে আড়াআড়ি স্কিপ_ক্লাসটি সংজ্ঞায়িত করা হতে পারে।

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

test    byte ptr [eax+_classmap],dgt

এর পরে একটি:

jne      <success>

অথবা

je       <failure>

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

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

string .. (''' .ANY ''' | '"' $(-"""" .ANY | """""","""") '"') MAKSTR[];

প্রথম বিকল্পটি কোনও একক উদ্ধৃতিযুক্ত উদ্ধৃত অক্ষরের সাথে মেলে। ডান বিকল্পটি একটি ডাবল উদ্ধৃতি উদ্ধৃত স্ট্রিংয়ের সাথে মেলে যা একক "অক্ষরকে উপস্থাপন করতে দুটি" অক্ষর একসাথে ব্যবহার করে ডাবল উদ্ধৃতি অক্ষর অন্তর্ভুক্ত করতে পারে। এই সূত্রটি তার নিজস্ব সংজ্ঞায় ব্যবহৃত স্ট্রিংগুলি সংজ্ঞায়িত করে। অভ্যন্তরীণ ডান বিকল্প '' '$ (- "" ""। ANY | "" "" "" "" "") "" "একটি ডাবল উদ্ধৃতি উদ্ধৃত স্ট্রিংয়ের সাথে মেলে। ডাবল উদ্ধৃতি "চরিত্রের সাথে মেলে আমরা একটি একক 'উদ্ধৃত অক্ষর ব্যবহার করতে পারি However তবে ডাবল" উদ্ধৃত স্ট্রিংয়ের মধ্যে যদি আমরা একটি "অক্ষর ব্যবহার করতে চাই তবে একটি পেতে দুটি অক্ষর অবশ্যই ব্যবহার করতে হবে"। উদাহরণস্বরূপ অভ্যন্তরীণ বাম বিকল্পে কোনও উদ্ধৃতি ব্যতীত অন্য কোনও অক্ষরের সাথে মেলে:

-"""" .ANY

একটি নেতিবাচক উঁকি দেওয়া - "" "" ব্যবহৃত হয় যে যখন সফল (একটি "চরিত্রের সাথে মেলে না) তখন মেলে AN সঠিক বিকল্পটি গ্রহণ করা হচ্ছে - "" "" "একটি" চরিত্রের সাথে মেলে এবং ব্যর্থ হ'ল সঠিক বিকল্প ছিল:

"""""",""""

দুটি "অক্ষরকে তাদের পরিবর্তে একক ডাবল" দিয়ে প্রতিস্থাপন করার চেষ্টা করে "একক" অক্ষর সন্নিবেশ করানোর জন্য "" "" ব্যবহার করা হয়। সমাপ্ত স্ট্রিং উদ্ধৃতি অক্ষরটি ব্যর্থ হওয়া উভয় অভ্যন্তরীণ বিকল্প মিলে যায় এবং ম্যাকআরসিআরটি [] একটি স্ট্রিং অবজেক্ট তৈরি করার জন্য ডাকা হয় $ $ সিক্যুয়েন্স, লুপটি সফল হওয়ার পরে, অপারেটরটি একটি সিকোয়েন্স মেলানোর ক্ষেত্রে ব্যবহৃত হয় Tok টোকন সূত্রটি স্কিপ শ্রেণীর অক্ষরগুলি (ঝকঝকে স্থান) ছেড়ে দিন .এখন প্রথম ম্যাচটি তৈরি হয়ে গেলে স্কিপ_ক্লাস বাদ দেওয়া অক্ষম হয়ে যায় using আমরা অন্যান্য ভাষায় প্রগ্রেড ফাংশনগুলি কল করতে পারি []। [], ম্যাকবিন [], মাকোকট [], ম্যাকএক্সএক্স [], ম্যাকফ্লাট [], এবং ম্যাকিন্ট [] সরবরাহ করা লাইব্রেরির ফাংশন যা একটি ম্যাচযুক্ত টোকেন স্ট্রিংকে একটি টাইপ করা বস্তুতে রূপান্তর করে below নীচের সংখ্যা সূত্রটি বেশ জটিল টোকেন স্বীকৃতি চিত্রিত করে:

number .. "0B" bin $bin MAKBIN[]        // binary integer
         |"0O" oct $oct MAKOCT[]        // octal integer
         |("0H"|"0X") hex $hex MAKHEX[] // hexadecimal integer
// look for decimal number determining if integer or floating point.
         | ('+'|+'-'|--)                // only - matters
           dgt $dgt                     // integer part
           ( +'.' $dgt                  // fractional part?
              ((+'E'|'e','E')           // exponent  part
               ('+'|+'-'|--)            // Only negative matters
               dgt(dgt(dgt|--)|--)|--)  // 1 2 or 3 digit exponent
             MAKFLOAT[] )               // floating point
           MAKINT[];                    // decimal integer

উপরের নম্বর টোকেন সূত্রটি পূর্ণসংখ্যার এবং ভাসমান পয়েন্ট সংখ্যাগুলি স্বীকৃতি দেয়। বিকল্পগুলি সর্বদা সফল। অঙ্কগুলিতে অঙ্কের জিনিসগুলি ব্যবহার করা যেতে পারে। সূত্রের সাফল্যের সাথে টোকেন বস্তুগুলি পার্স স্ট্যাকের উপরে ঠেলাঠেলি করা হয়। (+ 'E' | 'ই', 'ই') এর ব্যয়কারী সীসা আকর্ষণীয়। আমরা সর্বদা MAKEFLOAT [] এর জন্য একটি বড় হাতের ই রাখতে চাই। তবে আমরা 'E' ব্যবহার করে এটির পরিবর্তে একটি ছোট কেসকে 'ই' অনুমতি দিই।

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

(a b | c d)\ e

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

পার্সার ভাষা কোনও এলএল বা এলআর পার্সার নয়। তবে একটি পুনরাবৃত্তিমূলক শালীন পার্সার লেখার জন্য একটি প্রোগ্রামিং ল্যাঙ্গুয়েজ যেখানে আপনি গাছের নির্মাণের প্রোগ্রাম করছেন:

:<node name> creates a node object and pushes it onto the node stack.
..           Token formula create token objects and push them onto 
             the parse stack.
!<number>    pops the top node object and top <number> of parstack 
             entries into a list representation of the tree. The 
             tree then pushed onto the parse stack.
+[ ... ]+    creates a list of the parse stack entries created 
             between them:
              '(' +[argument $(',' argument]+ ')'
             could parse an argument list. into a list.

একটি সাধারণ ব্যবহৃত পার্সিং উদাহরণ হ'ল পাটিগণিতের বহিঃপ্রকাশ:

Exp = Term $(('+':ADD|'-':SUB) Term!2); 
Term = Factor $(('*':MPY|'/':DIV) Factor!2);
Factor = ( number
         | id  ( '(' +[Exp $(',' Exp)]+ ')' :FUN!2
               | --)
         | '(' Exp ')" )
         (^' Factor:XPO!2 |--);

লুপ ব্যবহার করে এক্সপ এবং টার্ম বাম হাতের গাছ তৈরি করে। ডান পুনরাবৃত্তি ব্যবহার করে ফ্যাক্টর একটি ডান হাত গাছ তৈরি করে:

d^(x+5)^3-a+b*c => ADD[SUB[EXP[EXP[d,ADD[x,5]],3],a],MPY[b,c]]

              ADD
             /   \
          SUB     MPY
         /   \   /   \
      EXP     a b     c
     /   \
    d     EXP     
         /   \
      ADD     3
     /   \
    x     5

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

program = $((declaration            // A program is a sequence of
                                    // declarations terminated by
            |.EOF .STOP)            // End Of File finish & stop compile
           \                        // Backtrack: .EOF failed or
                                    // declaration long-failed.
             (ERRORX["?Error?"]     // report unknown error
                                    // flagging furthest parse point.
              $(-';' (.ANY          // find a ';'. skiping .ANY
                     | .STOP))      // character: .ANY fails on end of file
                                    // so .STOP ends the compile.
                                    // (-';') failing breaks loop.
              ';'));                // Match ';' and continue

declaration =  "#" directive                // Compiler directive.
             | comment                      // skips comment text
             | global        DECLAR[*1]     // Global linkage
             |(id                           // functions starting with an id:
                ( formula    PARSER[*1]     // Parsing formula
                | sequencer  GENERATOR[*1]  // Code generator
                | optimizer  ISO[*1]        // Optimizer
                | pseudo_op  PRODUCTION[*1] // Pseudo instruction
                | emitor_op  MACHOP[*1]     // Machine instruction
                )        // All the above start with an identifier
              \ (ERRORX["Syntax error."]
                 garbol);                    // skip over error.

// গাছ তৈরি করার সময় আইডি কীভাবে ফ্যাক্টর অফ করা হয় এবং পরে সংযুক্ত করা হয় তা নোট করুন।

formula =   ("==" syntax  :BCKTRAK   // backtrack grammar formula
            |'='  syntax  :SYNTAX    // grammar formula.
            |':'  chclass :CLASS     // character class define
            |".." token   :TOKEN     // token formula
              )';' !2                // Combine node name with id 
                                     // parsed in calling declaration 
                                     // formula and tree produced
                                     // by the called syntax, token
                                     // or character class formula.
                $(-(.NL |"/*") (.ANY|.STOP)); Comment ; to line separator?

chclass = +[ letter $('|' letter) ]+;// a simple list of character codes
                                     // except 
letter  = char | number | id;        // when including another class

syntax  = seq ('|' alt1|'\' alt2 |--);

alt1    = seq:ALT!2 ('|' alt1|--);  Non-backtrack alternative sequence.

alt2    = seq:BKTK!2 ('\' alt2|--); backtrack alternative sequence

seq     = +[oper $oper]+;

oper    = test | action | '(' syntax ')' | comment; 

test    = string | id ('[' (arg_list| ,NILL) ']':GENCALL!2|.EMPTY);

action  = ':' id:NODE!1
        | '!' number:MAKTREE!1
        | "+["  seq "]+" :MAKLST!1;

//     C style comments
comment  = "//" $(-.NL .ANY)
         | "/*" $(-"*/" .ANY) "*/";

লক্ষণীয় বিষয় হল পার্সার ভাষা কীভাবে মন্তব্য করা এবং ত্রুটি পুনরুদ্ধার পরিচালনা করে।

আমি মনে করি আমি প্রশ্নের উত্তর দিয়েছি। এসএলিকস উত্তরসূরির একটি বড় অংশ লিখেছেন, এখানে নিজের মধ্যে সিসি ভাষা। এটির জন্য এখনও কোনও সংকলক নেই। তবে আমি এটি সমাবেশ কোড, নগ্ন asm c বা c ++ ফাংশনগুলিতে সংকলন করতে পারি।


0

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

বুটস্ট্র্যাপ করার জন্য আপনার যা প্রয়োজন তা হল ভাষার প্রয়োগ of এটি সংকলক বা দোভাষী হতে পারে।

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

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


-1

হতে পারে আপনি বিএনএফ-কে বর্ণনা করে একটি বিএনএফ লিখতে পারেন ।


4
আপনি প্রকৃতপক্ষে (এটি এতটা কঠিনও নয়) তবে এর একমাত্র ব্যবহারিক প্রয়োগটি পার্সার জেনারেটরে in
ড্যানিয়েল স্পিওক

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

আসলে আপনি পারবেন না, কারণ বিএনএফ নিজেকে বর্ণনা করতে পারে না। আপনার ইয়াকিতে যেমন নন-টার্মিনাল চিহ্নগুলিকে উদ্ধৃত করা হয় না তার মতো একটি বৈকল্পিক প্রয়োজন ।
লার্নের মারকুইস

1
আপনি <n> হিসাবে বিএনএফ সংজ্ঞায়িত করতে bnf ব্যবহার করতে পারবেন না recognized EBNF ভাষার ধ্রুব স্ট্রিং টোকেন উদ্ধৃত করে এটি স্থির করেছে।
GK
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.