ParseSub returns a slice of words, based on a string argument to the Fn::Sub intrinsic function. "ABC-${XYZ}-123" returns a slice containing: SubWord { T: STR, W: "ABC-" } SubWord { T: REF, W: "XYZ" } SubWord { T: STR, W: "-123" } Invalid syntax like "${AAA" returns an error
(sub string, leaveBang bool)
| 58 | // |
| 59 | // Invalid syntax like "${AAA" returns an error |
| 60 | func ParseSub(sub string, leaveBang bool) ([]SubWord, error) { |
| 61 | words := make([]SubWord, 0) |
| 62 | state := READSTR |
| 63 | var last rune |
| 64 | var buf string |
| 65 | var wt wordtype |
| 66 | for i, r := range sub { |
| 67 | //config.Debugf("%#U", r) |
| 68 | switch r { |
| 69 | case DOLLAR: |
| 70 | if state != READVAR { |
| 71 | state = MAYBE |
| 72 | } else { |
| 73 | // This is a literal $ inside a variable: "${AB$C}" |
| 74 | // TODO: Should that be an error? Is it valid? |
| 75 | buf += string(r) |
| 76 | } |
| 77 | case OPEN: |
| 78 | if state == MAYBE { |
| 79 | // Peek to see if we're about to start a LITERAL ! |
| 80 | if len(sub) > i+1 && []rune(sub)[i+1] == BANG { |
| 81 | // Treat this as part of the string, not a var |
| 82 | buf += "${" |
| 83 | state = READLIT |
| 84 | } else { |
| 85 | state = READVAR |
| 86 | // We're about to start reading a variable. |
| 87 | // Append the last word in the buffer if it's not empty |
| 88 | if len(buf) > 0 { |
| 89 | wt = STR |
| 90 | words = append(words, SubWord{T: wt, W: buf}) |
| 91 | buf = "" |
| 92 | } |
| 93 | } |
| 94 | } else { |
| 95 | buf += string(r) |
| 96 | } |
| 97 | case CLOSE: |
| 98 | if state == READVAR { |
| 99 | // Figure out what type it is |
| 100 | if strings.HasPrefix(buf, AWScc) { |
| 101 | wt = AWS |
| 102 | } else if strings.HasPrefix(buf, RAINcc) { |
| 103 | wt = RAIN |
| 104 | } else if strings.HasPrefix(buf, CONSTcc) { |
| 105 | wt = RAIN |
| 106 | } else if strings.Contains(buf, ".") { |
| 107 | wt = GETATT |
| 108 | } else { |
| 109 | wt = REF |
| 110 | } |
| 111 | buf = strings.Replace(buf, AWScc, "", 1) |
| 112 | buf = strings.Replace(buf, RAINcc, "", 1) |
| 113 | buf = strings.Replace(buf, CONSTcc, "", 1) |
| 114 | words = append(words, SubWord{T: wt, W: buf}) |
| 115 | buf = "" |
| 116 | state = READSTR |
| 117 | } else { |
no outgoing calls