How do you match nested structures without the generic syntax matchers overriding the more specific definitions?

I’m not sure if I’ve phrased this question correctly, but lemme try to explain.

For reference, I have a mostly working REPL here: Lezer: Polish Notation Grammar (no comments) - StackBlitz

The issue I’m having is that I’m trying to highlight function calls separate from just text or identifiers.

I have this example

  {{ (call expression) }}

is parsed as

 ├─ MoustacheExpression [9:2..9:25]
 │   ├─ {{ [9:2..9:4]: "{{"
 │   ├─ ⚠ [9:4..9:5]: " "
 │   ├─ SExpression [9:5..9:23]
 │   │   └─ CallExpression [9:5..9:23]
 │   │       ├─ ( [9:5..9:6]: "("
 │   │       ├─ SExpression [9:6..9:10]: "call"
 │   │       └─ ⚠ [9:21..9:22]
 │   │           └─ ) [9:21..9:22]: ")"
 │   └─ }} [9:23..9:25]: "}}"

(the other weird thing is that the word expression is missing :see_no_evil: )

and here is my relevant grammar:

CallExpression { "(" ~Function SExpression? (identifier Is SExpression)? ")"  }

SExpression { 
    CallExpression
    | identifier
    | Is 
    | Pipe
    | Argument
    //| String
    | keywords
}

So, the CallExpression can have s-expressions within it, and identifier and SExpression are valid “first things” after the (, but identifier should be prioritized – is there anyway to set precedence to the Function in the CallExpression? or am I thinking about this wrong?

Use parent node selectors in your styleTags spec—there’s no need to use a different identifier node to highlight this differently.