SORU
18 HAZİRAN 2010, Cuma


ruh semantik eylem boost parametreleri

article about boost spirit semantic actions bu söz edilmektedir

Aslında 2 Daha fazla bağımsız değişken vardır geçirilen: bağlam çözümleyici ve bir bir boolean başvuru ‘vurdu’ parametre. Ayrıştırıcı bağlam budur anlamsal yalnızca anlamlı eylem bir yere doğru bağlı bir kural tarafta. Daha fazlasını da göreceğiz bu konu hakkında bilgi kısaca. Bu boolean değeri false olarak ayarlanabilir semantik eylem içinde geçersiz kılar yapım retrospektif maç, ayrıştırıcı başarısız.

Herşey çok güzeldi, ama bir örnek diğer parametreleri (çözümleyici içerik ve hit boolean) kullanan anlamsal Eylem olarak işlev bir nesne geçirerek bulmaya çalıştım ama bulamadım. Ben zar zor phoenix voodoo grok gibi bir örnek normal işlevler veya işlev nesneleri kullanarak görmek isterdim

CEVAP
18 HAZİRAN 2010, Cuma


Bu qi ve phoenix arayüzü de olur, çünkü gerçekten güzel bir soru (ve de nasıl). Ya da bir örnek görmedim, bu yönde yazı biraz uzatacağım.

Dediğiniz gibi, semantic actions fonksiyonları için üç parametre alabilir

  1. Eşleşen öznitelik - madde ile kaplı
  2. Bağlam - qi-phoenix arayüzü içerir
  3. Bayrak Maçı - Maç durumunu değiştirmek

Bayrak maç

Makalede belirttiği gibi, ikinci parametre ifadesi üçüncü ile başlayalım öyle bir kural, bir parçası olmadığı sürece anlamlı değildir. İkinci parametre için bir yer tutucu hala ve bu kullanım için olsa boost::fusion::unused_type gereklidir. Madde değiştirilmiş bir fonksiyon üçüncü bir parametre kullanmak için:

#include <boost/spirit/include/qi.hpp>
#include <string>
#include <iostream>

void f(int attribute, const boost::fusion::unused_type& it, bool& mFlag){
    //output parameters
    std::cout << "matched integer: '" << attribute << "'" << std::endl
              << "match flag: " << mFlag << std::endl;

    //fiddle with match flag
    mFlag = false;
}

namespace qi = boost::spirit::qi;

int main(void){
   std::string input("1234 6543");
   std::string::const_iterator begin = input.begin(), end = input.end();

   bool returnVal = qi::phrase_parse(begin, end, qi::int_[f], qi::space);

   std::cout << "return: " << returnVal << std::endl;
   return 0;
}

çıkışları:

matched integer: '1234'
match flag: 1
return: 0

Tüm bu örnek, ayrıştırıcı çıktı yansıyan olmayan bir maç için maçın anahtarı yok. Hkaiser için destek 1.44 göre ve yanlış maçı bayrağı ayar maçın normal şekilde başarısız olmasına neden olur. Eğer alternatifler tanımlanır, çözümleyici biri beklendiği gibi vazgeçmek ve onları maç için çalışacaktır. Ancak, boost<=1.43 Ruhu bir hata garip davranış neden olan yararlar, engeller. Bunu görmek için, phoenix boost/spirit/include/phoenix.hpp ekleyin ve ifade değiştirin

qi::int_[f] | qi::digit[std::cout << qi::_1 << "\n"]

Qi zaman bekleyeceğiniz::int ayrıştırıcı başarısız, alternatif qi::basamaklı girdi başlayan maç için "1", ama çıktı

matched integer: '1234'
match flag: 1
6
return: 1

6 alternatif kaptan kullanma ve doğru ilaç olduğunu gösterir giriş ikinci int ilk basamak. Fark maçını da başarılı, alternatif dayalı olarak kabul edilir.

Boost 1.44 dışarı sonra, maçı bayrağı yoksa zor ayrıştırıcı bir dizi ifade etmek için olabilir bu maç kriterinin uygulanması için yararlı olacaktır. Maçı bayrağı phoenix ifadeler _pass yer tutucu kullanarak manipüle edilebilir olduğunu unutmayın.

Bağlam parametresi

Daha ilginç parametre qi-phoenix ınterface, ya da qi dilinde, anlamsal eylem bağlamı içeren ikinci bir,. Bunu göstermek için, ilk kural inceleyin:

rule<Iterator, Attribute(Arg1,Arg2,...), qi::locals<Loc1,Loc2,...>, Skipper>

Bağlam parametre Özniteliği temsil ediyor, Arg1, ... ArgN ve qi::şablon parametreleri yerliler, bir destek sarılı::ruh::bağlam Şablon Türü. Bu öznitelik fonksiyonu parametre farklıdır: parametre bu özniteliği kural kendi değerini ise ayrıştırılmış değeri, işlevi. Semantik bir eylemin ikincisi için eski bir harita gerekir. Burada olası bir içerik türüne bir örnek (Anka ifade benzerleri belirtilir):

using namespace boost;
spirit::context<              //context template
    fusion::cons<             
        int&,                 //return int attribute (phoenix: _val)
        fusion::cons<
            char&,            //char argument1       (phoenix: _r1)
            fusion::cons<
                float&,       //float argument2      (phoenix: _r2) 
                fusion::nil   //end of cons list
            >,
        >,
    >,
    fusion::vector2<          //locals container
        char,                 //char local           (phoenix: _a)
        unsigned int          //unsigned int local   (phoenix: _b)
    > 
>

Dönüş nitelik ve bağımsız değişken listesi lisp tarzı bir liste (a cons list) şeklinde not. Bir işlev içinde bu değişkenleri erişmek için, füzyon context yapı şablonu attribute locals üye erişim::&;^. lt (). İçerik con değişken için örneğin

//assign return attribute
fusion::at_c<0>(con.attributes) = 1;

//get the second rule argument
float arg2 = fusion::at_c<2>(con.attributes);

//assign the first local
fusion::at_c<1>(con.locals) = 42;

Bu makalede, ikinci bağımsız değişken kullanmak için örnek değiştirmek için, fonksiyon tanımını değiştirerek arama phrase_parse:

...
typedef 
    boost::spirit::context<
        boost::fusion::cons<int&, boost::fusion::nil>, 
        boost::fusion::vector0<> 
    > f_context;
void f(int attribute, const f_context& con, bool& mFlag){
   std::cout << "matched integer: '" << attribute << "'" << std::endl
             << "match flag: " << mFlag << std::endl;

   //assign output attribute from parsed value    
   boost::fusion::at_c<0>(con.attributes) = attribute;
}
...
int matchedInt;
qi::rule<std::string::const_iterator,int(void),ascii::space_type> 
    intRule = qi::int_[f];
qi::phrase_parse(begin, end, intRule, ascii::space, matchedInt);
std::cout << "matched: " << matchedInt << std::endl;
....

Bu sadece haritalar çıktı ayrıştırılmış Değer Değer öznitelik bu çok basit bir örnektir, ama uzantıları oldukça belirgin olmalıdır. Sadece şablon parametreleri kural çıktı maç bağlam yapı, giriş ve yerel türleri. Unutmayın, bu tip bir doğrudan maç arasında ayrıştırılmış türü/değer çıktı türü/değer yapılabilir otomatik olarak kullanarak otomatik kuralları ile bir %= yerine = zaman belirleyici kural:

qi::rule<std::string::const_iterator,int(void),ascii::space_type> 
    intRule %= qi::int_;

IMHO, her eylem için bir fonksiyon yazmak oldukça sıkıcı, kısa ve okunabilir phoenix ifade benzerleri ile karşılaştırılabilir. Voodoo bakış açısı çok iyi anlıyorum, ama kısa bir süre için phoenix ile çalışmak için bir kez, anlambilim ve sözdizimi çok zor değil.

Edit: Erişim kuralı içerik w/ Phoenix

Bağlam değişkeni sadece çözümleyici bir kural bir parçası olduğunda tanımlanır. Bir kural çözümleyici değerleri çevirir nereye girdi tüketir herhangi bir ifadesi olarak bir çözümleyici, düşün (:: _1 qi) kuralı bir değer haline (:: _val qi). Fark qi çoğu zaman önemsiz olmayan, örneğin::val POD ayrıştırılmış değerler inşa edilmesi gereken bir Sınıf türü vardır. Aşağıda basit bir örnek.

Diyelim ki bir bölümüne girdi. bir sıra üç CSV tamsayı (x1, x2, x3), ve biz sadece tek bir aritmetik fonksiyonun bu üç tamsayı (f = x 0 (x1, x2)*x3 ), burada x 0 bir değer elde başka bir yerde. Bir seçenek sayıları okuma ve işlevi hesaplamak, veya alternatif olarak phoenix kullanın her ikisini de yapmak için.

Bu örneğin, bir çıkış öznitelik (fonksiyon değeri) ve giriş (x 0) ve yerel (kuralı ile bireysel ayrıştırıcıları arasında bilgi aktarmak için) ve tek bir kuralı kullanın. İşte tam örnek.

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <string>
#include <iostream>

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

int main(void){
   std::string input("1234, 6543, 42");
   std::string::const_iterator begin = input.begin(), end = input.end();

   qi::rule<
      std::string::const_iterator,
      int(int),                    //output (_val) and input (_r1)
      qi::locals<int>,             //local int (_a)
      ascii::space_type
   >
      intRule =
            qi::int_[qi::_a = qi::_1]             //local = x1
         >> ","
         >> qi::int_[qi::_a  = qi::_1]            //local = x1   x2
         >> ","
         >> qi::int_
            [
               qi::_val = qi::_a*qi::_1   qi::_r1 //output = local*x3   x0
            ];

   int ruleValue, x0 = 10;
   qi::phrase_parse(begin, end, intRule(x0), ascii::space, ruleValue);
   std::cout << "rule value: " << ruleValue << std::endl;
   return 0;
}

Alternatif olarak, tüm değer vermez olabilir ayrıştırılmış olarak bir vektör, ve fonksiyonunun değerlendirilmesi ile tek bir eylem semantik (% aşağıda listesi operatör ve elemanların vektör vardır erişilen ile phoenix::):

namespace ph = boost::phoenix;
...
    qi::rule<
        std::string::const_iterator,
        int(int),
        ascii::space_type
    >
    intRule =
        (qi::int_ % ",")
        [
            qi::_val = (ph::at(qi::_1,0)   ph::at(qi::_1,1))
                      * ph::at(qi::_1,2)   qi::_r1
        ];
....

Yukarıda, eğer giriş yanlış (iki in yerine üç), kötü bir şey olabilir zamanında, çok daha iyi olurdu sayısını belirlemek ayrıştırılmış değerler açık bir şekilde, yani ayrıştırma başarısız olur için kötü bir giriş. Aşağıda _1, _2 _3 referans birinci, ikinci ve üçüncü değeri ile eşleştirmek için kullanır:

(qi::int_ >> "," >> qi::int_ >> "," >> qi::int_)
[
    qi::_val = (qi::_1   qi::_2) * qi::_3   qi::_r1
];

Bu yapmacık bir örnektir, ama size bir fikir verecektir. Phoenix anlamsal eylemleri doğrudan giriş karmaşık nesneleri oluştururken çok yararlı buldum; bu anlamsal eylemleri içinde kurucular ve üye işlevleri çağırabilirsiniz çünkü bu mümkündür.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Charles Griffin Gibson

    Charles Grif

    26 NİSAN 2006
  • Doc Adams

    Doc Adams

    20 HAZİRAN 2007
  • New Scientist

    New Scientis

    27 Kasım 2006