शाब्दिक विश्लेषण का कार्य इनपुट अनुक्रम (मेरे मामले में, पास्कल कोड) को शब्दों और टोकन में तोड़ना है।
शुरुआत करने के लिए, मैंने डेटा स्टोर करने के लिए 5 टाइप की गई चादरें बनाईं, जैसे: पहचानकर्ता, स्थिरांक, कीवर्ड, सीमांकक और दृढ़ संकल्प। सीमांकक की भी जरूरत है।
static char[] limiters = {',', '.', '(', ')', '[', ']', ':', ';', '+', '-', '*', '/', '<', '>', '@'};
और खोजशब्दों की एक सरणी। मैंने खुद को ग्यारह कीवर्ड तक सीमित कर लिया, क्योंकि लेख को C # में पास्कल भाषा के लेक्सिकल विश्लेषण के कार्यान्वयन के प्रारंभिक उदाहरण के रूप में लिखा गया था।
तो, कीवर्ड की एक सरणी:
static string[] reservedWords = { "program", "var", "real", "integer", "begin", "for", "downto", "do", "begin", "end", "writeln" };
इनपुट पर, हमारे पास पथ चर में प्रोग्राम के साथ .txt फ़ाइल का पथ है। हम AllTextProgram में एक फ़ाइल में सब कुछ पढ़ते हैं और शुरू करते हैं।
StreamReader sr = new StreamReader(path, Encoding.Default); AllTextProgram = sr.ReadToEnd(); sr.Close();
लूप के लिए, हम प्रत्येक अक्षर को AllTextProgram क्रम से लेते हैं और इसे विश्लेषण विधि में भेजते हैं। अलग-अलग, मैं केवल दो अपवादों पर विचार करता हूं। पहला एपोस्ट्रोफिस है, जो मेरे मामले में "रिटेलन" कीवर्ड का उपयोग करते समय होता है। यदि हम एक एपोस्ट्रोफ का सामना करते हैं, तो हम नियमों से दूर जाते हैं और AllTextPorgram चर के माध्यम से चलते हैं जब तक कि हम दूसरा एपोस्ट्रोफ नहीं पाते। कार्यक्रम में दूसरी टिप्पणी है। उत्तरार्द्ध के लिए, मैं केवल घुंघराले ब्रेसिज़ खोलने और बंद करने की संख्या की गणना करता हूं और अंतर शून्य होने तक उम्मीद करता हूं।
ऐसा लगता है कि कार्यक्रम को चक्र में जाना चाहिए यदि बाद में एपोस्ट्रोफ नहीं मिला है या घुंघराले कोष्ठक की संख्या 0. नहीं है, यह सच है, स्कैन से बाहर निकलने के लिए इन चक्रों में अतिरिक्त शर्तें जोड़ी जानी चाहिए। मैंने पार्सिंग के चरण में व्यवस्थितकरण के लिए इन शर्तों को बनाने का फैसला किया।
for (i = 0; i < AllTextProgram.Length; i++) { char c = AllTextProgram[i]; if (AllTextProgram[i] == '\'') { temp += '\''; i++; while (AllTextProgram[i] != '\'') { temp += AllTextProgram[i]; i++; } temp += '\''; type = 2; Result(temp); temp = null; } if (AllTextProgram[i] == '{') { int chet = 1; while (chet != 0) { i++; if (AllTextProgram[i] == '{') chet++; if (AllTextProgram[i] == '}') chet--; } } Analysis(AllTextProgram[i]); }
प्रकार चर उस तालिका की संख्या के लिए ज़िम्मेदार है, जिसका टोकन है।
पहचानकर्ता - तालिका 1
लगातार - तालिका 2
कीवर्ड - तालिका 3
विभाजक - तालिका 4
अब विश्लेषण पद्धति में क्या होता है, इसके बारे में बात करने का समय आ गया है। यह कोड टिप्पणियों के रूप में सबसे अच्छा किया जाता है। तुरंत, मैं ध्यान देता हूं कि अस्थायी चर में हम काम के मध्यवर्ती परिणाम को संग्रहीत करेंगे, जब तक कि हम एक विभाजक से नहीं मिलते। विभाजक से मिलने के बाद, हमें पहचानकर्ता, स्थिर या कीवर्ड से संबंधित वर्तमान टोकन निर्धारित करने के लिए परिणाम चर में अस्थायी चर भेजने की आवश्यकता है।
static void Analysis(char nextChar) { int acsiiCode = (int)nextChar; // // if (((acsiiCode >= 65) && (acsiiCode <= 90)) || ((acsiiCode >= 97) && (acsiiCode <= 122)) || (acsiiCode == 95) { if (temp == null) type = 1; temp += nextChar; return; } // if (((acsiiCode >= 48) && (acsiiCode <= 57)) || (acsiiCode == 46)) { // , , temp // . temp , // , - if (acsiiCode == 46) { int out_r; if (!int.TryParse(temp, out out_r)) goto not_the_number; } if (temp == null) type = 2; temp += nextChar; return; } not_the_number: if ((nextChar == ' ' || nextChar == '\n') && temp != null) { Result(temp); temp = null; return; } // . «:=» . foreach (char c in limiters) { if (nextChar == c) { if (temp != null) Result(temp); type = 3; if (nextChar == ':' && AllTextProgram[i+1] == '=') { temp = nextChar.ToString() + AllTextProgram[i + 1]; Result(temp); temp = null; return; } if (nextChar == '<' && (AllTextProgram[i + 1] == '>' || AllTextProgram[i + 1] == '=')) { temp = nextChar.ToString() + AllTextProgram[i + 1]; Result(temp); temp = null; return; } if (nextChar == '>' && AllTextProgram[i + 1] == '=') { temp = nextChar.ToString() + AllTextProgram[i + 1]; Result(temp); temp = null; return; } temp = nextChar.ToString(); Result(temp); temp = null; return; } }
अंतिम विचार परिणाम विधि है, जहां हम यह निर्धारित करते हैं कि हमने क्या पाया। बहुत शुरुआत में, हम कीवर्ड से संबंधित अस्थायी चर की जांच करते हैं। हम शुरुआत में जाँच करते हैं ताकि पहचानकर्ता के साथ पाए गए टोकन को भ्रमित न करें। यदि परिणाम एक कीवर्ड नहीं है, तो स्विच के माध्यम से हम विश्लेषण विधि में पहले से परिभाषित तालिका प्रकार की जांच करते हैं। यह जांचना न भूलें कि जो पहचानकर्ता / निरंतर / विभाजक पाया गया है वह पहले से ही तालिका में नहीं है।
static void Result(string temp) { for (int j = 0; j < reservedWords.Length; j++) { if (temp == reservedWords[j]) { for (int i = 0; i < tableR.Count; i++) { if (temp == tableR[i]) { LConv.Add("3" + i); return; } } tableR.Add(temp); LConv.Add("3" + (tableR.Count - 1)); return; } } switch (type) { case 1: for (int j = 0; j < tableI.Count; j++) { if (temp == tableI[j]) { LConv.Add("1" + j); return; } } tableI.Add(temp); LConv.Add("1" + (tableI.Count - 1)); break; case 2: for (int j = 0; j < tableC.Count; j++) { if (temp == tableC[j]) { LConv.Add("2" + j); return; } } tableC.Add(temp); LConv.Add("2" + (tableC.Count - 1)); break; case 3: for (int j = 0; j < tableL.Count; j++) { if (temp == tableL[j]) { LConv.Add("4" + j); return; } } tableL.Add(temp); LConv.Add("4" + (tableL.Count - 1)); break; } }
और यह कैसे काम करता है यह दिखाने के लिए एक आसान उदाहरण।
कार्यक्रम के इनपुट पर:
program main; { pro{g}am }
var sum: real;
f, per_1, x_1,i:integer;
begin
{sum:=(-x_1+2.5)*4 - (x_1-6)*((((x_1+2))));}
x_1:=18;
f:= 456;
for i:=10 downto per_1-f+i*(x_1+1) do
begin
per_1 := per_1 + x_1*sum*f;
x_1:=-x_1-1;
f:=(f+1)*(x_1-24700);
sum:=(x_1+2.5)*4 - (x_1-6)*(x_1+2);
end;
writeln( 'summa = ' , sum);
end.
और काम का परिणाम:
