2017-06-04 6 views
6

के साथ एक साधारण लैम्ब्डा कैलकुस पार्सर मैं एफ # के लिए नया हूं और एक बहुत परेशान समस्या है।FParsec

Application := Expression Expression 
Expression := "(" "lambda" Name "." Application ")" 
      | Name 
Name  := [a-z]+ 

कि (lambda x. (lambda y. x y)) z और (lambda x. x) y जैसी चीजों से मेल खाएंगे: मैं निम्नलिखित व्याकरण पार्स करने के लिए चाहता हूँ।

मेरे समस्या यह है कि दो नियम एक दूसरे पर निर्भर है:

let popen = pchar '(' 
let pclose = pchar ')' 
let pname = many1 letter |>> Seq.toArray |>> System.String |>> NameNode 
let plambda = pstring "lambda" 
let pdot = pchar '.' 
let phead = plambda >>. pname .>> pdot 
let pexpression = 
     popen >>. pname .>>. papplication .>> pclose |>> ExpressionNode 
    <|> pname 
let papplication = pexpression .>>. pexpression 

pexpressionpapplication और vicebersa पर निर्भर करता है। मैं उस निर्भरता से कैसे छुटकारा पा सकता हूं?

उत्तर

8

रिकर्सिव पार्सर्स createParserForwardedToRef के माध्यम से कार्यान्वित किया जा सकता है। यह फ़ंक्शन पार्सर "हैंडल" की एक जोड़ी देता है, इसलिए बोलने के लिए, और एक परिवर्तनीय सेल जो पार्सर कार्यान्वयन रखता है। एक बार "हैंडल", जिसे वास्तव में कुछ विश्लेषण करने के लिए कहा जाता है, कॉल को कार्यान्वयन के लिए अग्रेषित करेगा।

इस जोड़ी को प्राप्त करने के बाद, आप "हैंडल" का उपयोग करके रिकर्सन के दूसरे भाग को कार्यान्वित कर सकते हैं, और उसके बाद अग्रेषित पार्सर के कार्यान्वयन को बना सकते हैं और इसे म्यूटेबल सेल को असाइन कर सकते हैं।

let pexpression, pexpressionImpl = createParserForwardedToRef() 
let papplication = pexpression .>>. pexpression 
pexpressionImpl := 
     popen >>. pname .>>. papplication .>> pclose |>> ExpressionNode 
    <|> pname 
+0

आह! यही वही है जो मुझे चाहिए था। धन्यवाद :) – gosukiwi

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