func booleanToMSPIterative(boolExp string, vec data.Vector, c int) (*MSP, int, error) {
	boolExp = strings.TrimSpace(boolExp)
	numBrc := 0
	var boolExp1 string
	var boolExp2 string
	var c1 int
	var cOut int
	var msp1 *MSP
	var msp2 *MSP
	var err error
	found := false
	for i, e := range boolExp {
		if e == '(' {
			numBrc++
			continue
		}
		if e == ')' {
			numBrc--
			continue
		}
		if numBrc == 0 && i < len(boolExp)-3 && boolExp[i:i+3] == "AND" {
			boolExp1 = boolExp[:i]
			boolExp2 = boolExp[i+3:]
			vec1, vec2 := makeAndVecs(vec, c)
			msp1, c1, err = booleanToMSPIterative(boolExp1, vec1, c+1)
			if err != nil {
				return nil, 0, err
			}
			msp2, cOut, err = booleanToMSPIterative(boolExp2, vec2, c1)
			if err != nil {
				return nil, 0, err
			}
			found = true
			break
		}
		if numBrc == 0 && i < len(boolExp)-2 && boolExp[i:i+2] == "OR" {
			boolExp1 = boolExp[:i]
			boolExp2 = boolExp[i+2:]
			msp1, c1, err = booleanToMSPIterative(boolExp1, vec, c)
			if err != nil {
				return nil, 0, err
			}
			msp2, cOut, err = booleanToMSPIterative(boolExp2, vec, c1)
			if err != nil {
				return nil, 0, err
			}
			found = true
			break
		}
	}
	if !found {
		if boolExp[0] == '(' && boolExp[len(boolExp)-1] == ')' {
			boolExp = boolExp[1:(len(boolExp) - 1)]
			return booleanToMSPIterative(boolExp, vec, c)
		}
		if strings.Contains(boolExp, "(") || strings.Contains(boolExp, ")") {
			return nil, 0, fmt.Errorf("bad boolean expression or attributes contain ( or )")
		}
		mat := make(data.Matrix, 1)
		mat[0] = make(data.Vector, c)
		for i := 0; i < c; i++ {
			if i < len(vec) {
				mat[0][i] = new(big.Int).Set(vec[i])
			} else {
				mat[0][i] = big.NewInt(0)
			}
		}
		rowToAttribS := make([]string, 1)
		rowToAttribS[0] = boolExp
		return &MSP{Mat: mat, RowToAttrib: rowToAttribS}, c, nil
	}
	mat := make(data.Matrix, len(msp1.Mat)+len(msp2.Mat))
	for i := 0; i < len(msp1.Mat); i++ {
		mat[i] = make(data.Vector, cOut)
		for j := 0; j < len(msp1.Mat[0]); j++ {
			mat[i][j] = msp1.Mat[i][j]
		}
		for j := len(msp1.Mat[0]); j < cOut; j++ {
			mat[i][j] = big.NewInt(0)
		}
	}
	for i := 0; i < len(msp2.Mat); i++ {
		mat[i+len(msp1.Mat)] = msp2.Mat[i]
	}
	rowToAttribS := append(msp1.RowToAttrib, msp2.RowToAttrib...)
	return &MSP{Mat: mat, RowToAttrib: rowToAttribS}, cOut, nil
}
booleanToMspIterative iteratively builds a msp structure by splitting the expression
into two parts separated by an AND or OR gate, generating a msp structure on each of
them, and joining both structures together. The structure is such the the boolean expression
assigning 1 to some attributes is satisfied iff the corresponding rows span a vector
[1, 0,..., 0]. The algorithm is known as Lewko-Waters algorithm, see Appendix G in
https://eprint.iacr.org/2010/351.pdf.
package abe
import (
	"math/big"
	"strings"
	"fmt"
	"github.com/fentec-project/gofe/data"
)
type MSP struct {
	P           *big.Int
	Mat         data.Matrix
	RowToAttrib []string
}
func BooleanToMSP(boolExp string, convertToOnes bool) (*MSP, error) {
	vec := make(data.Vector, 1)
	vec[0] = big.NewInt(1)
	msp, _, err := booleanToMSPIterative(boolExp, vec, 1)
	if err != nil {
		return nil, err
	}
	if convertToOnes {
		invMat := make(data.Matrix, len(msp.Mat[0]))
		for i := 0; i < len(msp.Mat[0]); i++ {
			invMat[i] = make(data.Vector, len(msp.Mat[0]))
			for j := 0; j < len(msp.Mat[0]); j++ {
				if i == 0 || j == i {
					invMat[i][j] = big.NewInt(1)
				} else {
					invMat[i][j] = big.NewInt(0)
				}
			}
		}
		msp.Mat, err = msp.Mat.Mul(invMat)
		if err != nil {
			return nil, err
		}
	}
	return msp, nil
}