2010-05-17 8 views
8

मैं ओकैमल नौसिखिया हूं और मैं एक साधारण ओकैम-जैसी व्याकरण लिखने की कोशिश कर रहा हूं, और मैं इसे समझ नहीं सकता। मेरे व्याकरण कुछ इस तरह की अनुमति देता है:ocamlyacc पर, फ़ंक्शन एप्लिकेशन व्याकरण और प्राथमिकता

let sub = fun x -> fun y -> x - y;; 

हालांकि, अगर मैं समारोह इतना परिभाषित उपयोग करना चाहते हैं, मैं लिख सकते हैं: (sub 7) 3 लेकिन मैं sub 7 3 है, जो वास्तव में मुझे कीड़े नहीं लिख सकते हैं। किसी कारण से, यह व्याख्या की जाती है जैसे कि मैंने sub (7 3) लिखा था (जो 7 को तर्क 3 के साथ फ़ंक्शन के रूप में मानता है)। प्रासंगिक खंड हैं:

/* other operators, then at the very end: */ 
%left APPLY 

/* ... */ 

expr: 
    /* ... */ 
    | expr expr %prec APPLY  { Apply($1, $2) } 

धन्यवाद! (ocaml/parsing/parser.mly से)

expr: 
... 
    | simple_expr simple_labeled_expr_list 
     { mkexp(Pexp_apply($1, List.rev $2)) } 

जहां simple_expr संभव expr मानों कोष्ठकों जरूरत के बिना एक समारोह के लिए मूल्यांकन कर सकते हैं का एक सबसेट है:

उत्तर

5

ocaml संकलक के रूप में इस समारोह आवेदन करता है। इसमें सभी गैर-स्वयं-ब्रैकेट किए गए संरचनाओं को फ़ंक्शन कॉल के साथ इनलाइन का उपयोग करने से बाहर रखा गया है। यह उप-अभिव्यक्तियों की सहयोगकता को भी स्पष्ट करता है, क्योंकि दूसरा उप-अभिव्यक्ति स्पष्ट रूप से एक सूची है।

अपने प्रयास ocaml के parser.mly में %left APPLY उपयोग करने के लिए क्यों प्राप्त करने के लिए सही संबद्धता काम नहीं करता है, टिप्पणी से करने के लिए के रूप में:

We will only use associativities with operators of the kind x * x -> x 
for example, in the rules of the form expr: expr BINOP expr 
in all other cases, we define two precedences if needed to resolve 
conflicts. 

मैं कहना चाहता हूँ इसका मतलब है कि आप उपयोग नहीं कर सकते एक ऑपरेटर के बिना सहयोगीता के लिए% सटीक। अधिक नियमों को परिभाषित करके आप जो सहयोगीता चाहते हैं उसे बनाने का प्रयास करें, और देखें कि यह कहां जाता है।

+0

धन्यवाद। अब काम करता है :) – Amadan

+1

आपने जिस समाधान का उपयोग किया था? – Thelema

9

मामले में आप इस सवाल के लिए आया था और सोचा कि आप अंत में उस पल पर पहुंच गया था जब आप आप के लिए क्या चाहिए, तो मिल जाए, तो निराश थे, यहाँ एक और अधिक स्पष्ट जवाब है:

आप% prec उपयोग नहीं कर सकते कारण के लिए थेलेमा का उल्लेख किया। तो आपको नियमों का एक पुनरावर्ती सेट स्थापित करने में सहयोगीता को परिभाषित करना होगा।

यहाँ एक parser.mly सरलीकृत

%token <int> Num 
    %token <string> Id 
    %token TRUE FALSE 
    %token LET REC EQ IN FUN ARROW IF THEN ELSE 
    %token PLUS MINUS MUL DIV LT LE NE AND OR 
    %token EOF   

    %start exp 
    %type <Simple.expr> exp 

    %% 

/* Associativity increases from exp to exp8 
* Each precedence level trickles down to higher level expressions if the pattern is not matched 
*/ 

/* Parses the LET, LET REC, FUN, and IF expressions */ 
exp: 
     LET Id EQ exp IN exp  { Let($2,$4,$6) } 
    | LET REC Id EQ exp IN exp { Letrec($3,$5,$7) } 
    | FUN Id ARROW exp   { Fun($2,$4) } 
    | IF exp THEN exp ELSE exp { If($2,$4,$6) } 
    | exp2      { $1 } 

/* Parses OR expressions */ 
exp2: 
     exp2 OR exp3    { Bin($1,Or,$3) } 
    | exp3      { $1 } 

/* Parses AND expressions */ 
exp3: 
     exp3 AND exp4    { Bin($1,And,$3) } 
    | exp4      { $1 } 

/* Parses EQ, NE, LT, and LE expressions */ 
exp4: 
     exp4 EQ exp5    { Bin($1,Eq,$3) } 
    | exp4 NE exp5    { Bin($1,Ne,$3) } 
    | exp4 LT exp5    { Bin($1,Lt,$3) } 
    | exp4 LE exp5    { Bin($1,Le,$3) } 
    | exp5      { $1 } 

/* Parses PLUS and MINUS expressions */ 
exp5: 
     exp5 PLUS exp6   { Bin($1,Plus,$3) } 
    | exp5 MINUS exp6   { Bin($1,Minus,$3) } 
    | exp6      { $1 } 

/* Parses MUL and DIV expressions */ 
exp6: 
     exp6 MUL exp7    { Bin($1,Mul,$3)} 
    | exp6 DIV exp7    { Bin($1,Div,$3)} 
    | exp7      { $1 } 

/* Parses Function Application expressions */ 
exp7: 
     exp7 exp8     { Apply($1,$2) } 
    | exp8      { $1 } 

/* Parses numbers (Num), strings (Id), booleans (True | False), and expressions in parentheses */ 
exp8: 
     Num      { Const($1) } 
    | Id      { Var($1) } 
    | TRUE      { True } 
    | FALSE      { False } 
    | LPAREN exp RPAREN   { $2 } 

है पुनरावर्ती काम के आसपास मामले है कि हम इस सवाल के बारे में अधिक महत्वपूर्ण हैं को पकड़ने के लिए वास्तव में है, लेकिन यह देखने के लिए कि यह कैसे परिभाषित करने के लिए लागू किया जा सकता आसान है बाकी अभिव्यक्तियों के लिए सहयोगीता भी।

इस दृष्टिकोण का सारांश स्टार्ट केस (एक्सपी) में परिभाषित पैटर्न के खिलाफ प्रश्न में पैटर्न से मिलान करने का प्रयास करना है, और आप कैच-ऑल पैटर्न के रूप में तुरंत सफल केस (एक्सपी 2) पर कॉल छोड़ देते हैं। आपका पैटर्न इससे पहले किसी भी मेल नहीं खाता है; अंत तक पैटर्न के अंत तक इस दृष्टिकोण के साथ जारी है। इसका तात्पर्य है कि सबसे कम प्राथमिकता पैटर्न सबसे दूर के मामले में मौजूद है - इस उदाहरण में, exp8।

इस उदाहरण में, आवेदन (फ़ंक्शन एप्लिकेशन) के मामले में exp7 में है। ऐसा इसलिए है क्योंकि इस उदाहरण में किसी भी पैटर्न की उच्चतम सहयोगीता लागू करने के लिए लागू किया गया है। एक्स 8 में मामलों पर प्राथमिकता नहीं होने का कारण अभिव्यक्ति मामलों में आगे कॉल करने के लिए मूल्यांकन मूल्य लागू करना है, मूल्य कॉल नहीं। यदि एक्सपी 8 मौजूद नहीं था, तो हमारे हाथों पर एक अनंत रूप होगी।

hypothetical simple.ml में, फ़ंक्शन एप्लिकेशन को निम्न संपत्ति की अभिव्यक्ति के रूप में परिभाषित किया गया है: expr * expr का आवेदन करें।और चूंकि आवेदन बाएं-रिकर्सिव है, हम सही अभिव्यक्ति (एक्सपी 8) का मूल्यांकन कर रहे हैं और बाएं (एक्स 7) पर रिकर्सिंग कर रहे हैं।

0

एक भी इतने सारे स्तरों में इस तरह की बातें उपयोग कर सकते हैं नीचे भाव को तोड़ने से बचने के लिए:

%nonassoc LET FUN IF 

%left OR 

%left AND 

%left EQ NE LT LE 

%left PLUS MINUS 

%left MUL DIV 

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

  • कोई संबंधित समस्या नहीं^_^