Backport of https://github.com/go-gitea/gitea/pull/38754
Every `${{ }}` part was spliced as raw text into a synthesized
`format('...', <raw>)` call and re-parsed, so unbalanced parentheses
restructured the whole expression:
```yaml
run-name: ${{ 1) && (2 }} # panicked, aborting workflow parsing for the push
if: ${{ 1 }} ${{ 0) && (0 }} # silently skipped the job
runs-on: ${{ nosuchcontext.x }} # silently queued the job against the label ""
```
One scanner shaped like GitHub's template reader now splits every value
and each part is evaluated on its own, so nothing builds an expression
out of text. A part that fails is an error instead of an empty string.
`expressionCallsFunction` is self-contained here, since this branch has
no `expressionsMatch` to build it on. That makes
`github.com/rhysd/actionlint` a direct dependency, which it already is
on `main`.