Fehlende Zeichen



  • Ich hab ein Problem und zwar passiert es das Zeichen nicht ausgegeben werden. Oder gar überhaupt nicht ankommen.

    Eingabe: "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("greet");  }}"
    
    prototypestring{thisfunctionhello){consolestring("hello);}};prototypestring{thisfunctionbye){consolestring("bye);}};
    prototypestring:thisstring,string{thisfunctiongreet){consolestring("greet);}}
    

    Wie was übersetzt wird ist grade mal ziemlich Lachs. Problem ist bei dem "hello" zu erkennen. Oben in der Eingabe ist es in "" unten bei der Ausgabe ist nur das erste " vorhanden soll aber auch das hinter " da sein.

    Token Scanner::getNextToken(){  
      std::string buf;
      skipSpaces();                          //to skip chars which are not used
      switch(myCh){
        case '(':
          readNextChar();
           Trans.push_back('(');
          return Token(TT_LBRACKET);
        case ')':
          readNextChar();
          Trans.push_back(')');
          return Token(TT_RBRACKET);
        case '}':
          readNextChar();
          Trans.push_back('}');
          return Token(TT_RBRACE);
        case '{':
          readNextChar();
          Trans.push_back('{');
          return Token(TT_LBRACE);
        case ',':
          readNextChar();
          Trans.push_back(',');
          return Token(TT_COMMA);
        case ';':
          readNextChar();
          Trans.push_back(';');
          return Token(TT_SEMI);
        case ':':
          readNextChar();
          Trans.push_back(':');
          return Token(TT_COLON);
        case '.':
          readNextChar();
          Trans.push_back('.');
          return Token(TT_DOT);
        case '"':
          readNextChar();
           Trans.push_back('"');
          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();
     	char Sel(myCh);
    	if(buf == "class"){
    	  buf += myCh;
    	  readNextChar();   
     	  std::copy("prototype","prototype"+9,std::back_inserter(Trans));
     /* Problem tritt immer nach diesen aufrufen statt +10 
    hilft dort auch nicht 
    Allerdings klappt es auch nicht wenn ich diese raus nehme und 
    einfach stumpf nur ein zeichen return*/
    	  return Token(TT_CLASS);
    	}
    	if(buf == "function"){
    	  buf += myCh;
    	  readNextChar();    
     	  std::copy("function","function"+8,std::back_inserter(Trans)); //
    	  return Token(TT_FUNC);
    	}
    	if(buf == "public"){
    	  buf += myCh;
    	  readNextChar();   
     	  std::copy("this","this"+4,std::back_inserter(Trans));//
    	  return Token(TT_PUBLIC);
    	}
    	if(buf == "hello"){
    	  buf += myCh; 
     	  std::copy("hello","hello"+5,std::back_inserter(Trans));//
    	  readNextChar(); 
    	  return Token(TT_HELLO);
    	}
    	if(buf == "bye"){
    	  buf += myCh;
    	  readNextChar();   
     	  std::copy("bye","bye"+3,std::back_inserter(Trans));//
    	  return Token(TT_BYE);
    	}
    	if(buf == "greet"){
    	  buf += myCh;
    	  readNextChar();   
     	  std::copy("greet","greet"+5,std::back_inserter(Trans));//
    	  return Token(TT_GREET);
    	}
    	if(buf == "console"){
    	  buf += myCh; 
    	  readNextChar();   
     	  std::copy("console","console"+7,std::back_inserter(Trans));//
    	  return Token(TT_CONS);
    	}
          }   
          std::copy("string","string"+6,std::back_inserter(Trans));//
          return Token(TT_STRING);
    
        default:
          if(myCh != 0){
    	std::cerr << "Error: not used Char '" << myCh << "'" << std::endl;
          }      
          break;
      }  
      return Token(TT_NIL);
    };
    
    #ifndef OOPJS_H
    #define OOPJS_H
    
    #include <iostream> 
    #include <string> 
    #include <vector>
    #include <map>
    
    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_HELLO,
      TT_BYE,
      TT_GREET,
      TT_NIL
    };
    
    static const char *TokenTypStr[] = {     // for error message
      "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_HELLO",
      "TT_BYE",
      "TT_GREET",
      "TT_NIL"
    };
    
    class Token{
    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
    private:
      TokenType myType;
      int myValue;
    };
    
    class Scanner{
    public:
      void veci();
      void veci2();  
      Scanner(const std::string& input);
      Token getNextToken();
      void TranslateVeci();
    private:
    //  std::map<TokenType, char> Save;
      std::vector<char> Trans;
      std::string myInput;
      unsigned int myPos;                                            //Position at input
      char myCh;                                                     //last char
      void skipSpaces();
      void readNextChar();
    };
    
    #endif
    
    #include <iostream> 
    #include <fstream>
    #include <string> 
    #include "oopjs.h" 
    
    int main(){  
      std::ifstream open("../testunits/test.js");
      if(!open){
        std::cerr << "not open" << std::endl;
      }
      std::string input;
      std::string save;
      while(!open.eof()){ 
        getline(open,save);
        input.append(save);
      }
      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.veci2();
    }
    


  • Diese Sequenz in Zeile 51:

    std::copy("prototype","prototype"+9,std::back_inserter(Trans));
     /* Problem tritt immer nach diesen aufrufen statt +10
    hilft dort auch nicht
    Allerdings klappt es auch nicht wenn ich diese raus nehme und
    einfach stumpf nur ein zeichen return*/
    

    erzeugt ein undefiniertes Verhalten. Die beiden Strings "prototype" sind verschieden, auch wenn sie den selben Inhalt haben.

    Besser:

    const char* prototype_str = "prototype";
    std::copy( prototype_str, prototype_str + std::char_traits< char >::length( prototype_str ), std::back_inserter(Trans) );
    


  • Werner_logoff schrieb:

    Diese Sequenz in Zeile 51:

    std::copy("prototype","prototype"+9,std::back_inserter(Trans));
     /* Problem tritt immer nach diesen aufrufen statt +10
    hilft dort auch nicht
    Allerdings klappt es auch nicht wenn ich diese raus nehme und
    einfach stumpf nur ein zeichen return*/
    

    erzeugt ein undefiniertes Verhalten. Die beiden Strings "prototype" sind verschieden, auch wenn sie den selben Inhalt haben.

    Besser:

    const char* prototype_str = "prototype";
    std::copy( prototype_str, prototype_str + std::char_traits< char >::length( prototype_str ), std::back_inserter(Trans) );
    

    Sehr guter Tipp danke.
    Allerdings ändert das nichts.
    Vielleicht sollte ich noch erwähnen das es genau so wie es ist funktioniert HAT. Allerdings kam dann 3-4 mal beim compilieren ein Fehler und ich habe NICHTS geändert. Auf einmal funktioniert es wieder und es fehlen Zeichen. Das klingt irgendwie komisch. 😃 Ich werde noch mal eine neue Datei machen und es dort rein schreiben vielleicht hilft dies. So viel schon damit rum probiert. 😃



  • Du musst diese Änderung für alle Aufrufe vornehmen, die so aufgebaut sind.



  • ghjghj schrieb:

    Du musst diese Änderung für alle Aufrufe vornehmen, die so aufgebaut sind.

    Bringt nichts.



  • Vermutlich liest du beim Einlesen von class, hello, usw. am Ende ein Zeichen zu viel ein und es geht daher verloren.



  • fghfghfgh schrieb:

    Vermutlich liest du beim Einlesen von class, hello, usw. am Ende ein Zeichen zu viel ein und es geht daher verloren.

    Das hello Token ist nicht das Problem sonder oben die Zeichen Token( " . : ; () {} ). Die gehen verloren.



  • Enno schrieb:

    Das hello Token ist nicht das Problem sonder oben die Zeichen Token( " . : ; () {} ). Die gehen verloren.

    doch ist es:

    if(buf == "hello"){ 
      buf += myCh; 
      std::copy("hello","hello"+5,std::back_inserter(Trans));// 
      readNextChar(); 
      return Token(TT_HELLO); 
    }
    

    hier ignorierst du das erste zeichen nach hello (welches gerade in myCh steht)



  • hello schrieb:

    Enno schrieb:

    Das hello Token ist nicht das Problem sonder oben die Zeichen Token( " . : ; () {} ). Die gehen verloren.

    doch ist es:

    if(buf == "hello"){ 
      buf += myCh; 
      std::copy("hello","hello"+5,std::back_inserter(Trans));// 
      readNextChar(); 
      return Token(TT_HELLO); 
    }
    

    hier ignorierst du das erste zeichen nach hello (welches gerade in myCh steht)

    Könntest du das vielleicht noch einmal genauer sagen?
    Oh hab es. 😃

    if(buf == "hello"){ 
      std::copy( hello_str, hello_str + std::char_traits< char >::length( hello_str ), std::back_inserter(Trans) );  
      return Token(TT_HELLO); 
    }
    


  • Für diese Text-Tokens solltest du wirklich eine std::map o. ä. nutzen.

    theMap["public"] = TT_PUBLIC;
    theMap["class"] = TT_CLASS;
    
    if (theMap.find(buf) != theMap.end())
    {
     std::copy(theMap[buf].second.begin(), theMap[buf].second.end(), std::back_inserter(Trans))
    
     return Token(theMap[buf].first);
    }
    

    Ungetestet und ohne größere Überlegung dahingeschrieben, es geht einfach um das Prinzip...



  • hjkhjk schrieb:

    Für diese Text-Tokens solltest du wirklich eine std::map o. ä. nutzen.

    theMap["public"] = TT_PUBLIC;
    theMap["class"] = TT_CLASS;
    
    if (theMap.find(buf) != theMap.end())
    {
     std::copy(theMap[buf].second.begin(), theMap[buf].second.end(), std::back_inserter(Trans))
    
     return Token(theMap[buf].first);
    }
    

    Ungetestet und ohne größere Überlegung dahingeschrieben, es geht einfach um das Prinzip...

    Danke für die Anregung, schau ich mir mal an und guck ob draus was wird.


Log in to reply