2012-07-17 15 views
6

मैं पार्ससी का उपयोग करके हास्केल में एक पार्सर लिखने का प्रयास कर रहा हूं। वर्तमान में मैं एक प्रोग्राम है जो पार्स कर सकते हैंमुठभेड़ के लिए हास्केल पारसेक पार्सर [...]

test x [1,2,3] end 

कोड है कि के रूप में

testParser = do { 
    reserved "test"; 
    v <- identifier; 
    symbol "["; 
    l <- sepBy natural commaSep; 
    symbol "]"; 
    p <- pParser; 
    return $ Test v (List l) p 
} <?> "end" 

जहां commaSep

commaSep  = skipMany1 (space <|> char ',') 

अब के रूप में परिभाषित किया गया है इस प्रकार इस दिया जाता है है वहाँ मेरे लिए कुछ रास्ता है एक समान बयान का विश्लेषण करने के लिए, विशेष रूप से:

test x [1...3] end 

उस मामले के लिए हास्केल और पारसेक के लिए नया होने के नाते, मुझे यकीन है कि ऐसा करने का कुछ अच्छा संक्षिप्त तरीका है जिसे मैं अभी नहीं जानता हूं। किसी भी सहायता की सराहना की जाएगी।

फिर से धन्यवाद।

+0

क्या अवधि की संख्या स्थिर या परिवर्तनीय होनी चाहिए? क्या संख्याओं और अवधि, और अवधि के बीच रिक्त स्थान की अनुमति है? वैसे, आपका पहला पार्सर 'टेस्ट एक्स [1, 2,, 3] एंड' से मेल खाता है; हो सकता है कि आप जो चाहते हैं वह नहीं है। – dflemstr

+0

अवधि की संख्या स्थिर होना चाहिए, यानी [1 ... 3] किसी भी मामले के लिए बिल्कुल 3 अवधि होनी चाहिए। [1 ... 3] के बीच व्हाइटस्पेस को अनदेखा किया जाना चाहिए। उम्मीद है कि यह स्पष्ट करता है कि मैं थोड़ा और बाद में क्या कर रहा हूं। –

उत्तर

14

मैं Control.Applicative से (*>) जैसे कुछ फ़ंक्शंस का उपयोग करूँगा। यदि आप Parsec के monadic इंटरफ़ेस से बचना चाहते हैं और आवेदक इंटरफ़ेस को प्राथमिकता देना चाहते हैं, तो ये फ़ंक्शन उपयोगी हैं, क्योंकि पार्सर्स मेरी राय में इस तरह से पढ़ने में आसान हो जाते हैं।

यदि आप मूल आवेदक कार्यों से परिचित नहीं हैं, तो एक टिप्पणी छोड़ दो और मैं उन्हें समझाऊंगा। यदि आप अनिश्चित हैं तो आप उन्हें Hoogle पर देख सकते हैं।


मैं आपकी समस्या को समझ लिया है के रूप में, आप इस तरह कुछ डेटा संरचना के लिए एक पार्सर हैं:

data Test = Test String Numbers 
data Numbers = List [Int] | Range Int Int 

एक पार्सर कि इस तरह के एक डेटा संरचना पार्स कर सकते हैं इस प्रकार दिखाई देगा (मैंने कोड संकलित नहीं किया गया है, लेकिन यह काम करना चाहिए):

-- parses "test <identifier> [<numbers>] end" 
testParser :: Parser Test 
testParser = 
    Test <$> reserved "test" *> identifier 
     <*> symbol "[" *> numbersParser <* symbol "]" 
     <* reserved "end" 
     <?> "test" 

numbersParser :: Parser Numbers 
numbersParser = try listParser <|> rangeParser 

-- parses "<natural>, <natural>, <natural>" etc 
listParser :: Parser Numbers 
listParser = 
    List <$> sepBy natural (symbol ",") 
     <?> "list" 

-- parses "<natural> ... <natural>" 
rangeParser :: Parser Numbers 
rangeParser = 
    Range <$> natural <* symbol "..." 
     <*> natural 
     <?> "range" 
+0

आह बहुत बहुत धन्यवाद, यही वही है जो मुझे चाहिए। एक बार फिर धन्यवाद! –

+1

@VincentRusso यह 'fmap' के लिए समानार्थी है। – phg

+0

ठीक है, एक आखिरी बात मैं अभी भी सही होने की कोशिश कर रहा हूं। क्या मैं कुछ एल <- कोशिश कर सकता हूं (प्राकृतिक कॉम्पसेप <|> प्राकृतिक प्रतीक "..." प्राकृतिक); केवल, मेरा कार्यान्वयन यहां काम नहीं करता है, क्या ऐसा कुछ ऐसा है जो मैं कर सकता हूं? आपका उदाहरण बहुत अच्छा है, लेकिन जिस तरह से पार्सर वर्तमान में कार्यान्वित किया गया है, वह ऊपर दिए गए उदाहरण के साथ इतना अच्छी तरह से नहीं खेलता है। आपसे मिली हर मदद के लिए धन्यवाद। –

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