2012-04-16 19 views
8

pyparsing मैं pyparsing उपयोग करने के लिए समारोह के रूप में कॉल पार्स करने के लिए कोशिश कर रहा हूँ का उपयोग कर कहता है। लेकिन क्योंकि यह एक रिकर्सिव-डिसेंट पार्सर है, यह भी पार्स करने के लिए आसान होना चाहिए:पार्सिंग नेस्ट समारोह

f(g(x), y) 

है कि मैं नहीं मिल सकता है क्या। यहाँ एक उबला हुआ नीचे उदाहरण है:

from pyparsing import Forward, Word, alphas, alphanums, nums, ZeroOrMore, Literal 

lparen = Literal("(") 
rparen = Literal(")") 

identifier = Word(alphas, alphanums + "_") 
integer = Word(nums) 

functor = identifier 

# allow expression to be used recursively 
expression = Forward() 

arg = identifier | integer | expression 
args = arg + ZeroOrMore("," + arg) 

expression << functor + lparen + args + rparen 

print expression.parseString("f(x, y)") 
print expression.parseString("f(g(x), y)") 

और यहाँ उत्पादन है:

['f', '(', 'x', ',', 'y', ')'] 
Traceback (most recent call last): 
    File "tmp.py", line 14, in <module> 
    print expression.parseString("f(g(x), y)") 
    File "/usr/local/lib/python2.6/dist-packages/pyparsing-1.5.6-py2.6.egg/pyparsing.py", line 1032, in parseString 
    raise exc 
pyparsing.ParseException: Expected ")" (at char 3), (line:1, col:4) 

क्यों मेरी पार्सर एक स्टैंडअलोन पहचानकर्ता के रूप में आंतरिक अभिव्यक्ति की functor व्याख्या करता है?

उत्तर

4

arg की परिभाषा आइटम है कि बाएं में एक और के साथ शुरू होता के साथ व्यवस्था की जानी चाहिए, तो यह प्राथमिक रूप से मिलान किया जाता है: पता लगाना है कि identifierarg की अपनी परिभाषा में expression मास्किंग था पर

arg = expression | identifier | integer 
+0

अच्छा पकड़, @Jason! – PaulMcG

11

अच्छा पकड़ । यहाँ अपने पार्सर पर कुछ अन्य सुझाव दिए गए हैं:

x + ZeroOrMore(',' + x) pyparsing पारसर्स में एक बहुत ही आम पैटर्न है, इसलिए pyparsing एक सहायक विधि delimitedList जो आप delimitedList(x) साथ कि अभिव्यक्ति को बदलने के लिए अनुमति देता है। असल में, delimitedList एक और चीज करता है - यह डिलीमिटिंग कॉमा (या वैकल्पिक delim तर्क का उपयोग करके दिए गए अन्य डिलीमीटर) को दबाता है, इस धारणा के आधार पर कि डिलीमीटर समय पर पार्सिंग उपयोगी होते हैं, लेकिन जब वे बाहर निकलने की कोशिश करते हैं तो केवल अव्यवस्था टोकन हैं बाद में पार्स किया गया डेटा। तो आप args = delimitedList(arg) के रूप में तर्कों को फिर से लिख सकते हैं, और आपको केवल एक सूची में तर्क मिलेगा, "चरणबद्ध" होने के लिए कोई कॉमा नहीं होगा।

आप अपने पार्स किए गए टोकन में वास्तविक संरचना बनाने के लिए Group कक्षा का उपयोग कर सकते हैं। यह आप के लिए अपने घोंसले पदानुक्रम का निर्माण करेगा '(' और ')' में बताने के लिए जब आप समारोह घोंसले में एक स्तर नीचे चले गए हैं की तलाश में इस सूची चलने के लिए बिना:

arg = Group(expression) | identifier | integer 
expression << functor + Group(lparen + args + rparen) 

अपने आर्ग के बाद से आप के लिए Group एड किया जा रहा है, तो आप आगे कोष्ठक को दबाने सकते हैं, क्योंकि परिसीमन के लिए अल्पविराम की तरह, वे पार्स करने के दौरान उनके काम करते हैं, लेकिन अपने टोकन के समूह के साथ, वे अब जरूरी हैं:

lparen = Literal("(").suppress() 
rparen = Literal(")").suppress() 

मुझे लगता है ' एच() 'एक मान्य फंक्शन कॉल है, बस कोई तर्क नहीं है। आप आर्ग Optional का उपयोग कर वैकल्पिक होने की अनुमति कर सकते हैं:

expression << functor + Group(lparen + Optional(args) + rparen) 

अब आप पार्स कर सकते हैं "च (g (x), वाई, ज())"।

पाइपर्सिंग में आपका स्वागत है!

+3

सभी सहायक टिप्पणियों के लिए धन्यवाद!यह उदाहरण वास्तव में पाइपर्सिंग दस्तावेज से अनुकूलित किया गया था; मैं अपने वास्तविक पार्सर में वर्णित अधिकांश तकनीकों का उपयोग करता हूं। (और भाषा कार्यान्वयन अब लगभग 6 घंटे के काम में प्रयोग योग्य है --- पाइपरिंग में प्रोटोटाइपिंग पाइपर्सिंग आश्चर्यजनक रूप से त्वरित है।) – JasonFruit

+0

'दबाने ("(")' और 'लिटलल ("(") के बीच क्या अंतर है। दबाएं () ' – dashesy

+1

कोई फर्क नहीं पड़ता। 'Expr.suppress()' रिटर्न' दबाएं (expr) ', और अगर स्ट्रिंग को दबाकर प्रारंभ करने के लिए स्ट्रिंग पास की जाती है, तो स्ट्रिंग को एक शाब्दिक में पदोन्नत किया जाता है। – PaulMcG

0

पॉल की पोस्ट में बहुत मदद मिली। बस दूसरों के संदर्भ के लिए, एक ही प्रकार for loops परिभाषित करने के लिए (यहाँ सरलीकृत छद्म पार्सर, संरचना दिखाने के लिए) का उपयोग किया जा सकता है:

sep = Literal(';') 
if_ = Keyword('if') 
then_ = Keyword('then') 
elif_ = Keyword('elif') 
end_ = Keyword('end') 

if_block = Forward() 
do_block = Forward() 

stmt = other | if_block 
stmts = OneOrMore(stmt +sep) 

case = Group(guard +then_ +stmts) 
cases = case +OneOrMore(elif_ +case) 

if_block << if_ +cases +end_ 
संबंधित मुद्दे