It is debatable whether you really need a short grammar for everything. Sometimes the logic is just complex enough that you'll need to write it in the complex way.
But in your case, there is a good reason to have a special grammar. That is, sometimes bar() creates an object and qux() uses the object, and it might be in a type that does work in the constructor, in a language like C++, where using new and delete everywhere in short functions doesn't look good, so you are not supposed to use null-like default values.
In this case, I think you could just invent a new grammar, without considering whether it is short.
The basic logic might be:
some_keyword name = if (foo);
// Or: some_keyword name; if(foo) name;
name {bar();}
baz();
name {qux();}
In the background, of course it is just implemented in the traditional ways. And it doesn't look significantly different. But it could be managed automatically to avoid the possibility of an invalid state.
Or we could change it to make name optional, so you could define something without a name to call its destructor later without referring to it again:
if(foo)
some_keyword optional_name {bar();}
// Or:
some_keyword optional_name if(foo) {
bar();
yield;
}
In the former case, it is in a situation similar to break, that you may want to allow specifying the scope level it binds into. In the later case, it is supposed to be a coroutine, that doesn't exit the scope of if when it is defined. You may also make it support labels to match labels outside. In either case we are making the scope containing bar() live longer than it appears.
Then we could begin adding syntactic sugar:
try {
if(foo) {
bar();
finally {
qux();
}
}
baz();
}
You could also use it to replace the traditional try. With some improvements, it might work better than the traditional try in a constructor, where you undo what you have already done and ignore what you have not when there is an exception.
Note that it has slightly different meaning from your code. It changes the behavior if baz() throws an exception. You should think of what you actually want in concrete examples. It might be not bad to also have destructors marked as ignored on exceptions.
In case you are not using it in a serious programming language, I think I have seen a language, without remembering its name, where then and else are relatively separate from if and just take the result of the last if. (The Shakespeare Programming Language also works like this, but you won't want to use it as an example.) It might be possible to write code like this, which I don't remember:
if(foo)
then bar();
baz();
then qux();
The down side is it doesn't work well for nested ifs. So programmers often write like this:
if(a) then {
if(b) then
c;
if(true);
}
else
d;
But I think that could be solved by automatically resetting the if result after then and else blocks, and function calls.
It may not work well if you add more complexity to it, for example stacking more levels of this construct.
And if it is for golfing, you could also just invent an operator for this semantic and don't think too much about the internal logic.