Allow parsing of "cond && var=value" and similar expressions #170
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Expressions like "1 && x=1" aren't really valid (IMO), because assignments are lower-precedence than binary operators, but onetrueawk, Gawk, and mawk all support this for logical, match and comparison operators.
The other awks support this by using a yacc grammar which supports backtracking, and as Vitus13 said on reddit: "If there are two syntactically valid parsings and one is a semantic error, the error handling may resolve the ambiguity towards the valid parsing. In this case, you can only assign to L values, so trying to assign to (1&&x) doesn't make any sense."
In GoAWK, this requires a form of backtracking (I call it "partial backtracking" because it's not actually backing up the lexer). It works by parsing as (1&&x)=1 according to the operator precedence, then determining that you're trying to assign something that isn't an lvalue, then confirming that 1&&x is a binary expression, that the "x" part is an lvalue, and that the operator (&& in this case) is one that the other awks handle similarly for this case.
Also make the error message a bit clearer when you don't have an lvalue on the left hand side of an assignment, like "rand() = 1".
Fixes #166