2009-12-29 15 views
10

मैं किसी भी सफलता के बिना, इसके सार वाक्यविन्यास वृक्ष प्रतिनिधित्व में एक मान्य एरलांग अभिव्यक्ति वाली स्ट्रिंग को कन्वर्ट करना चाहता हूं।स्ट्रिंग को अमूर्त सिंटैक्स पेड़

नीचे एक उदाहरण है जो मैं करना चाहता हूं। संकलन के बाद, z:z(). ऑब्जेक्ट zed उत्पन्न करता है, जो zed:zed(). पर कॉल करके lists:reverse को दिए गए सूची पर लागू करने का परिणाम देता है।

-module(z). 
-export([z/0]). 

z() -> 
    ModuleAST = erl_syntax:attribute(erl_syntax:atom(module), 
            [erl_syntax:atom("zed")]), 

    ExportAST = erl_syntax:attribute(erl_syntax:atom(export), 
            [erl_syntax:list(
            [erl_syntax:arity_qualifier(
            erl_syntax:atom("zed"), 
            erl_syntax:integer(0))])]), 

    %ListAST = ?(String), % This is where I would put my AST 
    ListAST = erl_syntax:list([erl_syntax:integer(1), erl_syntax:integer(2)]), 

    FunctionAST = erl_syntax:function(erl_syntax:atom("zed"), 
            [erl_syntax:clause(
            [], none, 
            [erl_syntax:application(
             erl_syntax:atom(lists), 
             erl_syntax:atom(reverse), 
             [ListAST] 
        )])]), 

    Forms = [erl_syntax:revert(AST) || AST <- [ModuleAST, ExportAST, FunctionAST]], 

    case compile:forms(Forms) of 
    {ok,ModuleName,Binary}   -> code:load_binary(ModuleName, "z", Binary); 
    {ok,ModuleName,Binary,_Warnings} -> code:load_binary(ModuleName, "z", Binary) 
    end. 

String"[1,2,3].", या "begin A=4, B=2+3, [A,B] end.", या कुछ भी समान रूप से हो सकता है।

(ध्यान दें कि यह सिर्फ मैं, ऐसा करने String का मूल्यांकन करना चाहते हैं क्या का एक उदाहरण है मेरे लिए एक विकल्प नहीं है।)


संपादित:

निर्दिष्ट नीचे के रूप में ListAST एक विशाल dict-digraph-error-monster उत्पन्न करता है, और "lint_module में आंतरिक त्रुटि" कहता है।

String = "[1,2,3].", 
{ok, Ts, _} = erl_scan:string(String), 
{ok, ListAST} = erl_parse:parse_exprs(Ts), 

EDIT2:

यह समाधान सरल शब्दों के लिए काम करता है:

{ok, Ts, _} = erl_scan:string(String), 
{ok, Term} = erl_parse:parse_term(Ts), 
ListAST = erl_syntax:abstract(Term), 
+0

अब जब कि मैं कोड को देखो, मैं स्पष्ट रूप से ऊपर erl_syntax और erl_parse प्रारूपों मिश्रण ... अभी भी यह कैसे हालांकि (आम बहुत ज्यादा bejgli त्रुटि) करने के लिए को समझ नहीं सकता। – Zed

+0

हाँ, यदि आप erl_syntax द्वारा बनाए गए एक के साथ अपनी ListAST की तुलना करते हैं तो वे समान रूप से नहीं दिखते हैं :( 42> ListAST। [{Cons, 1, {integer, 1,1}, {cons, 1, {integer, 1,2}, {शून्य, 1}}}] 43> erl_syntax:। सूची ([1, 2, 3], []) {पेड़, सूची, {attr, 0, [], कोई नहीं} {सूची , [1,2,3], []}} 44> –

+0

तो मैं या तो एक तरह से स्ट्रिंग, या एक तरह से 'erl_syntax' सामान के लिए एक प्लेसहोल्डर डाल करने के बाहर एक' erl_syntax' संगत एएसटी बनाने की जरूरत है, और 'वापस लाएं() कॉल' के बाद इसे बदलना या मैं कुछ स्पष्ट याद आ रही है ... – Zed

उत्तर

5

अपने संपादित उदाहरण में:

String = "[1,2,3].", 
{ok, Ts, _} = erl_scan:string(String), 
{ok, ListAST} = erl_parse:parse_exprs(Ts), 

ListAST वास्तव में एएसटी की एक सूची है: रों (क्योंकि parse_exprs, के रूप में नाम इंगित करता है, कई भाव को पार्स करता है (प्रत्येक अवधि के द्वारा समाप्त)। चूंकि आपकी स्ट्रिंग में एक अभिव्यक्ति है, इसलिए आपको एक तत्व की एक सूची मिली है। तुम सब करने की ज़रूरत है से मेल है कि बाहर:

{ok, [ListAST]} = erl_parse:parse_exprs(Ts), 

तो यह (जो सभी erl_parse पेड़ स्वीकार करता है) erl_syntax कोई लेना देना नहीं है; यह सिर्फ इतना है कि आपके पास ListAST के आस-पास एक अतिरिक्त सूची रैपर था, जिसने संकलक को प्यूक करने का कारण बना दिया।

+0

धन्यवाद रिचर्ड! मुझे लगता है कि मुझे यह पता लगाना चाहिए था ...: \ – Zed

2

ज़ोल्टन

यह है कि हम कैसे एएसटी मिलता है:

11> String = "fun() -> io:format(\"blah~n\") end.". 
"fun() -> io:format(\"blah~n\") end." 
12> {ok, Tokens, _} = erl_scan:string(String).  
{ok,[{'fun',1}, 
    {'(',1}, 
    {')',1}, 
    {'->',1}, 
    {atom,1,io}, 
    {':',1}, 
    {atom,1,format}, 
    {'(',1}, 
    {string,1,"blah~n"}, 
    {')',1}, 
    {'end',1}, 
    {dot,1}], 
    1} 
13> {ok, AbsForm} = erl_parse:parse_exprs(Tokens). 
{ok,[{'fun',1, 
      {clauses,[{clause,1,[],[], 
           [{call,1, 
            {remote,1,{atom,1,io},{atom,1,format}}, 
            [{string,1,"blah~n"}]}]}]}}]} 
14> 
+0

मैंने पहले से ही इस तरह की चीजों की कोशिश की है। जब मैं इसे अपने एएसटी में erl_syntax के साथ बनाया गया तो यह बस काम नहीं करता है। यह 'संकलन करता है: रूपों()' फेंक ... – Zed

+0

@ गॉर्डन, मैंने अपने प्रश्न में उदाहरण बढ़ाया। जब मैं 'erl_syntax' के साथ सूची बनाता हूं तो यह पूरी तरह से काम करता है। लेकिन इसे 'erl_parse' सामान के साथ बदलना दुर्भाग्यवश काम नहीं कर रहा है। – Zed

3

मेरे सिर के शीर्ष पर कुछ टिप्पणियां।

मैंने वास्तव में erl_syntax पुस्तकालयों का उपयोग नहीं किया है, लेकिन मुझे लगता है कि वे इसे पढ़ने में कठिनाई कर रहे हैं और जो भी आप बनाने की कोशिश कर रहे हैं उसे "देखें"। मैं संभवतः कार्यों को आयात करता हूं या इसे छोटा और अधिक सुगम बनाने के लिए अपना स्वयं का एपीआई परिभाषित करता हूं। लेकिन फिर मैं आम तौर पर छोटे कार्य और परिवर्तनीय नाम पसंद करते हैं।

एआरटी erl_syntax द्वारा बनाया गया और erl_parse द्वारा निर्मित "मानक" एक और कंपाइलर में उपयोग किया जाता है और मिश्रित नहीं हो सकता है। तो आपको उनमें से एक चुनना होगा और इसके साथ रहना होगा।

अपने दूसरे संपादित में उदाहरण के शब्दों के लिए काम करेंगे, लेकिन अधिक सामान्य स्थिति में नहीं:

{ok, Ts, _} = erl_scan:string(String), 
{ok, Term} = erl_parse:parse_term(Ts), 
ListAST = erl_syntax:abstract(Term), 

इसका कारण यह है erl_parse: parse_term/1 रिटर्न वास्तविक अवधि टोकन का प्रतिनिधित्व करती है, जबकि अन्य erl_parse कार्यों parse_form और parse_exprs एएसटी वापस आते हैं। उन्हें erl_syntax में डालकर: अमूर्त मजेदार चीजें करेगा।

आपको बस इतना करना है कि यह वास्तव में वास्तव में लिखने और erlang फ़ाइल और अमूर्त रूपों के साथ प्रत्यक्ष रूप से कार्य करने के बजाय यह संकलित करने के लिए आसान हो सकता है कोशिश कर रहे हैं पर निर्भर करता है

। यह मेरी अंतर्निहित भावनाओं के खिलाफ चला जाता है लेकिन erlang एएसटी उत्पन्न करना तुच्छ नहीं है। आप किस प्रकार का कोड तैयार करना चाहते हैं?

<shameless_plug>

आप सूचियों आप LFE (तुतलाना स्वाद erlang) का उपयोग कर के साथ के रूप में सभी lisps वहाँ कोई विशेष सार रूप है कोड उत्पन्न करने के लिए कोशिश कर सकते हैं का डर नहीं कर रहे हैं, यह सब homoiconic और भी बहुत कुछ के साथ काम करना आसान है।

</shameless_plug>

+0

उत्तर के लिए धन्यवाद, रॉबर्ट। इस बीच मुझे रिचर्ड से जवाब मिला: erl_parse पेड़ erl_syntax पेड़ में मिश्रित किया जा सकता है। फिर 'erl_syntax: revert()' को कॉल करने से मिश्रण के बाहर एक साफ erl_parse पेड़ बनाता है। मेरी एकमात्र गलती यह नहीं देख रही थी कि 'erl_parse: parse_exprs() 'का परिणाम सूची में लपेटा गया है ... – Zed

+0

पहले मैं भी एक अस्थायी फ़ाइल में स्रोत कोड बनाने और इसे सामान्य तरीके से संकलित करने के लिए गया था। अब मैंने इसे बदलकर एक आईओलिस्ट() बनाने के लिए बदल दिया है, और उस पर parse_forms का उपयोग करें, इसलिए सब कुछ स्मृति में किया जाता है। दुर्भाग्य से मैंने कुछ अच्छी विशेषताएं खो दीं, जैसे कि कोड: get_object_code, beam_lib: get_chunks, hipe: संकलित करें, लेकिन मैं इसके साथ रह सकता हूं। – Zed

+0

BTW मैं सिर्फ टेम्पलेट फ़ाइलों से मॉड्यूल पैदा करने के साथ चारों ओर खेल रहा हूँ, जबकि दे अपने आप टेम्पलेट्स के अंदर Erlang कोड का उपयोग करें। – Zed

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