221 l.next() |
221 l.next() |
222 break |
222 break |
223 } |
223 } |
224 |
224 |
225 possibleDate := l.peekString(35) |
225 possibleDate := l.peekString(35) |
226 dateMatch := dateRegexp.FindString(possibleDate) |
226 dateSubmatches := dateRegexp.FindStringSubmatch(possibleDate) |
227 if dateMatch != "" { |
227 if dateSubmatches != nil && dateSubmatches[0] != "" { |
228 l.fastForward(len(dateMatch)) |
228 l.fastForward(len(dateSubmatches[0])) |
|
229 if dateSubmatches[2] == "" { // no timezone information => local date |
|
230 return l.lexLocalDate |
|
231 } |
229 return l.lexDate |
232 return l.lexDate |
230 } |
233 } |
231 |
234 |
232 if next == '+' || next == '-' || isDigit(next) { |
235 if next == '+' || next == '-' || isDigit(next) { |
233 return l.lexNumber |
236 return l.lexNumber |
245 } |
248 } |
246 |
249 |
247 func (l *tomlLexer) lexLeftCurlyBrace() tomlLexStateFn { |
250 func (l *tomlLexer) lexLeftCurlyBrace() tomlLexStateFn { |
248 l.next() |
251 l.next() |
249 l.emit(tokenLeftCurlyBrace) |
252 l.emit(tokenLeftCurlyBrace) |
250 return l.lexRvalue |
253 return l.lexVoid |
251 } |
254 } |
252 |
255 |
253 func (l *tomlLexer) lexRightCurlyBrace() tomlLexStateFn { |
256 func (l *tomlLexer) lexRightCurlyBrace() tomlLexStateFn { |
254 l.next() |
257 l.next() |
255 l.emit(tokenRightCurlyBrace) |
258 l.emit(tokenRightCurlyBrace) |
256 return l.lexRvalue |
259 return l.lexVoid |
257 } |
260 } |
258 |
261 |
259 func (l *tomlLexer) lexDate() tomlLexStateFn { |
262 func (l *tomlLexer) lexDate() tomlLexStateFn { |
260 l.emit(tokenDate) |
263 l.emit(tokenDate) |
|
264 return l.lexRvalue |
|
265 } |
|
266 |
|
267 func (l *tomlLexer) lexLocalDate() tomlLexStateFn { |
|
268 l.emit(tokenLocalDate) |
261 return l.lexRvalue |
269 return l.lexRvalue |
262 } |
270 } |
263 |
271 |
264 func (l *tomlLexer) lexTrue() tomlLexStateFn { |
272 func (l *tomlLexer) lexTrue() tomlLexStateFn { |
265 l.fastForward(4) |
273 l.fastForward(4) |
307 l.next() |
315 l.next() |
308 str, err := l.lexStringAsString(`"`, false, true) |
316 str, err := l.lexStringAsString(`"`, false, true) |
309 if err != nil { |
317 if err != nil { |
310 return l.errorf(err.Error()) |
318 return l.errorf(err.Error()) |
311 } |
319 } |
312 growingString += str |
320 growingString += "\"" + str + "\"" |
313 l.next() |
321 l.next() |
314 continue |
322 continue |
315 } else if r == '\'' { |
323 } else if r == '\'' { |
316 l.next() |
324 l.next() |
317 str, err := l.lexLiteralStringAsString(`'`, false) |
325 str, err := l.lexLiteralStringAsString(`'`, false) |
318 if err != nil { |
326 if err != nil { |
319 return l.errorf(err.Error()) |
327 return l.errorf(err.Error()) |
320 } |
328 } |
321 growingString += str |
329 growingString += "'" + str + "'" |
322 l.next() |
330 l.next() |
323 continue |
331 continue |
324 } else if r == '\n' { |
332 } else if r == '\n' { |
325 return l.errorf("keys cannot contain new lines") |
333 return l.errorf("keys cannot contain new lines") |
326 } else if isSpace(r) { |
334 } else if isSpace(r) { |
327 break |
335 break |
|
336 } else if r == '.' { |
|
337 // skip |
328 } else if !isValidBareChar(r) { |
338 } else if !isValidBareChar(r) { |
329 return l.errorf("keys cannot contain %c character", r) |
339 return l.errorf("keys cannot contain %c character", r) |
330 } |
340 } |
331 growingString += string(r) |
341 growingString += string(r) |
332 l.next() |
342 l.next() |
729 state = state() |
739 state = state() |
730 } |
740 } |
731 } |
741 } |
732 |
742 |
733 func init() { |
743 func init() { |
734 dateRegexp = regexp.MustCompile(`^\d{1,4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{1,9})?(Z|[+-]\d{2}:\d{2})`) |
744 // Regexp for all date/time formats supported by TOML. |
|
745 // Group 1: nano precision |
|
746 // Group 2: timezone |
|
747 // |
|
748 // /!\ also matches the empty string |
|
749 // |
|
750 // Example matches: |
|
751 //1979-05-27T07:32:00Z |
|
752 //1979-05-27T00:32:00-07:00 |
|
753 //1979-05-27T00:32:00.999999-07:00 |
|
754 //1979-05-27 07:32:00Z |
|
755 //1979-05-27 00:32:00-07:00 |
|
756 //1979-05-27 00:32:00.999999-07:00 |
|
757 //1979-05-27T07:32:00 |
|
758 //1979-05-27T00:32:00.999999 |
|
759 //1979-05-27 07:32:00 |
|
760 //1979-05-27 00:32:00.999999 |
|
761 //1979-05-27 |
|
762 //07:32:00 |
|
763 //00:32:00.999999 |
|
764 dateRegexp = regexp.MustCompile(`^(?:\d{1,4}-\d{2}-\d{2})?(?:[T ]?\d{2}:\d{2}:\d{2}(\.\d{1,9})?(Z|[+-]\d{2}:\d{2})?)?`) |
735 } |
765 } |
736 |
766 |
737 // Entry point |
767 // Entry point |
738 func lexToml(inputBytes []byte) []token { |
768 func lexToml(inputBytes []byte) []token { |
739 runes := bytes.Runes(inputBytes) |
769 runes := bytes.Runes(inputBytes) |