Boost :: Spirit Access Position Iterator von semantischen Aktionen

Nehmen wir an, ich habe folgenden Code (Zeilennummern als Referenz):

1:
2:function FuncName_1 {
3:    var Var_1 = 3;
4:    var  Var_2 = 4;
5:    ...

Ich möchte eine Grammatik schreiben, die solchen Text analysiert, alle Indentifier (Funktions- und Variablennamen) -Infos in einen Baum (utree?) Setzt. Jeder Knoten sollte folgende Werte beibehalten: line_num, column_num und symbol value. Beispiel:

root: FuncName_1 (line:2,col:10)
  children[0]: Var_1 (line:3, col:8)
  children[1]: Var_1 (line:4, col:9)

Ich möchte es in den Baum einfügen, weil ich vorhabe, diesen Baum zu durchlaufen, und für jeden Knoten muss ich den 'Kontext' kennen: (alle Elternknoten der aktuellen Knoten).

Zum Beispiel muss ich bei der Verarbeitung von Knoten mit Var_1 wissen, dass dies ein Name für die lokale Variable für die Funktion FuncName_1 ist (die derzeit als Knoten verarbeitet wird, jedoch eine Ebene früher).

Ich kann nicht wenige Dinge herausfinden

Kann dies im Geist mit semantischen Handlungen und Utrees geschehen? Oder sollte ich varianten <> bäume verwenden?Wie werden diese drei Informationen (Spalte, Zeile, Symbolname) gleichzeitig an den Knoten übergeben? Ich weiß, dass ich pos_iterator als Iterator-Typ für die Grammatik verwenden muss, aber wie kann ich in sematischer Aktion auf diese Informationen zugreifen?

Ich bin ein Neuling in Boost, also lese ich die Spirit-Dokumentation immer und immer wieder. Ich versuche, meine Probleme zu googeln, aber irgendwie kann ich nicht alle Teile zusammenfügen, um die Lösung zu finden. Es scheint, als gäbe es noch niemanden, der einen solchen Anwendungsfall wie meinen hatte (oder ich kann ihn einfach nicht finden). Es sieht so aus, als ob die einzigen Lösungen mit Positionsiterator die mit Parsing-Fehlerbehandlung sind, aber das ist nicht der Fall, den ich habe. Ich bin daran interessiert. Der Code, der nur den Code analysiert, über den ich geschrieben habe, ist unten, aber ich weiß nicht, wie ich damit weitermachen soll.

  #include <boost/spirit/include/qi.hpp>
  #include <boost/spirit/include/support_line_pos_iterator.hpp>

  namespace qi = boost::spirit::qi;
  typedef boost::spirit::line_pos_iterator<std::string::const_iterator> pos_iterator_t;

  template<typename Iterator=pos_iterator_t, typename Skipper=qi::space_type>
  struct ParseGrammar: public qi::grammar<Iterator, Skipper>
  {
        ParseGrammar():ParseGrammar::base_type(SourceCode)
        {
           using namespace qi;
           KeywordFunction = lit("function");
           KeywordVar    = lit("var");
           SemiColon     = lit(';');

           Identifier = lexeme [alpha >> *(alnum | '_')];
           VarAssignemnt = KeywordVar >> Identifier >> char_('=') >> int_ >> SemiColon;
           SourceCode = KeywordFunction >> Identifier >> '{' >> *VarAssignemnt >> '}';
        }

        qi::rule<Iterator, Skipper> SourceCode;
        qi::rule<Iterator > KeywordFunction;
        qi::rule<Iterator,  Skipper> VarAssignemnt;
        qi::rule<Iterator> KeywordVar;
        qi::rule<Iterator> SemiColon;
        qi::rule<Iterator > Identifier;
  };

  int main()
  {
     std::string const content = "function FuncName_1 {\n var Var_1 = 3;\n var  Var_2 = 4; }";

     pos_iterator_t first(content.begin()), iter = first, last(content.end());
     ParseGrammar<pos_iterator_t> resolver;    //  Our parser
     bool ok = phrase_parse(iter,
                            last,
                            resolver,
                            qi::space);

     std::cout << std::boolalpha;
     std::cout << "\nok : " << ok << std::endl;
     std::cout << "full   : " << (iter == last) << std::endl;
     if(ok && iter == last)
     {
        std::cout << "OK: Parsing fully succeeded\n\n";
     }
     else
     {
        int line   = get_line(iter);
        int column = get_column(first, iter);
        std::cout << "-------------------------\n";
        std::cout << "ERROR: Parsing failed or not complete\n";
        std::cout << "stopped at: " << line  << ":" << column << "\n";
        std::cout << "remaining: '" << std::string(iter, last) << "'\n";
        std::cout << "-------------------------\n";
     }
     return 0;
  }

Antworten auf die Frage(1)

Ihre Antwort auf die Frage