// load expressions, returning list and augmented parse tree list func load(filename string) []*RegEx { elist := make([]*RegEx, 0) // expression structure list rx.LoadExpressions(filename, func(l *rx.RegExParsed) { if l.Tree != nil { // if a real expression e := &RegEx{} e.index = len(elist) e.cnum = len(elist) e.RegExParsed = *l // save parse tree e.examples = genex(l.Tree) // gen examples unaugmented t := rx.Augment(l.Tree, e.index) e.dfa = rx.BuildDFA(t) // build DFA if verbose { fmt.Println() showexpr(e) // show details of expr showexamples(e) // show its examples } elist = append(elist, e) } }) if verbose { fmt.Printf("\nloaded %d expression(s), ignored %d more\n", rx.InputRegExCount, rx.InputErrorCount) } return elist }
// details responds to an inspection request for a single expression func details(w http.ResponseWriter, r *http.Request) { field := fmt.Sprintf("v%d", baseExpr) expr := r.FormValue(field) // must read before any writing expr = strings.TrimSpace(expr) // trim leading/trailing blanks putheader(w, r, "Inspect Expression") tree, err := rx.Parse(expr) if err == nil { fmt.Fprintf(w, "<P>Regular Expression: %s\n", hx(expr)) // must print (or at least stringize) tree before augmenting fmt.Fprintf(w, "<P>Initial Parse Tree: %s\n", hx(tree)) augt := rx.Augment(tree, 0) dfa := rx.BuildDFA(augt) dmin := dfa.Minimize() fmt.Fprintf(w, "<P>Augmented Tree: %s\n", hx(augt)) fmt.Fprintf(w, "<h2>Examples</h2>\n<P>") genexamples(w, tree, 0) genexamples(w, tree, 1) genexamples(w, tree, 2) genexamples(w, tree, 3) genexamples(w, tree, 5) genexamples(w, tree, 8) showaut(w, dmin, []string{expr}) } else { fmt.Fprint(w, "<P>") showerror(w, err) } fmt.Fprint(w, "<h2>Try another?</h2>") putform(w, "/details", "Enter a regular expression:", 1, []string{expr}, 0, nil) putfooter(w, r) }
// individual handles separate processing of each input regex func individual(l *rx.RegExParsed, cx int, i int, image string, augt rx.Node) { babble("tree: %s\n", image) babble("augmnt: %v\n", augt) x := augt.MaxLen() if x >= 0 { babble("length: %d to %d\n", augt.MinLen(), x) } else { babble("length: %d to *\n", augt.MinLen()) } babble("cplxty: %d\n", cx) dfa := rx.BuildDFA(augt) if *opt['R'] { rand.Seed(int64(seedvalue)) } if *opt['g'] { rx.ShowLabel(os.Stdout, "Examples") examples(dfa, l.Tree, 0) // gen and test w/ max repl of 0 examples(dfa, l.Tree, 1) // ... and 1 examples(dfa, l.Tree, 2) // ... and 2 examples(dfa, l.Tree, 3) // ... and 3 examples(dfa, l.Tree, 5) // ... and 5 examples(dfa, l.Tree, 8) // ... and 8 } showDFA(dfa, "Annotated Tree", false) }
// main control func main() { filename := cmdline() // process command line maxEx := *numElem * 4 exprs, trees := load(filename) // load expressions qns := make([]string, 0, maxEx) //create list of question words answers := new(rx.BitSet) //create list of answers dfaList := make([]*rx.DFA, 0, len(trees)) //list of candidate DFAs ind := make([]int, 0, len(dfaList)) //index array to track id of each regex a := 0 init := 0 if *mode == 1 { //run with examples //ask for examples fmt.Println("Enter some examples: ") //read examples r := bufio.NewReader(os.Stdin) line, err := r.ReadString(delim) if err != nil { fmt.Println(err) os.Exit(1) } for line != string('\n') { line = line[:len(line)-1] qns = append(qns, line) answers.Set(a) a++ line, err = r.ReadString(delim) if err != nil { fmt.Println(err) os.Exit(1) } } //ask for counter examples fmt.Println("\nEnter some counter-examples: ") rr := bufio.NewReader(os.Stdin) //read counter examples line, err = rr.ReadString(delim) if err != nil { fmt.Println(err) os.Exit(1) } for line != string('\n') { line = line[:len(line)-1] qns = append(qns, line) line, err = rr.ReadString(delim) if err != nil { fmt.Println(err) os.Exit(1) } } fmt.Printf("Processing ...\n") //build the DFAs of all candidates for i := 0; i < len(trees); i++ { aDfa := rx.BuildDFA(trees[i]) dfaList = append(dfaList, aDfa) //fmt.Printf("rx { %d } %s\n", i, exprs[i].Expr) } fmt.Printf("\n") //refine the candidate set based on examples and counter examples dfaList, exprs, ind = refine(answers, qns, dfaList, exprs, ind) init++ fmt.Printf("Length of dfaList: %d\n", len(dfaList)) for i := 0; i < len(ind); i++ { fmt.Printf("rx { %d } %s\n", ind[i], exprs[i].Expr) } } else if *mode == 2 { //partition numPerGroup := *numElem //build DFAs of all candidates for i := 0; i < len(trees); i++ { aDfa := rx.BuildDFA(trees[i]) dfaList = append(dfaList, aDfa) //fmt.Printf("rx { %d } %s\n", i, exprs[i].Expr) } times := 0 for len(dfaList) > 50 { permArray := rand.Perm(len(dfaList)) //randomly permute candidate set qns = make([]string, 0, maxEx) //initialize new set of questions answers = new(rx.BitSet) //initialize new set of answers //ask best question in each partition. Return questions and answers answers, qns = askBulk(answers, qns, permArray, dfaList, exprs, numPerGroup) fmt.Println("Here length of dfaList =", len(dfaList)) //refine the candidate set based on questions ans answers dfaList, exprs, ind = refine(answers, qns, dfaList, exprs, ind) init++ fmt.Printf("Length of dfaList: %d\n", len(dfaList)) times++ } } else if *mode == 3 { //ask all DFAs numPerGroup := *numElem //build DFA's of all candidates for i := 0; i < len(trees); i++ { aDfa := rx.BuildDFA(trees[i]) dfaList = append(dfaList, aDfa) fmt.Printf("rx { %d } %s\n", i, exprs[i].Expr) } times := 0 for len(dfaList) > 50 { //fmt.Println("iteration = ", times) //default partition is 20 per group permArray := rand.Perm(len(dfaList)) //randomly permute candidate set qns = make([]string, 0, maxEx) //initialize new set of questions answers = new(rx.BitSet) //initialize new set of answers //ask best question based on number of DFAs that accept question word answers, qns = askBulk2(answers, qns, permArray, dfaList, exprs, numPerGroup) fmt.Println("Here length of dfaList =", len(dfaList)) //fmt.Printf("\n") //refine candidate set based on questions and answers dfaList, exprs, ind = refine(answers, qns, dfaList, exprs, ind) init++ fmt.Printf("Length of dfaList: %d\n", len(dfaList)) times++ } } else { //mode = 0, run basic algorithm //build DFA's of all candidates for i := 0; i < len(trees); i++ { aDfa := rx.BuildDFA(trees[i]) dfaList = append(dfaList, aDfa) //fmt.Printf("rx { %d } %s\n", i, exprs[i].Expr) } } param := 1 value := *numElem tempLen := 0 done := false numPerGroup := 5 for len(dfaList) > param && !done { subjlist := make([]int, 0, *group) subjtrees := make([]rx.Node, 0, *group) expressions := make([]*RegEx, 0, len(dfaList)) if init == 0 { //if this is the first iteration, mode = 0 //pick a random subset for i := 0; i < *group && i < len(dfaList); i++ { j := rand.Intn(len(dfaList)) // naive; can duplicate subjlist = append(subjlist, j) subjtrees = append(subjtrees, dfaList[j].Tree) expressions = append(expressions, &RegEx{j, exprs[j].Expr}) fmt.Printf("rx { %d } %s\n", j, exprs[j].Expr) } init++ } else if len(dfaList) < value { //if the number of dfa's is small enough, run qns on all remaining for i := 0; i < len(dfaList); i++ { //j := rand.Intn(len(dfaList)) // naive; can duplicate subjlist = append(subjlist, i) subjtrees = append(subjtrees, dfaList[i].Tree) expressions = append(expressions, &RegEx{ind[i], exprs[i].Expr}) fmt.Printf("rx { %d } %s\n", ind[i], exprs[i].Expr) } } else { //if number of dfa's is too large, do nothing } qns = make([]string, 0, maxEx) //initialize new set of questions answers = new(rx.BitSet) //initialize new set of answers permArray := rand.Perm(len(dfaList)) //randomly permute candidate DFAs fmt.Println("len dfa list = ", len(dfaList)) //ask best question based on number of candidates that accept question word answers, qns = askBulk2(answers, qns, permArray, dfaList, exprs, numPerGroup) fmt.Printf("\n") fmt.Println("before length of dfaList = ", len(dfaList)) tempLen = len(dfaList) //store current length //refine the candidate set based on questions and answers dfaList, exprs, ind = refine(answers, qns, dfaList, exprs, ind) fmt.Println("length of dfaList = ", len(dfaList)) //if refinement did not change candidate list then we have equivalent reg exp if tempLen == len(dfaList) { done = true fmt.Println("Main: There are ", len(dfaList), " reg exs that match your query and they are equivalent:") for i := 0; i < len(dfaList); i++ { fmt.Printf("rx { %d } %s\n ", ind[i], exprs[i].Expr) } } } //if one remaining reg ex, print it if len(dfaList) == 1 { fmt.Printf("\nMain: The reg ex you are looking for is: rx { %d } %s\n\nMETA DATA: \n", ind[0], exprs[0].Expr) // print accumulated metadata exprs[0].ShowMeta(os.Stdout, "") fmt.Printf("\n") } //if no remaining reg exs, no match in our library if len(dfaList) == 0 { fmt.Printf("Main: No reg ex in our library matches your query.\n") } }