def expr(self):
        """
        expr    ::= term ((AND | OR) term)*
        term    ::= factor ((EQ | NE) factor)*
        factor  ::= func | const | LPAREN expr RPAREN
        func    ::= lit LPAREN expr (,expr)* RPAREN
        lit     ::= alphanum
        """
        node = self.term()

        while True:
            token = self.current_token
            if token.type == AND:
                self.eat(AND)
            elif token.type == OR:
                self.eat(OR)
            else:
                break
            node = Op(op=token, children=[node, self.term()])
        return node