The classic example, I guess, is the most vexing parse: https://en.m.wikipedia.org/wiki/Most_vexing_parse
"""
The line
TimeKeeper time_keeper(Timer());
is seemingly ambiguous, since it could be interpreted either as a variable definition [...]
a function declaration [...]
"""These things you can only resolve by having the symbol tables around and checking. The parser alone can't tell.
A language could avoid this i.e. by requiring specific keywords or having more distinct syntax.
Humans (programmers) however often can deal with ambiguity, we have it in humannlanaguage as well and context on most cases helps and I argue those aren't practical problems. (While that's only opinion)
This is not a distinguishing feature. (I'm assuming you meant something else.) Example of a CFG with ambiguity:
S → S S
S → xOn the other hand, I've seen EBNF definition of BASIC (VB, actually). Is this a contradiction?
(just someone still learning)
<Statement> ::= CLOSE '#' Integer
| DATA <Constant List>
[...]
| LET Id '=' <Expression>
[...]
| Remark
<Compare Exp> ::= <Add Exp> '=' <Compare Exp>
| <Add Exp> '<>' <Compare Exp>
| <Add Exp> '><' <Compare Exp>
| <Add Exp> '>' <Compare Exp>
| <Add Exp> '>=' <Compare Exp>
| <Add Exp> '<' <Compare Exp>
| <Add Exp> '<=' <Compare Exp>
| <Add Exp>
Language features are an orthogonal issue--you can implement any language feature with a CFG, but you just can't reuse the same keyword or operator to have different meanings in different grammatical contexts.
A classic example is that in C++ it is impossible to know whether << is brackets around template arguments, or the left bit shift operator, or the stream output operator, without arbitrary lookahead--you need to parse the rest of the statement in order to decide which one it is in the current statement's context.
Generally language designers don't choose to implement a context-sensitive grammar on purpose because they desire some feature that requires it; they strive for a context-free grammar, but end up with a handful of special cases that require context-sensitive parsing because of either convenience or legacy reasons.
Popular programming languages nearly all use custom parsers written in other (or the same) Turing-complete programming languages, so it's not "harder" to parse the context-sensitive rules, it only poses a problem if you want to use a parser generator to implement parsing for a CSG.