frage zu compilieren/parser



  • hallo liebe freunde vom cplusplus forum 🙂

    möchte wissen, ob ich so einen Code mit Visual C++ 2005 express edition (damit arbeite ich zur Zeit) kompilieren kann. Ich habe es versucht, geht aber wg. "node.h" und "parser.hpp" nicht, kennt visual c++ 2005 nicht. Kann mir jemand helfen wie das richtig geht? Wäre super nett! Bin noch relativ neu mit Visual C++ und übe. Würde gerne verstehen, wie so ein Compiler läuft.

    #include <string>
    #include "node.h"
    #include "parser.hpp"
    #define SAVE_TOKEN yylval.string = new std::string(yytext, yyleng)
    #define TOKEN(t) (yylval.token = t)
    extern "C" int yywrap() { }
    
    [ \t\n]                 ;
    [a-zA-Z_][a-zA-Z0-9_]*  SAVE_TOKEN; return TIDENTIFIER;
    [0-9]+\.[0-9]*          SAVE_TOKEN; return TDOUBLE;
    [0-9]+                  SAVE_TOKEN; return TINTEGER;
    "="                     return TOKEN(TEQUAL);
    "=="                    return TOKEN(TCEQ);
    "!="                    return TOKEN(TCNE);
    "<"                     return TOKEN(TCLT);
    "<="                    return TOKEN(TCLE);
    ">"                     return TOKEN(TCGT);
    ">="                    return TOKEN(TCGE);
    "("                     return TOKEN(TLPAREN);
    ")"                     return TOKEN(TRPAREN);
    "{"                     return TOKEN(TLBRACE);
    "}"                     return TOKEN(TRBRACE);
    "."                     return TOKEN(TDOT);
    ","                     return TOKEN(TCOMMA);
    "+"                     return TOKEN(TPLUS);
    "-"                     return TOKEN(TMINUS);
    "*"                     return TOKEN(TMUL);
    "/"                     return TOKEN(TDIV);
    .                       printf("Unknown token!\n"); yyterminate();
    

    best grüße, ciao, Franziska



  • Die Header Dateien gehören nicht zu dem was an libs und Header Dateien mit dem Studio ausgeliefert wird. Sprich das ist irgendwas selbst gebasteltes.
    Sieht so aus als würde flex+bison als lib zum Parsen verwendet.

    Wo hast du den Code her? Evtl kann man dann mehr sagen.



  • möchte wissen, ob ich so einen Code mit Visual C++ 2005 express edition (damit arbeite ich zur Zeit) kompilieren kann.

    Nein!

    Das ist ist eine Datei fuer flex. Du musst daraus zuerst mittels flex eine richtige C-Datei generieren lassen und die mit deinem Compiler uebersetzen und linken. Als Tip: Tue es nicht mit Visual Studio.

    Würde gerne verstehen, wie so ein Compiler läuft.

    Das ist zu allgemein. Geht es auch konkreter?



  • hallo, danke erst mal für die Infos.

    Ich glaube, ich habe tatsächlich in der Schule so einen Parser Code für "Flex/Bison" (habe gegoogelt, obwohl ich nicht weiß, was ich damit genau machen soll, sorry!) kopiert und wollte damit herum experimentieren. Das war dumm, nicht wahr ? Möchte für ein Projekt wissen, wie ich eine ähnl. Art von "ParserCode" mit Visual Studio Express C++ hinbekomme. Ich arbeite damit und möchte es hinbekommen, ein paar Zahlen eingeben zum Kalkulieren und vielleicht ein paar Strings. Bin um Hilfe dankbar. Wir haben ein paar Grundkurse in C++ zur Einführung in Mathe durchgeführt, komme schon ganz gut klar damit. Jetzte hatte ich die Idee etwas eigenes auf zubauen mit einem Parser, der mir meine Kalkulationen berechnet, wie ich es gerne hätte. Deswegen dieser Code von meiner ersten Post, weil es gut aussah, dachte ich, es könnte klappen.

    beste Grüße, Franziska



  • Vom Ablauf ist es in etwa so:
    Du erzeugst 2 Dateien die die Struktur vom dem was geparst werden soll beschreiben. Das ist erstmal kein C-Code sondern eine spezielle Sprache für Flex bzw Bison.
    (Flex)Eine Datei beschreibt die gültigen Token. Z.B. für einen Formelparser würdest du sagen es gibt nur Zahlen (1..9), +, -.
    (Bison)Die 2. Datei definiert wie diese Token aufeinander folgen, z.B. 1+2 ist ok, 12+ wär falsch.

    Hast du diese beiden Dateien, kannst du mit Flex und Bison C-Code erzeugen. Den solltest du auch im Studio compilieren können.

    Du brauchst also die 2 Beschreibungsdateien und die Tools Flex und Bison, der Rest sollte einfach sein. Die Dateien selber zu erzeugen wird nicht so ohne weiteres möglich sein. Dazu wirst du dich wohl in die beiden Tools einarbeiten müssen.



  • danke ihoernchen 🙂

    habe einen guten Kalkulator in cpp gefunden, der funktioniert und wo ich draus lernen kann. Das mit flex und bison habe ich im Prinzip verstanden, aber das Ganze ist einfach zu hoch für mich im Moment zum verstehen 😉

    Du brauchst also die 2 Beschreibungsdateien und die Tools Flex und Bison, der Rest sollte einfach sein.

    meine dumme Frage: wozu ist denn so ein "Parser" besser geeignet als visual studio c++ ? Ich dachte, ich kann mit c++ alles programmieren, was machbar und möglich ist in dieser schönen windows-welt 🙂 ???

    calculator example:

    */
    
    #include <iostream>
    #include <sstream>
    #include <string>
    #include <map>
    #include <cctype>
    using namespace std;
    
    enum Token_value {
      NAME, NUMBER, END, INC, DEC,
      PLUS='+', MINUS='-', MUL='*', DIV='/',
      PRINT=';', ASSIGN='=', LP='(', RP=')'
    };
    
    Token_value curr_tok = PRINT;
    
    double number_value;
    string string_value;
    
    double expr(bool );
    double term(bool );
    double error(const string&);
    double prim(bool );
    Token_value get_token();
    
    map<string, double> table;
    
    double expr(bool get)
    {
      double left = term(get);
    
      for(;;)
        switch(curr_tok) {
        case PLUS:
          left += term(true);
          break;
        case MINUS:
          left -= term(true);
          break;
        default:
          return left;
        }
    }
    
    double term(bool get)
    {
      double left = prim(get);
    
      for(;;)
        switch(curr_tok) {
        case MUL:
          left *= prim(true);
          break;
        case DIV:
          if (double d = prim(true)) {
    	left /=d;
    	break;
          }
          return error("divide by 0");
        default:
          return left;
        }
    }
    
    double prim(bool get)
    {
      if(get) get_token();
    
      switch(curr_tok) {
      case NUMBER:
        {
          double v = number_value;
          get_token();
          return v;
        }
      case NAME:
        {
    
          double& v = table[string_value];
          get_token();
          if (curr_tok  == ASSIGN) 
            v = expr(true);
          if (curr_tok == INC)  //r++;
    	v = v+1;
          if (curr_tok == DEC)  //r++;
    	v = v-1;
          return v;
        }
      case INC:
        return prim(true)+1;
      case DEC:
        return prim(true)-1;
      case MINUS:
        return -prim(true);
      case LP:
        {
          double e=expr(true);
          if(curr_tok != RP) return error(" ')' expected");
          get_token();
          return e;
        }
      default:
        return error("primary expected");
      }
    }
    
    Token_value get_token()
    {
      char ch;
    
      do {
        if(!cin.get(ch)) return curr_tok = END;
      } while(ch!='\n' && isspace(ch));
    
      switch(ch) {
      case ';':
      case '\n':
        return curr_tok=PRINT;
      case 0:
        return curr_tok=END;
      case '+':    // added for ++name and name++
        {
          char c;
          if ( cin.get(c) && c == '+' )
    	return curr_tok=INC;
    
          cin.putback(c);
          return curr_tok=Token_value(ch);
        }
      case '-':
        {
          char c;
          if ( cin.get(c) && c == '-' )
    	return curr_tok=DEC;
    
          cin.putback(c);
          return curr_tok=Token_value(ch);
        }
      case '*':
      case '/':
      case '(':
      case ')':
      case '=':
        return curr_tok=Token_value(ch);
    
      case '0':case '1': case '2': case '3': case '4':
      case '5': case '6': case '7': case '8': case '9':
      case '.':
        cin.putback(ch);
        cin >> number_value;
        return curr_tok=NUMBER;
      default:
        if (isalpha(ch)){
          string_value=ch;
          while(cin.get(ch) && isalnum(ch)) string_value.push_back(ch);
          cin.putback(ch);
          return curr_tok=NAME;
        }
        error("bad token");
        return curr_tok=PRINT;
      }
    }
    
    int no_of_errors;
    
    double error(const string& s)
    {
      no_of_errors++;
      cerr << "error: " << s << '\n';
      return 1;
    }
    
    istream* input;
    
    int main(int argc, char* argv[])
    {
    
      switch(argc) {
      case 1:
        input = &cin;
        break;
      case 2:
        input = new istringstream(argv[1]);
        break;
      default:
        error("too man arguments");
        return 1;
      }
    
      table["pi"] = 3.1415926535897932385;
      table["e"] = 2.718281818284590452354;
    
      while(cin) {
        get_token();
        if( curr_tok == END) break;
        if( curr_tok == PRINT) continue;
        cout << expr(false) << '\n';
      }
    
      if(input != &cin) delete input;
      return no_of_errors;
    
    }
    

    schönen Tag noch und Fragen kommen noch, vielen dank, lg franziska



  • Franziska2009 schrieb:

    Du brauchst also die 2 Beschreibungsdateien und die Tools Flex und Bison, der Rest sollte einfach sein.

    meine dumme Frage: wozu ist denn so ein "Parser" besser geeignet als visual studio c++ ?

    Du meinst einen "Parsergenerator". Einen Parser kannst du natürlich in C++ schreiben, Bison kocht ja auch nur mit Wasser.

    Die Frage ist, ob man den Parser von Hand schreiben will oder ob man dazu einen Parsergenerator verwendet. Es hat beides Vor- und Nachteile, von Hand zu schreiben ist flexibler, aber dauert viel länger und ist fehlerträchtiger.

    Es gibt noch Abstufungen dazwischen, z.B. Boost Spirit.


Anmelden zum Antworten