jheruty / hscpp

Runtime compiled C++ with hot-swapped classes.
MIT License
91 stars 5 forks source link

Failed to lex - Unterminated string, expected a '"' in my additional class #15

Closed szelected closed 3 years ago

szelected commented 3 years ago

I've got this error message during hot swap, and I don't know what to do with it. The standard compilation with VS2019 going well, only when I save an opengl widget that uses this additional class... please advise !

jheruty commented 3 years ago

Yes, this is an issue from the hscpp Lexer: https://github.com/jheruty/hscpp/blob/7850c3acb2a694422fb2fc06559c6819ef64f758/src/preprocessor/LangError.cpp#L12

Do you have preprocessing enabled?

Would it be possible to take a look at the code? Perhaps there are cases that produce an unterminated string that are valid C++, which I did not account for.

jheruty commented 3 years ago

edited:

At first I thought this might be incorrectly handled multiline strings, but the string parsing is intentionally simplistic to avoid this causing issues.

I think I would need to see the code that is causing the issue to diagnose this.

szelected commented 3 years ago

First of all Thank you for all of your work here and for your reply!

Please note that it was worked like a charm first time when I created the class.

It must be some kind of phrase error. The error code is : Unterminated string, expected a '"'. (Line: 73, Column: 1) My (additional) class file currently has only 73 lines and it's ending like this :

MusicPlayer.cpp :

67 void MusicPlayer::ShutDown() 68 { 69 // cleanup the audio stuff 70 //olc::SOUND::StopAll(); 71 //olc::SOUND::DestroyAudio(); 72 std::cout << "Music shutdown..." << std::endl; 73 }

yep! in the main.cpp I did call the : swapper.EnableFeature(hscpp::Feature::Preprocessor); Otherwise in the xyzWidget.cpp (using MusicPlayer class) the hot swap doesn't compile my widget dispite it has the require as well like this:

in the TimeLineWidget.cpp : hscpp_require_include_dir("../include") hscpp_require_source("./MusicPlayer.cpp")

I don't need to track this MusicPlayer.cpp, I just need as dependency and I did manage to access to this class using global mem manager. in the widget: MusicPlayer *player = &Globals::MusicPlayer(); and it's worked for first time.

Once again, please note that it was worked like a charm first time when I created the MusicPlayer class.

next day did reload the project and I facing with this. I don't get it.

if you need, I can share the whole project as well...

Thanks in advance!

jheruty commented 3 years ago

Thank you for the additional details!

Unfortunately I don't see anything wrong with your code. The Lexer is behaving as though it saw an opening quotation, and then never saw the terminating one. This is why it gives you an error at the very end of the file, as at this point it realizes the string never closed.

If you could share the project that would be appreciated. You can email me at jheruty@gmail.com if you wish to keep this code private.

szelected commented 3 years ago

Thank you for your reply. Well, I think I did sorted out. Definitely it's my fault. I wrote a function called GetExePath used like this -> std::string exePath = this->GetExePath() + "\\"; The double backslash between quotes caused the issue and now it's working with single quotes '\\'

to be more specific:

MusicPlayer::MusicPlayer() {
    std::string exePath = this->GetExePath() + '\\';
    std::string mp3filename = exePath + "BODNB_01.mp3";
    bool initaudio = olc::SOUND::InitialiseAudio(44100, 2, 16, 1024);
    sample_id = olc::SOUND::LoadMp3FileSample(mp3filename);
    std::cout << "Music loaded..." << std::endl;
}

....

the get exepath it goes like this in my code:

std::string MusicPlayer::GetExePath() {
    TCHAR szExeFileName[MAX_PATH];
    GetModuleFileName(NULL, szExeFileName, MAX_PATH);
    std::string s = szExeFileName;
    return s.substr(0, s.find_last_of("\\/"));
    //return (std::string)"hello!";
}

seems to be whenever an std::string contains "\\" the hotswap stopping to work.

to replicate: simple make an std::string s = "\\"; - anywhere in your code. note that my character set is : Use Multi-Byte Character Set

Please let me know your thoughts.

jheruty commented 3 years ago

That's a great find, and is a bug in the Lexer code. What was going on is that I did not handle escaped backslashes, so the Lexer interpreted "\\" as a slash and then an escaped quote.

I have added the case where the backslash is escaped, merged into master.

Future improvements for this issue could be: 1) Better error message, telling you where the unterminated string began. 2) Reducing Lexing to only be done within hscpp macros and for #include statements.