2016-01-19 6 views
9

मैं इस व्याकरण हास्केल के पारसेक लाइब्रेरी का उपयोग कर नियम लागू करना चाहते हैं अंदर many` Combinator:हास्केल पारसेक: `एक` optional` Combinator

((a | b | c)* (a | b))? 

जो एक पार्सर नियम यह है कि एक वैकल्पिक स्वीकार करता है (यानी संभावित रिक्त है) स्ट्रिंग। स्ट्रिंग यह acccepts खाली नहीं है, तो यह ab या c पारसर्स के शून्य या अधिक घटनाओं के माध्यम से गुजर द्वारा सेवन किया जा सकता है, लेकिन सबसे बाहरी ? वैकल्पिक पार्सर द्वारा स्वीकार कर लिया स्ट्रिंग या तो पार्सर a द्वारा या सेवन किया जाना चाहिए b, लेकिन c नहीं। यहाँ एक उदाहरण है:

module Main where 

import Text.Parsec 
import Text.Parsec.Text 

a,b,c :: GenParser() Char 
a = char 'a' 
b = char 'b' 
c = char 'c' 

-- ((a | b | c)* (a | b))? 
myParser = undefined 

shouldParse1,shouldParse2,shouldParse3, 
     shouldParse4,shouldFail :: Either ParseError String 
-- these should succeed 
shouldParse1 = runParser myParser() "" "" -- because ? optional 
shouldParse2 = runParser myParser() "" "b" 
shouldParse3 = runParser myParser() "" "ccccccb" 
shouldParse4 = runParser myParser() "" "aabccab" 

-- this should fail because it ends with a 'c' 
shouldFail = runParser myParser() "" "aabccac" 

main = do 
    print shouldParse1 
    print shouldParse2 
    print shouldParse3 
    print shouldParse4 
    print shouldFail 

एक पहला प्रयास इस प्रकार दिखाई देंगे:

myParser = option "" $ do 
    str <- many (a <|> b <|> c) 
    ch <- a <|> b 
    return (str ++ [ch]) 

लेकिन many बस सभी 'एक' 'ख' और 'प्रत्येक परीक्षा मामले में सी' अक्षर की खपत, a <|> b छोड़ने उपभोग करने के लिए कोई पात्र नहीं है।

सवाल:

पारसेक combinators का उपयोग करना, ((a | b | c)* (a | b))? का सही कार्यान्वयन myParser परिभाषित करने के लिए क्या है?

+0

शायद पार्स (a | b | ग) + और बाद में इसे अस्वीकार कर दें यदि यह सी के साथ समाप्त होता है? –

उत्तर

4

हम यह भी कह सकते हैं यह थोड़ा अलग हैं: अपने पार्सर में c केवल सफल हो सकते है, तो यह किसी भी टोकन, जिसका उपयोग एकमात्र lookAhead साथ किया जा सकता द्वारा पीछा किया है:

myParser = many (a <|> b <|> (c <* (lookAhead anyToken <?> "non C token"))) <* eof 
+1

धन्यवाद, यह काम करता है। मैं आधे से उम्मीद कर रहा था कि यह 'किसी भी टोकन' के कारण काम नहीं करता था, मैंने इसका मतलब यह माना था कि क्या वह 'डी', '\ n', या जो भी हो। मैं कुछ सोच रहा था जैसे 'myParser = कई (<|> बी <|> (सी <* (lookAhead (<|> कोशिश करें बी) "गैर सी टोकन")) <* eof'। हालांकि, 'myParser' * की आपकी परिभाषा * काम करती है। जैसे पार्सिंग "सीए" रिटर्न "सीए", जबकि "सीडी" पार्स करने की कोशिश कर रहा है "अप्रत्याशित" डी 'में विफल रहता है। "ए", "बी", "सी" या इनपुट के अंत "। यह 'ए' टोकन 'संयोजक' केवल 'ए', 'बी', या 'सी' स्वीकार करने के लिए तैयार क्यों है? –

+1

@RobStewart: '<* eof' के कारण। 'myParser' सभी इनपुट का उपभोग करने की उम्मीद करता है। – Zeta

+0

धन्यवाद! स्वीकृत उत्तर के रूप में चिह्नित। –

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