1// This file is generated from format_fsm.rl. DO NOT EDIT. 2%%{ 3 # (except you are actually in scan_tokens.rl here, so edit away!) 4 machine formatfsm; 5}%% 6 7package stdlib 8 9import ( 10 "bytes" 11 "fmt" 12 "unicode/utf8" 13 14 "github.com/zclconf/go-cty/cty" 15 "github.com/zclconf/go-cty/cty/function" 16) 17 18%%{ 19 write data; 20}%% 21 22func formatFSM(format string, a []cty.Value) (string, error) { 23 var buf bytes.Buffer 24 data := format 25 nextArg := 1 // arg numbers are 1-based 26 var verb formatVerb 27 highestArgIdx := 0 // zero means "none", since arg numbers are 1-based 28 29 %%{ 30 31 action begin { 32 verb = formatVerb{ 33 ArgNum: nextArg, 34 Prec: -1, 35 Width: -1, 36 } 37 ts = p 38 } 39 40 action emit { 41 buf.WriteByte(fc); 42 } 43 44 action finish_ok { 45 } 46 47 action finish_err { 48 return buf.String(), fmt.Errorf("invalid format string starting at offset %d", p) 49 } 50 51 action err_char { 52 // We'll try to slurp a whole UTF-8 sequence here, to give the user 53 // better feedback. 54 r, _ := utf8.DecodeRuneInString(data[p:]) 55 return buf.String(), fmt.Errorf("unrecognized format character %q at offset %d", r, p) 56 } 57 58 action flag_sharp { 59 verb.Sharp = true 60 } 61 action flag_zero { 62 verb.Zero = true 63 } 64 action flag_minus { 65 verb.Minus = true 66 } 67 action flag_plus { 68 verb.Plus = true 69 } 70 action flag_space { 71 verb.Space = true 72 } 73 74 action argidx_reset { 75 verb.ArgNum = 0 76 } 77 action argidx_num { 78 verb.ArgNum = (10 * verb.ArgNum) + (int(fc) - '0') 79 } 80 81 action has_width { 82 verb.HasWidth = true 83 } 84 action width_reset { 85 verb.Width = 0 86 } 87 action width_num { 88 verb.Width = (10 * verb.Width) + (int(fc) - '0') 89 } 90 91 action has_prec { 92 verb.HasPrec = true 93 } 94 action prec_reset { 95 verb.Prec = 0 96 } 97 action prec_num { 98 verb.Prec = (10 * verb.Prec) + (int(fc) - '0') 99 } 100 101 action mode { 102 verb.Mode = rune(fc) 103 te = p+1 104 verb.Raw = data[ts:te] 105 verb.Offset = ts 106 107 if verb.ArgNum > highestArgIdx { 108 highestArgIdx = verb.ArgNum 109 } 110 111 err := formatAppend(&verb, &buf, a) 112 if err != nil { 113 return buf.String(), err 114 } 115 nextArg = verb.ArgNum + 1 116 } 117 118 # a number that isn't zero and doesn't have a leading zero 119 num = [1-9] [0-9]*; 120 121 flags = ( 122 '0' @flag_zero | 123 '#' @flag_sharp | 124 '-' @flag_minus | 125 '+' @flag_plus | 126 ' ' @flag_space 127 )*; 128 129 argidx = (( 130 '[' (num $argidx_num) ']' 131 ) >argidx_reset)?; 132 133 width = ( 134 ( num $width_num ) >width_reset %has_width 135 )?; 136 137 precision = ( 138 ('.' ( digit* $prec_num )) >prec_reset %has_prec 139 )?; 140 141 # We accept any letter here, but will be more picky in formatAppend 142 mode = ('a'..'z' | 'A'..'Z') @mode; 143 144 fmt_verb = ( 145 '%' @begin 146 flags 147 width 148 precision 149 argidx 150 mode 151 ); 152 153 main := ( 154 [^%] @emit | 155 '%%' @emit | 156 fmt_verb 157 )* @/finish_err %/finish_ok $!err_char; 158 159 }%% 160 161 // Ragel state 162 p := 0 // "Pointer" into data 163 pe := len(data) // End-of-data "pointer" 164 cs := 0 // current state (will be initialized by ragel-generated code) 165 ts := 0 166 te := 0 167 eof := pe 168 169 // Keep Go compiler happy even if generated code doesn't use these 170 _ = ts 171 _ = te 172 _ = eof 173 174 %%{ 175 write init; 176 write exec; 177 }%% 178 179 // If we fall out here without being in a final state then we've 180 // encountered something that the scanner can't match, which should 181 // be impossible (the scanner matches all bytes _somehow_) but we'll 182 // flag it anyway rather than just losing data from the end. 183 if cs < formatfsm_first_final { 184 return buf.String(), fmt.Errorf("extraneous characters beginning at offset %d", p) 185 } 186 187 if highestArgIdx < len(a) { 188 // Extraneous args are an error, to more easily detect mistakes 189 firstBad := highestArgIdx+1 190 if highestArgIdx == 0 { 191 // Custom error message for this case 192 return buf.String(), function.NewArgErrorf(firstBad, "too many arguments; no verbs in format string") 193 } 194 return buf.String(), function.NewArgErrorf(firstBad, "too many arguments; only %d used by format string", highestArgIdx) 195 } 196 197 return buf.String(), nil 198} 199