2011-10-06 14 views
5

मुझे पुरानी आत्म-कल्पना वाली स्क्रिप्टिंग भाषा में विरासत कोड का एक बड़ा समूह मिला है जिसे हम जावास्क्रिप्ट में संकलित/अनुवाद करते हैं।पुन: लिखने के लिए एल्गोरिदम संशोधित गोटो अर्थशास्त्र

उस भाषा में एक सशर्त कूद है, जो एक लेबल पर कूद रहा है। आम गोटो स्टेटमेंट में अंतर यह है कि कोई पिछड़ा कूद संभव नहीं है। अगर उस भाषा में बयान और न ही लूप हो तो कोई घोंसला नहीं है।

जैसा कि जावा जावास्क्रिप्ट में मौजूद नहीं है, मैं एक एल्गोरिदम खोज रहा हूं जो goto mylabel और mylabel: को अर्थात् समकक्ष संरचना में परिवर्तित करता है।

मैंने ifs का उपयोग करने के बारे में सोचा लेकिन गोटो लेबल के मनमाने ढंग से घोंसले के कारण यह मामूली नहीं पाया।

उदाहरण:

if cond1 goto a 
do something1 
if cond2 goto b 
do something2 
a: 
do something3 
if cond3 goto c 
do something4 
c: 
do something5 
b: 

फिर से लिखा जा सकता है के रूप में:

lbl_b=false; 
lbl_c=false; 

lbl_a = cond1; 
if (!cond1) { 
    do something1; 
    lbl_b = cond2; 
    if (!lbl_b) { 
    do something2; 
    } 
} 
if (!lbl_b) { 
    do something3; 
    lbl_c = cond3; 
    if (!lbl_c) { 
    do something4; 
    } 
    do something5; 
} 

हालांकि, मैं नहीं है कि से एक सामान्य एल्गोरिथ्म प्राप्त करने में सक्षम था।

+0

सामान्य गोटो हटाने का समाधान यहां दिए गए "टमिंग कंट्रोल फ्लो" पेपर में प्रदान किया गया है: http://stackoverflow.com/questions/14061856/automated-goto-removal-algorithm –

उत्तर

2

यह आमतौर पर कहा जाता है गोटो हटाने precompute कर सकते हैं एक और तरीका है, कुछ आसान व्याख्या प्रारूप, यानी बाईटकोड संकलित करने के लिए हो सकता है, हम सिर्फ एक बार एक छात्र था काम जहां काम को सी के लिए कार्यान्वित करना था। आम तौर पर आपको लूप के साथ काम करना पड़ता है (दुख की बात है कि हमने उस काम को ऑनलाइन नहीं रखा है)। लेकिन जैसा कि आपके पास प्रतिबंध है कि आप केवल आगे बढ़ सकते हैं यह अपेक्षाकृत आसान है:

सभी लाइनों पर एक बार पार्स और सभी लेबल एकत्रित करें। हर लेबल के लिए एक ध्वज "skip_to_label" बनाएं। शुरुआत में सभी झंडे झूठी शुरूआत में शुरू करें। जब आप लेबल एक्स के लिए सशर्त गेटो को पूरा करते हैं तो अब आप प्रत्येक पंक्ति को "लाइन नहीं करते हैं" के साथ लेबल लाइन तक प्रीपेड करते हैं और ध्वज को सत्य पर सेट करते हैं।

यह पहले से ही पर्याप्त और काम होना चाहिए, लेकिन निश्चित रूप से बहुत अनुकूल नहीं है।

आप इसे कैसे अनुकूलित कर सकते हैं: अगर प्रीपेन्ड करने की बजाय, बस प्रत्येक पंक्ति के लिए झंडे का एक सेट बनाए रखें, और कुछ गलत करने के बजाय, बस सेट में corrosponding ध्वज लाइनों के लिए जोड़ें।

अब आप उस समूह के लिए बना सकते हैं जिसमें सभी लाइनें हों, जहां सेट नहीं बदले, और स्थिति सेट के बूलियन झंडे हैं।आपके दिए गए कोड के साथ

उदाहरण:

set     your code 
empty     if cond1 goto a 
skip_to_a,    do something1 
skip_to_a,    if cond2 goto b 
skip_to_a, skip_to_b do something2 
skip_to_a, skip_to_b a: 
skip_to_b    do something3 
skip_to_b, skip_to_c if cond3 goto c 
skip_to_b, skip_to_c do something4 
skip_to_b, skip_to_c c: 
skip_to_b    do something5 
skip_to_b    b: 

अब आप प्रत्येक पंक्ति के सामने बारे में या तो अगर (s) या आप शीर्ष पर शुरू और जब तक सेट एक ही रहता है के रूप में एक अगर ब्लॉक बनाने ।

तो जब आप आप खाली पर अपने पहले मिल शुरू करते हैं, इसकी एक सशर्त गोटो तो बजाय आप अपने ध्वज

if cond1 goto skip_to_a=true; 

अब सेट परिवर्तन निर्धारित करते हैं, और आप के साथ सेट की अगर आपके ब्लॉक परिचय:

if (!skip_to_a) BEGIN 
    do something1 
    if cond2 skip_to_b=true; 
    END 

सेट में अगले परिवर्तन, इसलिए नए यदि ब्लॉक:

if (!skip_to_a and !skip_to_b) BEGIN 
    do something2 
    END 

और इतने पर (मैं आप अनुमान लगा जीई टी अब विचार)।

EDIT: जैसा कि कोई उदाहरण में सेट के साथ अच्छी तरह से देख सकता है, सामान्य रूप से इसे नेस्टेड आईएसएस के साथ मॉडल करना संभव नहीं है, उदाहरण के लिए skip_to_a वाली रेखाएं और skip_to_b ओवरलैप वाले वाले, लेकिन न तो अन्य पूर्ण है।

+2

बूलियन झंडे के बजाय, आप कर सकते हैं एक एकल पूर्णांक चर का उपयोग करें, यह दर्शाता है कि आप किस लेबल का लक्ष्य रख रहे हैं। फिर एनएच ब्लॉक के सामने की स्थिति बस 'if (skip_to <= N)' और 'goto Mth_label' को 'skip_to = M' द्वारा प्रतिस्थापित किया गया है। – han

+0

@han: मुझे लगता है कि काम नहीं करेगा। उपर्युक्त उदाहरण में आप 1,2,3 के साथ आसानी से ए, बी, सी को प्रतिस्थापित कर सकते हैं। आप देखते हैं कि यह केवल तभी सही होगा जब आप उच्चतम को छोड़ते समय हमेशा निचले लेबल को छोड़ दें। यह मामला नहीं है। आप शायद तर्क दे सकते हैं कि दो संख्याएं पर्याप्त हैं (सबसे कम और उच्चतम लेबल) - जो वास्तव में इस उदाहरण में काम करेगी। लेकिन मुझे लगता है कि कोई एक counterexample बना सकता है जहां यह काम नहीं करेगा (मैं लेबल के अंतराल में "छेद")। – flolo

+0

मुझे आपका अंक नहीं मिला। लेबल को कोड में दिखाई देने के क्रम में गिना जाना चाहिए, यानी ए, सी, बी 1,2,3 द्वारा प्रतिस्थापित किया गया है। फिर उच्च-क्रमांकित लेबल में कूदने से संकेत मिलता है कि वर्तमान निर्देश और लक्ष्य लेबल के बीच सभी निचले-क्रमांकित लेबलों के पीछे कूदना। – han

1

आप थोड़ी देर के पाश में गोटो राज्य पर नज़र रखने की तरह कुछ कर सकता है, लेकिन यह बहुत सुंदर लग रही हो नहीं होगा:

var goto = null ; 

do { 
    if(goto == null && cond1) goto = 'a' ; 
    if(goto == null) do_something(1) ; 
    if(goto == null && cond2) goto = 'b' ; 
    if(goto == null) do_something(2) ; 
    if(goto == null || goto == 'a') goto = null; 
    if(goto == null) do_something(3) ; 
    if(goto == null && cond3) goto = 'c' ; 
    if(goto == null) do_something(4) ; 
    if(goto == null || goto == 'c') goto = null ; 
    if(goto == null) do_something(5) ; 
    if(goto == null || goto == 'b') goto = null ; 
} while(goto != null) 
1

किसी अन्य भाषा में संकलन आम तौर पर आवश्यक तुलना में कठिन है। एक सरल विधि होगी, दूसरी भाषा को संकलित नहीं करना, बल्कि जावास्क्रिप्ट में कोड की व्याख्या करना। इस तरह से आप अपने गोटो स्टेटमेंट को किसी भी प्रकार के अर्थशास्त्र के साथ आसानी से बनाना संभव होगा।

हालांकि यदि आप इसे ऐसा करते हैं, तो आपको सभी पार्सिंग तर्क को अपने जावास्क्रिप्ट कोड में स्थानांतरित करने की आवश्यकता होगी, जो करने के लिए बदसूरत हो सकता है। ताकि आप सब कुछ आप पार्सर से की जरूरत है, सभी लेबल पदों आदि

1

एक वैकल्पिक समाधान प्रत्येक लेबल को उस लेबल की शुरुआत से कोड को निम्नलिखित लेबल की शुरुआत में कोड के साथ बनाना होगा, उसके बाद निम्न लेबल के लिए उत्पन्न फ़ंक्शन पर कॉल किया जाएगा।

इसके लिए समर्थक यह है कि एक गोटो को एक साधारण विधि कॉल द्वारा प्रतिस्थापित किया जा सकता है। दोष यह है कि, लंबी स्क्रिप्ट या लूप के लिए आप बड़े कॉल स्टैक के साथ समाप्त हो सकते हैं।

इस विधि का उपयोग करना, एक सरल एल्गोरिथ्म होगा:

goto_label_count := 0 // Find out how many methods we need to generate 
For each line: 
    if line is goto 
     goto_label_count := goto_label_count + 1 

Write function head 
Write "goto0();" 

goto_count := 0 // Generate code 
For each line: 
    if line is goto 
     if goto_count > 0 
      write "goto"+goto_count+"();" // produce call to last goto found 
     write function header for corresponding goto //("goto"+goto_count+"()") 
     goto_count := goto_count + 1 
    else 
     translate normally 
Generate end of code 

इस अतिरिक्त समस्याओं के कारण हो सकता है। उदाहरण के लिए, चर के लिए क्या गुंजाइश है? लेकिन, कम से कम यह एक वैकल्पिक दृष्टिकोण है जो मुझे आशा है कि आपके दिमाग को और अधिक पटरियों के साथ शुरू करना चाहिए। ;)

+0

"उस लेबल की शुरुआत से उस लेबल की शुरुआत से कोड"? बुह? –

+0

ध्यान देने के लिए धन्यवाद। इसका मतलब था "उस लेबल की शुरुआत से निम्नलिखित लेबल की शुरुआत से कोड" पोस्ट को सही किया गया है। – Agentlien

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^