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