Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ignore casts when evaluating #defines #86

Open
d3dave opened this issue Apr 29, 2024 · 3 comments
Open

Ignore casts when evaluating #defines #86

d3dave opened this issue Apr 29, 2024 · 3 comments
Labels
enhancement New feature or request

Comments

@d3dave
Copy link
Contributor

d3dave commented Apr 29, 2024

For example:

#define A ((unsigned long) 1)
#define B ((unsigned long) 2)
#define C (A | B)

causes A, B and C to have string values like "(A | B)" instead of the numeric values.

@d3dave d3dave changed the title Missing context when evaluating #defines Ignore casts when evaluating #defines Apr 29, 2024
@Schamper Schamper added the enhancement New feature or request label May 6, 2024
@Schamper
Copy link
Member

Schamper commented May 6, 2024

This looks very fixable. Probably requires dealing with casts in the expression parser though.

@sMezaOrellana can you perhaps recommend the best way to add this to your parser?

@sMezaOrellana
Copy link
Contributor

I will try to have a proper look in the coming days.
In order implement or deal with type-casting it will require changing the evaluate function.

    def evaluate(self, context: Optional[dict[str, int]] = None) -> int:
        """Evaluates an expression using a Shunting-Yard implementation."""

        ...
        while i < len(tmp_expression):
            current_token = tmp_expression[i]
            ...
            elif current_token == "sizeof":
                if len(tmp_expression) < i + 3 or (tmp_expression[i + 1] != "(" or tmp_expression[i + 3] != ")"):
                    raise ExpressionParserError("Invalid sizeof operation")
                self.queue.append(len(self.cstruct.resolve(tmp_expression[i + 2])))
                i += 3
            ...
            elif current_token == "(":
                if i > 0:
                    previous_token = tmp_expression[i - 1]
                    if self.is_number(previous_token):
                        raise ExpressionParserError(
                            f"Parser expected sizeof or an arethmethic operator instead got: '{previous_token}'"
                        )

                self.stack.append(current_token)
            elif current_token == ")":
                if i > 0:
                    previous_token = tmp_expression[i - 1]
                    if previous_token == "(":
                        raise ExpressionParserError(
                            f"Parser expected an expression, instead received empty parenthesis. Index: {i}"
                        )

        ...
        while len(self.stack) != 0:
            if self.stack[-1] == "(":
                raise ExpressionParserError("Invalid expression")

            self.evaluate_exp()

        return self.queue[0]

Take for example ((unsigned long) 10) this is something like an expression with the left-hand side being (unsigned long) and the right-hand side being 10, there is no explicit operator.

This could simply evaluate to 10. In practise a simple solution would be to change the case where elif current_token == "(": and elif current_token == ")":. If whatever is between ( and ) is a casting expression just skip over it. It's not very pretty but it would work. In order to actually implement casting we would need to extend the parser, to support evaluating the casting expression.

Does cstruct implement casting?

I hope this helps. And will look at this properly sometime this week.

@Schamper
Copy link
Member

Schamper commented May 7, 2024

We don't really support casting, no. The new v4 (#35) should make this easier/possible, but it's not a feature as of yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants