EOS पर रोकु व्याकरण रोकना (स्ट्रिंग का अंत)


9

एक म्यूजिक लैंग्वेज का ट्रांसलेटर लिखने की प्रक्रिया में रकु डीएसएल-क्षमता सीखने के लिए एक बहाने के रूप में दूसरे (एबीसी से एल्डा) में, मैंने देखा कि ए को समाप्त करने का कोई तरीका नहीं लगता है .parse! यहाँ मेरा छोटा डेमो कोड है:

#!/home/hsmyers/rakudo741/bin/perl6
use v6d;

# use Grammar::Debugger;
use Grammar::Tracer;

my $test-n01 = q:to/EOS/;
a b c d e f g
A B C D E F G
EOS

grammar test {
  token TOP { <score>+ }
  token score {
      <.ws>?
      [
          | <uc>
          | <lc>
      ]+
      <.ws>?
  }
  token uc { <[A..G]> }
  token lc { <[a..g]> }
}

test.parse($test-n01).say;

और यह ग्रामर का अंतिम भाग है :: ट्रेसर डिस्प्ले जो मेरी समस्या को प्रदर्शित करता है।

|  score
|  |  uc
|  |  * MATCH "G"
|  * MATCH "G\n"
|  score
|  * FAIL
* MATCH "a b c d e f g\nA B C D E F G\n"
「a b c d e f g
A B C D E F G
」

दूसरी से अंतिम पंक्ति में, फेल शब्द मुझे बताता है कि .parse रन में छोड़ने का कोई तरीका नहीं है। मुझे आश्चर्य है कि क्या यह सही है? .Say सब कुछ प्रदर्शित करता है जैसा कि यह होना चाहिए, इसलिए मैं स्पष्ट नहीं हूं कि फेल कितना वास्तविक है? सवाल यह है, "मैं एक व्याकरण को सही ढंग से कैसे लिखूं जो त्रुटि के बिना कई लाइनों को पार्स करता है?"


मैं आपकी सीखने की प्रक्रिया में हस्तक्षेप नहीं करना चाहता, लेकिन अगर आपको पता नहीं था, तो एबीसी मॉड्यूल है
raiph

1
ठीक है, कम से कम हम पर परीक्षण करने के लिए एक ही धुन नहीं चुना!
हस्मर्स

जवाबों:


10

जब आप व्याकरण डीबगर का उपयोग करते हैं, तो यह आपको यह देखने देता है कि इंजन स्ट्रिंग को कैसे पार्स कर रहा है - विफल सामान्य और अपेक्षित हैं। माना जाता है, उदाहरण के लिए, a+b*स्ट्रिंग के साथ मिलान aab। आपको 'ए' के ​​लिए दो मैच मिलने चाहिए, उसके बाद फेल होना (क्योंकि bनहीं है a) लेकिन फिर यह bमैच और सफलतापूर्वक मैच होगा।

यह अधिक आसानी से देखा जा सकता है यदि आप एक वैकल्पिक व्यवस्था करते हैं ||(जो आदेश को लागू करता है)। यदि आपके पास है

token TOP   { I have a <fruit> }
token fruit { apple || orange || kiwi }

और आप वाक्य "मेरे पास एक कीवी है" को पार्स करते हैं, आप इसे पहले मैच "मेरे पास" देखेंगे, उसके बाद "सेब" और "नारंगी" के साथ दो असफलताएं, और अंत में "कीवी" के साथ एक मैच होगा।

अब आपके मामले को देखते हैं:

TOP                  # Trying to match top (need >1 match of score)
|  score             #   Trying to match score (need >1 match of lc/uc)
|  |  lc             #     Trying to match lc
|  |  * MATCH "a"    #     lc had a successful match! ("a")
|  * MATCH "a "      #   and as a result so did score! ("a ")
|  score             #   Trying to match score again (because <score>+)
|  |  lc             #     Trying to match lc 
|  |  * MATCH "b"    #     lc had a successful match! ("b")
|  * MATCH "b "      #   and as a result so did score! ("b ")
……………                #     …so forth and so on until…
|  score             #   Trying to match score again (because <score>+)
|  |  uc             #     Trying to match uc
|  |  * MATCH "G"    #     uc had a successful match! ("G")
|  * MATCH "G\n"     #   and as a result, so did score! ("G\n")
|  score             #   Trying to match *score* again (because <score>+)
|  * FAIL            #   failed to match score, because no lc/uc.
|
|  # <--------------   At this point, the question is, did TOP match?
|  #                     Remember, TOP is <score>+, so we match TOP if there 
|  #                     was at least one <score> token that matched, there was so...
|
* MATCH "a b c d e f g\nA B C D E F G\n" # this is the TOP match

यहां असफल होना सामान्य है: किसी समय हम <score>टोकन से बाहर निकल जाएंगे , इसलिए असफल होना अपरिहार्य है। जब ऐसा होता है, तो व्याकरण इंजन <score>+आपके व्याकरण में आने के बाद आगे बढ़ सकता है । चूंकि कुछ भी नहीं है, यह वास्तव में पूरे स्ट्रिंग के एक मैच के परिणामस्वरूप होता है (क्योंकि TOPअंतर्निहित के साथ मेल खाता है /^…$/)।

इसके अलावा, आप एक नियम के साथ अपने व्याकरण को फिर से लिखने पर विचार कर सकते हैं, जो <।

grammar test {
  rule TOP { <score>+ }
  token score {
      [
          | <uc>
          | <lc>
      ]+
  }
  token uc { <[A..G]> }
  token lc { <[a..g]> }
}

इसके अलावा, IME, आप uc / lc के लिए एक प्रोटो टोकन भी जोड़ना चाह सकते हैं, क्योंकि जब आपके पास [ <foo> | <bar> ]होगा तो आपके पास हमेशा उनमें से एक अपरिभाषित रहेगा जो उन्हें एक्शन क्लास में थोड़ा परेशान कर सकता है। तुम कोशिश कर सकते हो:

grammar test {
  rule  TOP   { <score>  + }
  token score { <letter> + }

  proto token letter    {     *    }
        token letter:uc { <[A..G]> }
        token letter:lc { <[a..g]> }
}

$<letter> हमेशा इस तरह से परिभाषित किया जाएगा।


यह इस तथ्य की व्याख्या करता है कि मैच ऑब्जेक्ट 'फेल' के साथ भी सच है। मुझे लगा कि वो मामला हो सकता है; मैं वास्तविक परियोजना के लिए आवश्यक टोकन जोड़ने के लिए वापस जाऊँगा;)
hsmyers

असली व्याकरण डालने के लिए प्रतीत नहीं होता है <.ws> * स्वचालित रूप से; संभवतः अतिरिक्त परतों के कारण <स्कोर> से परे। जैसे ही मैं तकनीक के चारों ओर अपना सिर लपेटने में सक्षम हूं, प्रोटो का उपयोग करने का आपका सुझाव अच्छा है ...
hsmyers


मुझे उस कोड से नफरत है, जिसकी मुझे आवश्यकता नहीं है - अधिक डिबग करने के लिए, और फिर वहाँ यह सब के सौंदर्यशास्त्र है! वास्तविक समस्या यह है कि एबीसी रिक्त स्थान के बारे में ध्यान नहीं देता है। कुछ अपवाद हैं, लेकिन बड़े और वे लगभग कहीं भी हो सकते हैं। 'उपयोग' मामला कुछ हद तक बड़े अंकों के तार में अल्पविराम की तरह सुगमता का मामला है। जब तक मैं समस्या को समझूंगा और समस्या को कम से कम कर दूंगा, तब तक समस्या पर फिर से विचार करूंगा।
हस्मर्स

1
hsmyers: शुक्र है समझ protoबहुत कठिन नहीं है और एक बार जब आप इसे लटका लेते हैं तो यह आपके जीवन को इतना आसान बना देता है।
user0721090601
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.