Page 1 of 1

Is this a compiler or logic bug?

Posted: Thu Mar 17, 2022 2:47 pm
by Ethin
For my CS degree I have to take a class on interpreter and compiler design. This semester we're doing the compiler portion, and we're designing a mini-pascal top-down compiler. Part of that includes determining whether a datatype is a valid datatype among the possibilities of integer, char, and boolean. We're doing it as a top-down compiler, so I designed my datatype() function like so:

Code: Select all

void Parser::datatype() {
    if (token->index() == Word) {
        if (auto dtype = std::get<0>(*token);
            dtype != "integer" || dtype != "char" || dtype != "boolean") {
            throw std::runtime_error("Bad code: unknown data type");
        }
    }
}
(As a side-note, this is C++20 with the token type being an std::variant of four strings. I could probably do away with the std::variant altogether and just use a string, but I decided not to. Also, the token member variable is an std::optional<std::variant<...>> to solve the possibility of no tokens remaining in the token stream.) The problem I'm facing is that when the parser encounters this line of pascal:

Code: Select all

var x, y, z : integer;
It bails out on the "integer" part. Using gdb I've determined that, yes, the token being scanned is "integer", all lower-case, and without any whitespace or other invalidating characteristics. However, the function still throws the exception, despite the condition (in all three cases) being false (which should cause it to immediately return as though it were an epsilon). I've compiled this using clang, but I'm curious if this is a logic error on my part or a bug in the compiler? I doubt the "bug in the compiler" case but I'm utterly flummoxed as to why the exception is being triggered when its condition is false, and therefore, it should not be triggering. Do you guys have any advice to solving problems like this that appear to be utterly nonsensical?
If you require more code, I can publish this on GH, but I admit that the code is not the cleanest and probably not the most efficient, and if this were production code I'd write it at a much higher quality and standard. And if I were allowed to use parser generators like any sane person, I'd happily do that, but my professor says "no" to parser generators or a library like PEGTL, so... Anyway, I'm stuck on this issue, and can't find what's actually causing it, because everything appears to be fine in a debugger.

Re: Is this a compiler or logic bug?

Posted: Thu Mar 17, 2022 3:53 pm
by Minoto

Code: Select all

dtype != "integer" || dtype != "char" || dtype != "boolean"
Isn't this always going to be true?

Re: Is this a compiler or logic bug?

Posted: Thu Mar 17, 2022 3:56 pm
by thewrongchristian
Ethin wrote:

Code: Select all

void Parser::datatype() {
    if (token->index() == Word) {
        if (auto dtype = std::get<0>(*token);
            dtype != "integer" || dtype != "char" || dtype != "boolean") {
            throw std::runtime_error("Bad code: unknown data type");
        }
    }
}
Aren't you after something more like:

Code: Select all

void Parser::datatype() {
    if (token->index() == Word) {
        auto dtype = std::get<0>(*token);
        if (dtype != "integer" || dtype != "char" || dtype != "boolean") {
            throw std::runtime_error("Bad code: unknown data type");
        }
    }
}
Your "auto dtype = std::get<0>(*token);" is within the "if (...)", and I suspect the assignment is resulting in the if condition being true, and so you throw your exception.

Re: Is this a compiler or logic bug?

Posted: Thu Mar 17, 2022 4:11 pm
by Ethin
thewrongchristian wrote:
Ethin wrote:

Code: Select all

void Parser::datatype() {
    if (token->index() == Word) {
        if (auto dtype = std::get<0>(*token);
            dtype != "integer" || dtype != "char" || dtype != "boolean") {
            throw std::runtime_error("Bad code: unknown data type");
        }
    }
}
Aren't you after something more like:

Code: Select all

void Parser::datatype() {
    if (token->index() == Word) {
        auto dtype = std::get<0>(*token);
        if (dtype != "integer" || dtype != "char" || dtype != "boolean") {
            throw std::runtime_error("Bad code: unknown data type");
        }
    }
}
Your "auto dtype = std::get<0>(*token);" is within the "if (...)", and I suspect the assignment is resulting in the if condition being true, and so you throw your exception.
I don't think so. According to this page, the C++ standard (in C++17/20) allows an init-statement in a conditional statement, which is identical to what you posted, but scoped within the if statement.

Re: Is this a compiler or logic bug?

Posted: Thu Mar 17, 2022 4:13 pm
by Ethin
Minoto wrote:

Code: Select all

dtype != "integer" || dtype != "char" || dtype != "boolean"
Isn't this always going to be true?
I mean... Maybe... I'm aiming for "if the data type is not either integer or char or boolean" or something along those lines. I could've created a container and then used something like

Code: Select all

if (!dtypes.contains(dtype)) {...}
but that seemed like a bit much for a simple check like this.

Re: Is this a compiler or logic bug?

Posted: Thu Mar 17, 2022 4:14 pm
by Octocontrabass
Use "&&" instead of "||" and it will work.

Re: Is this a compiler or logic bug?

Posted: Thu Mar 17, 2022 5:55 pm
by Ethin
Octocontrabass wrote:Use "&&" instead of "||" and it will work.
Oops? Pretty amateurish mistake, I suppose, but then again I guess we all do that. Thanks for all the help guys!