Tokenizer



  • Man schaue sich das hier einmal an:

    So wird es im Code definiert:

    case '}':
          readNextChar();
          Toki.push_back(TT_LBRACE);
          return Token(TT_LBRACE);
        case '{':
          readNextChar();
          Toki.push_back(TT_RBRACE);
          return Token(TT_RBRACE);
    

    Lets twist it bei der Ausgabe:

    Eingabe: "class a {"
    
    TT_CLASS = 0
    TT_STRING = 0
    TT_LBRACE = 0
    

    TT_LBRACE sollte eigentlich nach dem Code TT_RBRACE heißen...



  • Hast du nicht irgendwas vergessen..?



  • [Rewind] schrieb:

    Hast du nicht irgendwas vergessen..?

    Kp sag mir was?


  • Mod

    Enno schrieb:

    [Rewind] schrieb:

    Hast du nicht irgendwas vergessen..?

    Kp sag mir was?

    Kennst du diese Kurzgeschichten, die mitten in der Handlung losgehen und man weiß nie, worum es überhaupt geht?



  • 1. Um was geht es hier? Ich verstehe nicht, was du sagen willst.
    2. Ich sehe gar keine Frage.



  • Ich denke er bezieht sich auf das hier.

    @Enno: Hast du dass schon mal mit dem Debugger verfolgt?



  • Na meine Frage ist doch wohl klar? ... Wieso werden einfach meine Zeichen falsch interpretiert? Der vertauscht doch da was?

    Wollte nicht die ganz Funktion posten aber ok:

    Token Scanner::getNextToken(){  //stings -> class/public/function/name
      std::string buf;
      skipSpaces();                          //to skip chars which are not used
      switch(myCh){
        case '(':
          readNextChar();
          Toki.push_back(TT_LBRACKET);
          return Token(TT_LBRACKET);
        case ')':
          readNextChar();
          Toki.push_back(TT_RBRACKET);
          return Token(TT_RBRACKET);
        case '}':
          readNextChar();
          Toki.push_back(TT_RBRACE);
          return Token(TT_RBRACE);
        case '{':
          readNextChar();
          Toki.push_back(TT_LRBRACE);
          return Token(TT_LBRACE);
        case ',':
          readNextChar();
          Toki.push_back(TT_COMMA);
          return Token(TT_COMMA);
        case ';':
          readNextChar();
          Toki.push_back(TT_SEMI);
          return Token(TT_SEMI);
        case ':':
          readNextChar();
          Toki.push_back(TT_COLON);
          return Token(TT_COLON);
        case '.':
          readNextChar();
          Toki.push_back(TT_DOT);
          return Token(TT_DOT);
        case '"':
          readNextChar();
          Toki.push_back(TT_QUOTE);
          return Token(TT_QUOTE);
                                            //read as long its a letter
        case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': 
          while(isalpha(myCh)){
    	buf += myCh;   
    	readNextChar();
    	if(buf == "class"){
    	  buf += myCh;
    	  readNextChar();   
    	  Toki.push_back(TT_CLASS);
    	  return Token(TT_CLASS);
    	}
    	if(buf == "function"){
    	  buf += myCh;
    	  readNextChar();   
    	  Toki.push_back(TT_FUNC);
    	  return Token(TT_FUNC);
    	}
    	if(buf == "public"){
    	  buf += myCh;
    	  readNextChar();   
    	  Toki.push_back(TT_PUBLIC);
    	  return Token(TT_PUBLIC);
    	}
          }   
          Toki.push_back(TT_STRING);
          return Token(TT_STRING);
    
        default:
          if(myCh != 0){
    	std::cerr << "Error: not used Char '" << myCh << "'" << std::endl;
          }      
          break;
      }  
      return Token(TT_NIL);
    };
    
    Token::Token(TokenType type, int value) : myType(type), myValue(value){
    }
    
    enum TokenType{                           // token definition
      TT_LBRACKET,
      TT_RBRACKET,
      TT_LBRACE,
      TT_RBRACE,
      TT_COMMA,
      TT_SEMI,
      TT_COLON,
      TT_DOT,
      TT_PUBLIC,
      TT_FUNC,
      TT_CONS,
      TT_QUOTE,
      TT_STRING,
      TT_CLASS,
      TT_NIL
    };
    
    Eingabe: "class a {" <-- meine Eingabe die in Token unten ausgegeben wird.
    
    TT_CLASS = 0
    TT_STRING = 0
    TT_LBRACE = 0 <-- das ist falsch laut meinem Code oben sollte das doch TT_RBRACE sein? Es wird als "}" und nicht als "{" zu einem Token gebaut.
    

    Wenn ihr noch mehr Infos haben wollte ich kann auch gerne den ganzen kram posten. Aber ich denke eigentlich müsste das Problem doch klar werden.



  • Tobias Gerg schrieb:

    Ich denke er bezieht sich auf das hier.

    @Enno: Hast du dass schon mal mit dem Debugger verfolgt?

    Ich hab ehrlich gesagt keine Ahnung wie man das macht.



  • case '{':
          readNextChar();
          Toki.push_back(TT_LRBRACE);
          return Token(TT_LBRACE);
    

    Du pusht ein TT_LRBRACE in deinen Token Vektor und gibts TT_LBRACE als Token zurück...

    Btw.
    Kopiere deinen Code immer und schreib ihn nicht ab. Der Code aus deinem ersten Posting stimmt nämlich nicht mit dem Code aus deinem zweiten Posting überein.

    case '{':
          readNextChar();
          Toki.push_back(TT_RBRACE);
          return Token(TT_RBRACE);
    

    Wenn du nicht weißt wie man einen Debugger benutzt dann frag mal deinen Betreuer. Der Debugger ist das wohl wichtigste Werkzeug des Softwareentwicklers.



  • Tobias Gerg schrieb:

    case '{':
          readNextChar();
          Toki.push_back(TT_LRBRACE);
          return Token(TT_LBRACE);
    

    Du pusht ein TT_LRBRACE in deinen Token Vektor und gibts TT_LBRACE als Token zurück...

    Ja das tue ich. Allerdings behebt das nicht mein Problem. Das in den Vector pushen brauch ich wo anders. Hat mit dieser Sache nichts zu tun steht da nun aber mit.

    Tobias Gerg schrieb:

    Btw.
    Kopiere deinen Code immer und schreib ihn nicht ab. Der Code aus deinem ersten Posting stimmt nämlich nicht mit dem Code aus deinem zweiten Posting überein.

    case '{':
          readNextChar();
          Toki.push_back(TT_RBRACE);
          return Token(TT_RBRACE);
    

    Ups ja stimmt. War nicht abgeschrieben ich hab es nur einmal geändert. Problem ist das gleiche.

    case '}':
          readNextChar();
      //    Toki.push_back(TT_RBRACE);
          return Token(TT_RBRACE);
        case '{':
          readNextChar();
      //    Toki.push_back(TT_LBRACE);
          return Token(TT_LBRACE);
    

    Ausgabe:

    Eingabe: "class a {"
    
    TT_CLASS = 0
    TT_STRING = 0
    TT_RBRACE = 0
    

    Für meinen case '{' hab ich ihm gesagt soll er TT_LBRACE returnen, er gibt mir aber TT_RBRACE, also den return von case '}'. Umgekehrt allerdings auch. Also vom prinzip macht er das alles richtig nur vertauscht der die einfach. Das gleiche passiert btw auch bei case '(' und case ')', werden auch vertauscht. Versteh ich nicht.

    EDIT:

    Tobias Gerg schrieb:

    Wenn du nicht weißt wie man einen Debugger benutzt dann frag mal deinen Betreuer. Der Debugger ist das wohl wichtigste Werkzeug des Softwareentwicklers.

    Ok werde ich mal machen.



  • Enno schrieb:

    ...
    Für meinen case '{' hab ich ihm gesagt soll er TT_LBRACE returnen, er gibt mir aber TT_RBRACE, also den return von case '}'. Umgekehrt allerdings auch. Also vom prinzip macht er das alles richtig nur vertauscht der die einfach. Das gleiche passiert btw auch bei case '(' und case ')', werden auch vertauscht. Versteh ich nicht.
    ...

    Wenn ich mich recht entsinne, kommt die Ausgabe doch über eine toString Methode oder ähnliches.

    Steht vielleicht in deinem const char* Array an der Stelle von TT_LBRACE ein "TT_RBRACE"?

    Greets
    Tobi



  • Das könnte hilfreich sein: http://www.c-plusplus.net/forum/304133.



  • ich bins schrieb:

    Das könnte hilfreich sein: http://www.c-plusplus.net/forum/304133.

    🙄 Ok

    .h:

    #ifndef OOPJS_H
    #define OOPJS_H
    
    #include <iostream> 
    #include <string> 
    #include <vector>
    
    enum TokenType{                           // token definition
      TT_LBRACKET,
      TT_RBRACKET,
      TT_LBRACE,
      TT_RBRACE,
      TT_COMMA,
      TT_SEMI,
      TT_COLON,
      TT_DOT,
      TT_PUBLIC,
      TT_FUNC,
      TT_CONS,
      TT_QUOTE,
      TT_STRING,
      TT_CLASS,
      TT_NIL
    };
    
    static const char *TokenTypStr[] = {     // for error message
      "TT_RBRACKET",
      "TT_LBRACKET",
      "TT_RBRACE",
      "TT_LBRACE",
      "TT_COMMA",
      "TT_SEMI",
      "TT_COLON",
      "TT_DOT",
      "TT_PUBLIC",
      "TT_FUNC",
      "TT_CONS",
      "TT_QUOTE",
      "TT_STRING",
      "TT_CLASS",
      "TT_NIL"
    };
    
    class Token{
    private:
      TokenType myType;
      int myValue;
    public:
      Token(TokenType type = TT_NIL, int value = 0);
      TokenType getType() const { return myType; }
      int getValue() const { return myValue; }
      const char *toString() const { return TokenTypStr[myType]; }  // error message
      bool equal(TokenType type) const { return myType == type; }         //comparison
    };
    
    class Scanner{
    public:
      void print(const std::string& s);
      void veci();
      Scanner(const std::string& input);
      Token getNextToken();
    private:
      std::vector<TokenType> Toki;
      std::string myInput;
      unsigned int myPos;                                            //Position at input
      char myCh;                                                     //last char
      void skipSpaces();
      void readNextChar();
    };
    #endif
    

    .cpp:

    #include "oopjs.h"
    
    #include <algorithm> 
    #include <vector> 
    #include <string> 
    #include <iostream> 
    #include <iterator>
    
    void Scanner::veci(){
      copy(Toki.begin(), Toki.end(), std::ostream_iterator<TokenType> (std::cout, "\n"));
    }
    
    // SCANNER from here
    
    void Scanner::readNextChar(){
      if(myPos > myInput.length()){
        myCh = 0;
        return;
      }
      myCh = myInput[myPos++];
    }
    
    void Scanner::skipSpaces(){
      while(myCh == ' ' || myCh == '\t' || myCh == '\r' || myCh == '\n'){
        readNextChar();
      }
    }
    
    Scanner::Scanner(const std::string& input) : myInput(input), myPos(0){
      readNextChar();
    }
    
    Token Scanner::getNextToken(){  //stings -> class/public/function/name
      std::string buf;
      skipSpaces();                          //to skip chars which are not used
      switch(myCh){
        case '(':
          readNextChar();
          Toki.push_back(TT_LBRACKET);
          return Token(TT_LBRACKET);
        case ')':
          readNextChar();
          Toki.push_back(TT_RBRACKET);
          return Token(TT_RBRACKET);
        case '}':
          readNextChar();
      //    Toki.push_back(TT_RBRACE);
          return Token(TT_RBRACE);
        case '{':
          readNextChar();
      //    Toki.push_back(TT_LBRACE);
          return Token(TT_LBRACE);
        case ',':
          readNextChar();
          Toki.push_back(TT_COMMA);
          return Token(TT_COMMA);
        case ';':
          readNextChar();
          Toki.push_back(TT_SEMI);
          return Token(TT_SEMI);
        case ':':
          readNextChar();
          Toki.push_back(TT_COLON);
          return Token(TT_COLON);
        case '.':
          readNextChar();
          Toki.push_back(TT_DOT);
          return Token(TT_DOT);
        case '"':
          readNextChar();
          Toki.push_back(TT_QUOTE);
          return Token(TT_QUOTE);
                                            //read as long its a letter
        case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': 
          while(isalpha(myCh)){
    	buf += myCh;   
    	readNextChar();
    	if(buf == "class"){
    	  buf += myCh;
    	  readNextChar();   
    	  Toki.push_back(TT_CLASS);
    	  return Token(TT_CLASS);
    	}
    	if(buf == "function"){
    	  buf += myCh;
    	  readNextChar();   
    	  Toki.push_back(TT_FUNC);
    	  return Token(TT_FUNC);
    	}
    	if(buf == "public"){
    	  buf += myCh;
    	  readNextChar();   
    	  Toki.push_back(TT_PUBLIC);
    	  return Token(TT_PUBLIC);
    	}
          }   
          Toki.push_back(TT_STRING);
          return Token(TT_STRING);
    
        default:
          if(myCh != 0){
    	std::cerr << "Error: not used Char '" << myCh << "'" << std::endl;
          }      
          break;
      }  
      return Token(TT_NIL);
    };
    
    Token::Token(TokenType type, int value) : myType(type), myValue(value){
    }
    

    main:

    #include <iostream> 
    #include <string> 
    #include "oopjs.h" 
    
    int main(){  
      std::string input = R"(class a {public:   function hello(){    console.log("hello");  }};class b {public:  function bye(){     console.log("bye");  }};class c : public a,b{public:  function greet(){ console.log("greeting");  }} )";
      std::cout << "Eingabe: \"" << input << "\"\n" << std::endl; 
      Scanner scanner(input); 
      Token tok = scanner.getNextToken(); 
      while (!tok.equal(TT_NIL)){ 
        std::cout << tok.toString() << " = " << tok.getValue() << std::endl; 
        tok = scanner.getNextToken(); 
      } 
      scanner.veci();
    }
    

    Problem ist ja schon beschrieben oder Frage.



  • enum TokenType{                           // token definition 
      TT_LBRACKET, 
    // ...
    }; 
    
    static const char *TokenTypStr[] = {     // for error message 
      "TT_RBRACKET", 
    // ...
    };
    

    Augen auf im Stadtverkehr ;)...
    Schau mal auf Zeile 1 im Enum und Zeile 1 im array

    Greets
    Tobi



  • Danke. Ich hab halt einfach angenommen das die reinfolge da vollkommen Wurst ist. Naja wissen ist die macht. 😃



  • Enno schrieb:

    ...Ich hab halt einfach angenommen das die reinfolge da vollkommen Wurst ist. ...

    Dann solltest du dir schleunigst nochmal ein Grundlagenbuch schnappen. Die Reihenfolge in Array Deklarationen in Verbindung mit Enums ist nie egal, da der Enum als Index für das Array genommen wird.

    Greets
    Tobi



  • Tobias Gerg schrieb:

    Enno schrieb:

    ...Ich hab halt einfach angenommen das die reinfolge da vollkommen Wurst ist. ...

    Dann solltest du dir schleunigst nochmal ein Grundlagenbuch schnappen. Die Reihenfolge in Array Deklarationen in Verbindung mit Enums ist nie egal, da der Enum als Index für das Array genommen wird.

    Greets
    Tobi

    Also mal ehrlich. Solche Bücher legt man nach 10min wieder weg. Ich hab viel mehr durch dieses Forum gelernt und durch den Compiler. Fehler machen, Fehler finden und man hat es gelernt. Hasst mich dafür! 🤡
    Bücher hab ich btw. 🕶



  • Enno schrieb:

    Tobias Gerg schrieb:

    Enno schrieb:

    ...Ich hab halt einfach angenommen das die reinfolge da vollkommen Wurst ist. ...

    Dann solltest du dir schleunigst nochmal ein Grundlagenbuch schnappen. Die Reihenfolge in Array Deklarationen in Verbindung mit Enums ist nie egal, da der Enum als Index für das Array genommen wird.

    Greets
    Tobi

    Also mal ehrlich. Solche Bücher legt man nach 10min wieder weg. Ich hab viel mehr durch dieses Forum gelernt und durch den Compiler. Fehler machen, Fehler finden und man hat es gelernt. Hasst mich dafür! 🤡
    Bücher hab ich btw. 🕶

    Wenn man sich deine Fragen anschaut, dann ist dein Wissensstand mehr als schockierend. Trial & Error ist gerade bei C++ total gefährlich, da es funktionieren kann, obwohl es absolut falsch ist.

    Aber na ja, mach mal...



  • Tobias Gerg schrieb:

    Wenn du nicht weißt wie man einen Debugger benutzt dann frag mal deinen Betreuer.

    LOL, ich kenne betreutes Wohnen und betreutes Trinken (hab ich mit einem Freund praktiziert ;)), aber betreutes Programmieren war mir neu.



  • EOP schrieb:

    Tobias Gerg schrieb:

    Wenn du nicht weißt wie man einen Debugger benutzt dann frag mal deinen Betreuer.

    LOL, ich kenne betreutes Wohnen und betreutes Trinken (hab ich mit einem Freund praktiziert ;)), aber betreutes Programmieren war mir neu.

    Ausbilder im Nacken. xD


Log in to reply