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

ternary operator ? should be right associative #712

Closed
andychu opened this issue Apr 16, 2020 · 6 comments
Closed

ternary operator ? should be right associative #712

andychu opened this issue Apr 16, 2020 · 6 comments

Comments

@andychu
Copy link
Contributor

andychu commented Apr 16, 2020

FizzBuzz doesn't work for me in bash 4.3 or 4.4?

What's wrong with the output? If you're referring to the error messages, only stdout is counted in the golf and the stderr junk is intended. You can prepend it with : to stop it.

The prime numbers program works with let as let(){ IFS=,;return $((!($*)));} and eval_unsafe_arith.

The divisors program doesn't work even with workarounds for the lack of $_ and $[ as OSH doesn't support mixed case in brace expansion ({a..C}).

The FizzBuzz program doesn't work even with workarounds for the lack of $_; it seems to be because OSH doesn't support nested ternary:

osh$ echo $((1?2?3:4:5))
  echo $((1?2?3:4:5))
             ^
[ interactive ]:1: Parser expected Id.Arith_Colon, got Id.Arith_QMark
$ echo $((1?2?3:4:5))
3

bash, dash, ksh, mrsh, yash, and zsh seem to support it, but ash doesn't seem to either

Originally posted by @Crestwave in #161 (comment)

andychu pushed a commit that referenced this issue Apr 17, 2020
@andychu andychu changed the title Precedence of ? : is probably wrong ternary operator ? should be right associative Apr 17, 2020
@andychu andychu closed this as completed Apr 19, 2020
@akinomyoga
Copy link
Collaborator

akinomyoga commented Apr 22, 2020

Hi, this now causes a new error in source ble.osh. Here is a reduced test case:

$ osh -c '((1?a=1:(b=1)))'
  ((1?a=1:(b=1)))
       ^
[ -c flag ]:1: Parser expected Id.Arith_Colon, got Id.Arith_Equal

@akinomyoga
Copy link
Collaborator

akinomyoga commented Apr 22, 2020

I'm sorry the bug is not caused by this change. I'm not sure why the problem did not appear in source ble.sh until recently, but it turned out that this bug has existed before.

Edit: OK, this problem started to appear because of a recent change to ble.sh.

@andychu
Copy link
Contributor Author

andychu commented Apr 22, 2020

OK cool, yes it should be doing the right thing now! It was parsing incorrectly before this.

I guess you need parens around (a=1) like (b=1)

@akinomyoga
Copy link
Collaborator

I guess you need parens around (a=1) like (b=1)

Thank you. Yes, I know that I can work around it by adding parens, and in fact, now I have parens there to test ble.sh in Oil. But, we don't usually need such parens in conditional operators in C and similar languages. Is there any reason not to support it in Oil?

I tested with shells and was surprised that zsh and busybox sh don't support it. But all the other shells that I tested (dash, mksh, ksh93, ksh2020, bash, posh, oksh and pdksh) support $((1?a=1:1)). I also tested with ksh88, but it turned out that ksh88 only accept a simple number in conditional operators, i.e., neither $((1?a=1:1)) nor $((1?(a=1):1)) works. The Bourne shell doesn't have arithmetic expressions.

@andychu
Copy link
Contributor Author

andychu commented Apr 22, 2020

Ah it is possible that there is a precedence bug between ? and = ... let me see.

@andychu
Copy link
Contributor Author

andychu commented Apr 22, 2020

Yeah according to the precedence table, ? is higher precedence than =. But it also has this footnote:

https://en.cppreference.com/w/c/language/operator_precedence

The expression in the middle of the conditional operator (between ? and :) is parsed as if parenthesized: its precedence relative to ?: is ignored.

Shell specifies that its arithmetic is identical to C arithmetic, so I guess this is a bug.

So I am not sure right now how to fix this using the TDOP parsing algorithm, but it can probably be done. It sounds like it's a special case in C, which was originally done with the shunting yard algorithm... not sure if that matters or not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants