def _parse_bin_op_expr(self: DefinitionParser, opId: int, inTemplate: bool) -> ASTExpression:
    if ((opId + 1) == len(_expression_bin_ops)):

        def parser(inTemplate: bool) -> ASTExpression:
            return self._parse_cast_expression()
    else:

        def parser(inTemplate: bool) -> ASTExpression:
            return _parse_bin_op_expr(self, (opId + 1), inTemplate=inTemplate)
    exprs = []
    ops = []
    exprs.append(parser(inTemplate=inTemplate))
    while True:
        self.skip_ws()
        if (inTemplate and (self.current_char == '>')):
            break
        pos = self.pos
        oneMore = False
        for op in _expression_bin_ops[opId]:
            if (op[0] in 'abcnox'):
                if (not self.skip_word(op)):
                    continue
            elif (not self.skip_string(op)):
                continue
            if ((op == '&') and (self.current_char == '&')):
                self.pos -= 1
                break
            try:
                expr = parser(inTemplate=inTemplate)
                exprs.append(expr)
                ops.append(op)
                oneMore = True
                break
            except DefinitionError:
                self.pos = pos
        if (not oneMore):
            break
    return ASTBinOpExpr(exprs, ops)
def _parse_bin_op_expr(self: DefinitionParser, opId: int, inTemplate: bool) -> ASTExpression:
    if ((opId + 1) == len(_expression_bin_ops)):

        def parser(inTemplate: bool) -> ASTExpression:
            return self._parse_cast_expression()
    else:

        def parser(inTemplate: bool) -> ASTExpression:
            return _parse_bin_op_expr(self, (opId + 1), inTemplate=inTemplate)
    exprs = []
    ops = []
    exprs.append(parser(inTemplate=inTemplate))
    while True:
        self.skip_ws()
        if (inTemplate and (self.current_char == '>')):
            break
        pos = self.pos
        oneMore = False
        for op in _expression_bin_ops[opId]:
            if (op[0] in 'abcnox'):
                if (not self.skip_word(op)):
                    continue
            elif (not self.skip_string(op)):
                continue
            if ((op == '&') and (self.current_char == '&')):
                self.pos -= 1
                break
            try:
                expr = parser(inTemplate=inTemplate)
                exprs.append(expr)
                ops.append(op)
                oneMore = True
                break
            except DefinitionError:
                self.pos = pos
        if (not oneMore):
            break
    return ASTBinOpExpr(exprs, ops)