github.com/unirita/cuto@v0.9.8-0.20160830082821-aa6652f877b7/flowgen/converter/parser.go (about) 1 package converter 2 3 import ( 4 "errors" 5 "io/ioutil" 6 "regexp" 7 "strings" 8 ) 9 10 const ( 11 arrow = "->" 12 gHead = "[" 13 gTerm = "]" 14 gDelim = "," 15 tmpGW = ":gw" 16 ) 17 18 // Parse parses flow description from file. 19 func ParseFile(filepath string) (Element, error) { 20 buf, err := ioutil.ReadFile(filepath) 21 if err != nil { 22 return nil, err 23 } 24 25 return ParseString(string(buf)) 26 } 27 28 // ParseString parses flow description from string. 29 // If it successed, returns head element of flow. 30 func ParseString(str string) (Element, error) { 31 str = ignoreSpaceChars(str) 32 extracted, gws, err := extractGateways(str) 33 34 var head Element = nil 35 elmStrs := strings.Split(extracted, arrow) 36 isFirst := true 37 var current Element 38 var pre Element 39 var tmpGWIndex = 0 40 for _, elmStr := range elmStrs { 41 if elmStr == tmpGW { 42 if tmpGWIndex > len(gws) { 43 return nil, errors.New("Gateway parse error.") 44 } 45 current = gws[tmpGWIndex] 46 tmpGWIndex++ 47 } else { 48 current, err = parseJob(elmStr) 49 if err != nil { 50 return nil, err 51 } 52 } 53 54 if isFirst { 55 head = current 56 isFirst = false 57 } else { 58 pre.SetNext(current) 59 } 60 pre = current 61 } 62 return head, nil 63 } 64 65 func ignoreSpaceChars(str string) string { 66 ptn := regexp.MustCompile(`\s`) 67 return ptn.ReplaceAllLiteralString(str, "") 68 } 69 70 func extractGateways(str string) (string, []*Gateway, error) { 71 ptn := regexp.MustCompile(`\[.+?\]`) 72 gws := make([]*Gateway, 0) 73 74 gwStrs := ptn.FindAllString(str, -1) 75 for _, gwStr := range gwStrs { 76 gw, err := parseGateway(gwStr) 77 if err != nil { 78 return str, nil, err 79 } 80 gws = append(gws, gw) 81 } 82 83 str = ptn.ReplaceAllString(str, tmpGW) 84 return str, gws, nil 85 } 86 87 func parseJob(str string) (*Job, error) { 88 if err := validateJobName(str); err != nil { 89 return nil, err 90 } 91 return NewJob(str), nil 92 } 93 94 func validateJobName(str string) error { 95 if len(str) == 0 { 96 return errors.New("Empty job name found.") 97 } 98 99 ptn := regexp.MustCompile(`[\[\]\\/:*?<>$&,\-]`) 100 if ptn.MatchString(str) { 101 return errors.New("Irregal character found in job name.") 102 } 103 104 return nil 105 } 106 107 func parseGateway(str string) (*Gateway, error) { 108 str = strings.TrimLeft(str, gHead) 109 str = strings.TrimRight(str, gTerm) 110 111 p := NewGateway() 112 113 pathStrs := strings.Split(str, gDelim) 114 for _, pathStr := range pathStrs { 115 jobNames := strings.Split(pathStr, arrow) 116 isFirst := true 117 var preJob *Job 118 for _, jobName := range jobNames { 119 j, err := parseJob(jobName) 120 if err != nil { 121 return nil, err 122 } 123 124 if isFirst { 125 p.AddPathHead(j) 126 isFirst = false 127 } else { 128 preJob.SetNext(j) 129 } 130 preJob = j 131 } 132 } 133 134 return p, nil 135 }