RegexParsers के लिए कस्टम त्रुटियां

कोई मुझे निम्नलिखित व्यवहार को समझने में मदद कर सकता है: parseAll (parseIf, "अगर bla blablaa") परिणामस्वरूप अपेक्षित होना चाहिए। इसके बजाय मुझे हमेशा स्ट्रिंग मिलान रेगेक्स 'मिलता है \ b' अपेक्षित लेकिन 'बी' मिला । मुझे लगता है कि इसमें सफेद जगहों के साथ कुछ करना है क्योंकि "अगर ब्ला ब्लाब्ला है" (शुरुआत में सफेद जगहों पर ध्यान दें) परिणाम एक ही व्यवहार में होते हैं। मैंने इसे मानक टोकनपर्सर्स के साथ करने की कोशिश की और सब ठीक काम किया। लेकिन एसटीपी दुर्भाग्य से regex का समर्थन नहीं करता है। फॉलो-अप प्रश्न: मुझे RegexParsers को कैसे बदलना होगा ताकि यह वर्णों के क्रम के बजाय स्ट्रिंग्स के अनुक्रम का उपयोग कर सके? इससे त्रुटि रिपोर्टिंग बहुत आसान हो जाएगी।

lazy val parseIf = roleGiverIf ~ giverRole

lazy val roleGiverIf =
  kwIf ~> identifier | failure("""A rule must begin with if""")
lazy val giverRole =
  kwIs ~> identifier | failure("""is expected""")

lazy val keyword =
  kwIf | kwAnd | kwThen | kwOf | kwIs | kwFrom | kwTo

lazy val identifier =
  not(keyword) ~ roleEntityLiteral
// ...

def roleEntityLiteral: Parser[String] =
  """([^"\p{Cntrl}\\]|\\[\\/bfnrt]|\\u[a-fA-F0-9]{4})\S*""".r 
def kwIf: Parser[String] = "If\\b".r
def kwIs: Parser[String] = "is\\b".r

// ...

parseAll(parseIf, "If bla blablaa") match {
  case Success(parseIf, _) => println(parseIf)
  case Failure(msg, _) => println("Failure: " + msg)
  case Error(msg, _) => println("Error: " + msg)
1

1 उत्तर

यह समस्या बहुत अजीब है। जब आप | को कॉल करते हैं और दोनों पक्ष असफल होते हैं, तो जिस पक्ष में विफलता अंतिम चयनित होती है, बायीं ओर वाले पक्ष का पक्ष लेती है।

जब आप सीधे giverRole के साथ पार्स करने का प्रयास करते हैं, तो यह आपके द्वारा अपेक्षित परिणाम उत्पन्न करता है। यदि आप विफलता से पहले एक सफल मैच जोड़ते हैं, हालांकि, यह परिणाम जो आप देख रहे हैं उसका उत्पादन करता है।

कारण बल्कि सूक्ष्म है - मुझे केवल सभी पार्सर्स पर log कथन छिड़ककर इसे मिला। इसे समझने के लिए, आपको समझना होगा RegexParser रिक्त स्थान कैसे करता है। विशेष रूप से, रिक्त स्थान स्वीकार करें पर छोड़ दिए जाते हैं। क्योंकि विफलता स्वीकार करें को कॉल नहीं करती है, यह रिक्त स्थान को छोड़ नहीं देती है।

जबकि kwIs की विफलता b पर होती है, जैसे स्थान छोड़ा गया है, विफलता के बाद स्थान पर विफलता यदि । यहाँ:

If bla blablaa
   ^ kwIs fails here
  ^ failure fails here

इसलिए, मेरे द्वारा वर्णित नियम द्वारा kwIs पर त्रुटि संदेश प्राथमिकता प्राप्त करता है।

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

"\\b|$".r ~ failure("is expected")

एक और समाधान अंतर्निहित regex स्वीकार करने के बजाय acceptIf या acceptMatch का उपयोग करना है, इस स्थिति में आप एक अनुरूप त्रुटि संदेश प्रदान कर सकते हैं।

0
जोड़ा
@awertos मुझे अंत में पता चला कि समस्या क्या थी। पहला समाधान मैंने सोचा जितना उचित था - मैंने इसे किसी भी गैर-स्पेस वर्णों का उपभोग न करके उचित स्थान पर त्रुटि प्रकट करने के लिए बदल दिया है।
जोड़ा लेखक Daniel C. Sobral, स्रोत
मैंने रेगेक्स और लेक्सिकल क्षमता के साथ एक पार्सर लिखा है और जैसा कि आप सुझाव देते हैं, स्वीकार करते हैं। लेकिन यह अभी भी अजीब बात है कि ऊपर दिया गया उदाहरण अपेक्षित काम नहीं करेगा। आपकी सहायता के लिए धन्यवाद
जोड़ा लेखक awertos, स्रोत