2012-10-17 19 views
14

मैं पारसी के साथ अपना पहला कार्यक्रम लिख रहा हूं। मैं MySQL स्कीमा डंप को पार्स करना चाहता हूं और केस-असंवेदनशील फैशन में कुछ कीवर्ड का प्रतिनिधित्व करने वाले तारों को पार्स करने के लिए एक अच्छा तरीका पेश करना चाहता हूं। यहां कुछ कोड दिखाया गया है जिसका उपयोग मैं "CREATE" या "create" को पार्स करने के लिए कर रहा हूं। क्या ऐसा करने के लिए इससे अच्छा तरीका है? एक उत्तर जो buildExpressionParser का सहारा नहीं लेता है सबसे अच्छा होगा। मैं यहाँ बच्चे के कदम उठा रहा हूँ।Text.Combinators.Parsec के साथ केस-असंवेदनशील पार्सिंग करने का सबसे साफ तरीका क्या है?

p_create_t :: GenParser Char st Statement 
    p_create_t = do 
     x <- (string "CREATE" <|> string "create") 
     xs <- manyTill anyChar (char ';') 
     return $ CreateTable (x ++ xs) [] -- refine later 
+5

मुझे लगता है कि पार्सर चलाने से पहले इनपुट पर 'नक्शा टू लोवर' एक विकल्प नहीं है? साथ ही, मैं "केस" असंवेदनशील "" क्रिएट "," CREEATe "," CREATe ", या किसी अन्य भिन्नता से मेल खाता हूं, जो आपका उदाहरण अस्वीकार करता है। तुम्हें कौनसा चाहिए? –

+0

यह काम करता है। धन्यवाद। मैंने इसके बारे में सोचा नहीं था! – dan

+1

@ डैन बस सावधान रहें कि यदि आपके इनपुट में तार हैं, तो वे भी कम हो जाएंगे। उदाहरण के लिए, यदि आपके किसी भी कॉलम में डिफ़ॉल्ट स्ट्रिंग मान हैं। –

उत्तर

17

आप केस पार्सर्स से केस-असंवेदनशील पार्सर बना सकते हैं। toLower के साथ पूरे इनपुट मानचित्रण के

-- Match the lowercase or uppercase form of 'c' 
caseInsensitiveChar c = char (toLower c) <|> char (toUpper c) 

-- Match the string 's', accepting either lowercase or uppercase form of each character 
caseInsensitiveString s = try (mapM caseInsensitiveChar s) <?> "\"" ++ s ++ "\"" 
8

दोहरा क्या मैं एक टिप्पणी में कहा, के रूप में यह जाहिरा तौर पर मददगार था:

सरल हथौड़े समाधान यहाँ बस पार्सर चलाने से पहले मैप करने के लिए toLower पूरे इनपुट खत्म हो गया है, तो आपके सभी कीवर्ड मिलान करना लोअरकेस में

यह स्पष्ट कठिनाइयों को प्रस्तुत करता है यदि आप कुछ ऐसी जगहों पर विश्लेषण कर रहे हैं जिन्हें कुछ स्थानों में केस-असंवेदनशील होना चाहिए और दूसरों में केस-सेंसिटिव होना चाहिए, या यदि आप कॉस्मेटिक कारणों से मामले को संरक्षित करने की परवाह करते हैं। उदाहरण के लिए, हालांकि एचटीएमएल टैग केस-असंवेदनशील हैं, लेकिन पूरे वेबपृष्ठ को लोअरकेस में बदलने के दौरान इसे कम करने के लिए संभवतः अवांछनीय होगा। यहां तक ​​कि केस-असंवेदनशील प्रोग्रामिंग भाषा को संकलित करते समय, पहचानकर्ताओं को परिवर्तित करना परेशान हो सकता है, क्योंकि परिणामी त्रुटि संदेश प्रोग्रामर द्वारा लिखे गए मेल से मेल नहीं खाते हैं।

0

इसके बजाय, Text.ParserCombinators.Parsec.Rfc2234 से (hsemail पैकेज से)

Text.ParsecCombinators.Parsec.Rfc2234

p_create_t :: GenParser Char st Statement 
p_create_t = do 
    x <- (caseString "create") 
    xs <- manyTill anyChar (char ';') 
    return $ CreateTable (x ++ xs) [] -- refine later 

तो अब xcaseString का उपयोग करेंगे जो कुछ भी मामले-संस्करण मौजूद है पर विचार इनपुट में आपके इनपुट को बदलने के बिना।

पुनश्च: मुझे पता है कि यह एक प्राचीन सवाल है, मैं सिर्फ इतना है कि मैं इस जोड़ने के रूप में इस सवाल आया, जबकि मैं एक ऐसी ही समस्या

+0

यह टेक्स्ट से नहीं है। ParsecCombinators.Parsec। यह Text.ParsecCombinators.Parsec.Rfc2234 से है। आपका लिंक सही है, लेकिन आपका शीर्षक गलत है। यह भी ध्यान में है कि यह हैमेल पैकेज का हिस्सा है, जिसे कोई पहले से इंस्टॉल नहीं कर सकता है। – Sean

2

नहीं लिए खोज रहा था होगा सोचा, Parsec कि स्वच्छ तरीके से नहीं कर सकतेstring आदिम tokens संयोजक के शीर्ष पर लागू किया गया है जो समानता परीक्षण (==) का उपयोग करने के लिए हार्ड-कोड किया गया है। केस-असंवेदनशील चरित्र को पार्स करना थोड़ा आसान है, लेकिन आप शायद अधिक चाहते हैं।

हालांकि नहीं है Parsec का एक आधुनिक कांटा, कहा जाता Megaparsec जो सब कुछ के लिए निर्मित समाधान आप चाहते हो सकता है है:

λ> parseTest (char' 'a') "b" 
parse error at line 1, column 1: 
unexpected 'b' 
expecting 'A' or 'a' 
λ> parseTest (string' "foo") "Foo" 
"Foo" 
λ> parseTest (string' "foo") "FOO" 
"FOO" 
λ> parseTest (string' "foo") "fo!" 
parse error at line 1, column 1: 
unexpected "fo!" 
expecting "foo" 

नोट अंतिम त्रुटि संदेश, यह क्या आप पार्स प्राप्त कर सकते हैं की तुलना में बेहतर है वर्ण एक-एक करके (विशेष रूप से आपके विशेष मामले में उपयोगी)। string' केवल Parsec के string की तरह लागू किया गया है लेकिन वर्णों की तुलना करने के लिए केस-असंवेदनशील तुलना का उपयोग करता है। oneOf' और noneOf' भी हैं जो कुछ मामलों में सहायक हो सकते हैं।


प्रकटीकरण: मैं Megaparsec के लेखकों में से एक हूँ।

+0

वास्तव में आश्चर्य की बात है कि 'टोकन' मूल पारसेक में तुलना करने के लिए तुलनात्मक कार्य को पारित करने की अनुमति नहीं देता है। – MicroVirus