How to make this possible?

This is my grammar:


@skip { spaces }

@precedence {
    times @left,
    plus @left,
    and @left,
    or @left
}

@top Pipeline {
    state ("|" state)*
}

state {
    MatchState
}

MatchState {
    "match:" matchCondition
}

matchCondition {
    AndCondition | OrCondition | EqCondition | GtCondition | GeCondition | LtCondition | LeCondition | ParenthesizedCondition
}

AndCondition {
    matchCondition !and "and" matchCondition
}

OrCondition {
    matchCondition !or "or" matchCondition
}

NotCondition {
    NotOp matchCondition
}

EqCondition {
    expression EqOp (logicalExpression | expression)
}

GtCondition {
    expression GtOp expression
}

GeCondition {
    expression GeOp expression
}

LtCondition {
    expression LtOp expression
}

LeCondition {
    expression LeOp expression
}

ParenthesizedCondition { "(" matchCondition ")" }

logicalExpression[@isGroup=LogicalExpression] {
    AndLogicalExpression | OrLogicalExpression | ParenthesizedLogicalExpression
}

AndLogicalExpression {
    (expression | logicalExpression) !and "and" (expression | logicalExpression)
}

OrLogicalExpression {
    (expression | logicalExpression) !or "or" (expression | logicalExpression)
}

ParenthesizedLogicalExpression { "(" logicalExpression ")" }

expression[@isGroup=Expression] {
    Number |
    String |
    Identifier |
    @specialize[@name=BooleanLiteral]<Identifier, "true" | "false"> |
    RegExp |
    ArrayExpression {
      "[" commaSep1<"..."? expression | ""> "]"
    } |
    UnaryExpression |
    ParenthesizedExpression |
    BinaryExpression
}

//!commaSep

commaSep<content> {
    (content ("," content)*)?
}
  
commaSep1<content> {
    content ("," content)*
}

ParenthesizedExpression { "(" expression ")" }

//!operators
UnaryExpression {
    ArithOp<"+" | "-">
    expression
}
  
BinaryExpression {
    expression !times (ArithOp<"/"> | ArithOp<"%"> | ArithOp<"*">) expression |
    expression !plus ArithOp<"+" | "-"> expression
}

@tokens {
    spaces[@export] { $[\u0009 \u000b\u00a0]+ }
    newline[@export] { $[\r\n] }

    identifierChar { @asciiLetter | $[_$\u{a1}-\u{10ffff}] }

    Identifier { identifierChar (identifierChar | @digit)* }

    //!numberTokens

    hex { @digit | $[a-fA-F] }

    Number {
        (@digit ("_" | @digit)* ("." ("_" | @digit)*)? | "." @digit ("_" | @digit)*)
            (("e" | "E") ("+" | "-")? ("_" | @digit)+)? |
        @digit ("_" | @digit)* "n" |
        "0x" (hex | "_")+ "n"? |
        "0b" $[01_]+ "n"? |
        "0o" $[0-7_]+ "n"?
    }

    @precedence { Number "." }
    //!stringTokens
    String {
        '"' (![\\\n"] | "\\" _)* '"'? |
        "'" (![\\\n'] | "\\" _)* "'"?
    }

    //!operatorTokens

    ArithOp<expr> { expr }

    NotOp { "not" }
    EqOp { "=" }
    LtOp { "<" }
    LeOp { "<=" }
    GtOp { ">" }
    GeOp { ">=" }
    PipeOp { "|" }

    //!regexpTokens

    RegExp { "/" (![/\\\n[] | "\\" ![\n] | "[" (![\n\\\]] | "\\" ![\n])* "]")+ ("/" $[gimsuy]*)? }

    //!literalTokens

    "=" "..." "=>"
    "(" ")" "[" "]" "{" "}"
    "." "," ";" ":"
}

I want this

match: people = 3 or (people = 4 or animal < (people +4) * 4 / money)

to be parsed as

match: (people = 3) or (people = 4 or animal < (people +4) * 4 / money)

which means

MatchState
  OrCondition 
    EqCondition
    ParenthesizedCondition 

However, currently it is parsed as

match: people = (3 or (people = 4 or animal < (people +4) * 4 / money))

which means

MatchState
  Identifier
  EqOp
  OrLogicalExpression

I know it’s ambiguous。 But according to the documentation lezer supports branch matching. I’ve tried many combinations and still haven’t tried to figure out where the disambiguation markers should be placed to achieve this effect

Give your EqCondition rule a precedence the way binary and or/and rules have them, and make sure it’s higher than the one for or/and.

Thank your for your response. After referring to your modification, it does not report the error, but

match: people = 3 or 4

is parsed as

match: (people = 3) or 4

not

match: people = (3 or 4)

which I want.

That looks like it may contradict your expectation for the initial example, where or binds more tightly than =.

In the initial example,
I want

match: people = 3 or (people = 4 or animal < (people +4) * 4 / money)

to be parsed as

match: (people = 3) or (people = 4 or animal < (people +4) * 4 / money)

because (people = 4 or animal < (people +4) * 4 / money) is a matchCondition not expression.
So 3 or (people = 4 or animal < (people +4) * 4 / money) is not a logicalExpression.
Then it should be parsed as matchCondition or matchCondition not expression = logicalExpression