You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

lexer.go 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807
  1. // TOML lexer.
  2. //
  3. // Written using the principles developed by Rob Pike in
  4. // http://www.youtube.com/watch?v=HxaD_trXwRE
  5. package toml
  6. import (
  7. "bytes"
  8. "errors"
  9. "fmt"
  10. "regexp"
  11. "strconv"
  12. "strings"
  13. )
  14. var dateRegexp *regexp.Regexp
  15. // Define state functions
  16. type tomlLexStateFn func() tomlLexStateFn
  17. // Define lexer
  18. type tomlLexer struct {
  19. inputIdx int
  20. input []rune // Textual source
  21. currentTokenStart int
  22. currentTokenStop int
  23. tokens []token
  24. brackets []rune
  25. line int
  26. col int
  27. endbufferLine int
  28. endbufferCol int
  29. }
  30. // Basic read operations on input
  31. func (l *tomlLexer) read() rune {
  32. r := l.peek()
  33. if r == '\n' {
  34. l.endbufferLine++
  35. l.endbufferCol = 1
  36. } else {
  37. l.endbufferCol++
  38. }
  39. l.inputIdx++
  40. return r
  41. }
  42. func (l *tomlLexer) next() rune {
  43. r := l.read()
  44. if r != eof {
  45. l.currentTokenStop++
  46. }
  47. return r
  48. }
  49. func (l *tomlLexer) ignore() {
  50. l.currentTokenStart = l.currentTokenStop
  51. l.line = l.endbufferLine
  52. l.col = l.endbufferCol
  53. }
  54. func (l *tomlLexer) skip() {
  55. l.next()
  56. l.ignore()
  57. }
  58. func (l *tomlLexer) fastForward(n int) {
  59. for i := 0; i < n; i++ {
  60. l.next()
  61. }
  62. }
  63. func (l *tomlLexer) emitWithValue(t tokenType, value string) {
  64. l.tokens = append(l.tokens, token{
  65. Position: Position{l.line, l.col},
  66. typ: t,
  67. val: value,
  68. })
  69. l.ignore()
  70. }
  71. func (l *tomlLexer) emit(t tokenType) {
  72. l.emitWithValue(t, string(l.input[l.currentTokenStart:l.currentTokenStop]))
  73. }
  74. func (l *tomlLexer) peek() rune {
  75. if l.inputIdx >= len(l.input) {
  76. return eof
  77. }
  78. return l.input[l.inputIdx]
  79. }
  80. func (l *tomlLexer) peekString(size int) string {
  81. maxIdx := len(l.input)
  82. upperIdx := l.inputIdx + size // FIXME: potential overflow
  83. if upperIdx > maxIdx {
  84. upperIdx = maxIdx
  85. }
  86. return string(l.input[l.inputIdx:upperIdx])
  87. }
  88. func (l *tomlLexer) follow(next string) bool {
  89. return next == l.peekString(len(next))
  90. }
  91. // Error management
  92. func (l *tomlLexer) errorf(format string, args ...interface{}) tomlLexStateFn {
  93. l.tokens = append(l.tokens, token{
  94. Position: Position{l.line, l.col},
  95. typ: tokenError,
  96. val: fmt.Sprintf(format, args...),
  97. })
  98. return nil
  99. }
  100. // State functions
  101. func (l *tomlLexer) lexVoid() tomlLexStateFn {
  102. for {
  103. next := l.peek()
  104. switch next {
  105. case '}': // after '{'
  106. return l.lexRightCurlyBrace
  107. case '[':
  108. return l.lexTableKey
  109. case '#':
  110. return l.lexComment(l.lexVoid)
  111. case '=':
  112. return l.lexEqual
  113. case '\r':
  114. fallthrough
  115. case '\n':
  116. l.skip()
  117. continue
  118. }
  119. if isSpace(next) {
  120. l.skip()
  121. }
  122. if isKeyStartChar(next) {
  123. return l.lexKey
  124. }
  125. if next == eof {
  126. l.next()
  127. break
  128. }
  129. }
  130. l.emit(tokenEOF)
  131. return nil
  132. }
  133. func (l *tomlLexer) lexRvalue() tomlLexStateFn {
  134. for {
  135. next := l.peek()
  136. switch next {
  137. case '.':
  138. return l.errorf("cannot start float with a dot")
  139. case '=':
  140. return l.lexEqual
  141. case '[':
  142. return l.lexLeftBracket
  143. case ']':
  144. return l.lexRightBracket
  145. case '{':
  146. return l.lexLeftCurlyBrace
  147. case '}':
  148. return l.lexRightCurlyBrace
  149. case '#':
  150. return l.lexComment(l.lexRvalue)
  151. case '"':
  152. return l.lexString
  153. case '\'':
  154. return l.lexLiteralString
  155. case ',':
  156. return l.lexComma
  157. case '\r':
  158. fallthrough
  159. case '\n':
  160. l.skip()
  161. if len(l.brackets) > 0 && l.brackets[len(l.brackets)-1] == '[' {
  162. return l.lexRvalue
  163. }
  164. return l.lexVoid
  165. }
  166. if l.follow("true") {
  167. return l.lexTrue
  168. }
  169. if l.follow("false") {
  170. return l.lexFalse
  171. }
  172. if l.follow("inf") {
  173. return l.lexInf
  174. }
  175. if l.follow("nan") {
  176. return l.lexNan
  177. }
  178. if isSpace(next) {
  179. l.skip()
  180. continue
  181. }
  182. if next == eof {
  183. l.next()
  184. break
  185. }
  186. possibleDate := l.peekString(35)
  187. dateSubmatches := dateRegexp.FindStringSubmatch(possibleDate)
  188. if dateSubmatches != nil && dateSubmatches[0] != "" {
  189. l.fastForward(len(dateSubmatches[0]))
  190. if dateSubmatches[2] == "" { // no timezone information => local date
  191. return l.lexLocalDate
  192. }
  193. return l.lexDate
  194. }
  195. if next == '+' || next == '-' || isDigit(next) {
  196. return l.lexNumber
  197. }
  198. return l.errorf("no value can start with %c", next)
  199. }
  200. l.emit(tokenEOF)
  201. return nil
  202. }
  203. func (l *tomlLexer) lexLeftCurlyBrace() tomlLexStateFn {
  204. l.next()
  205. l.emit(tokenLeftCurlyBrace)
  206. l.brackets = append(l.brackets, '{')
  207. return l.lexVoid
  208. }
  209. func (l *tomlLexer) lexRightCurlyBrace() tomlLexStateFn {
  210. l.next()
  211. l.emit(tokenRightCurlyBrace)
  212. if len(l.brackets) == 0 || l.brackets[len(l.brackets)-1] != '{' {
  213. return l.errorf("cannot have '}' here")
  214. }
  215. l.brackets = l.brackets[:len(l.brackets)-1]
  216. return l.lexRvalue
  217. }
  218. func (l *tomlLexer) lexDate() tomlLexStateFn {
  219. l.emit(tokenDate)
  220. return l.lexRvalue
  221. }
  222. func (l *tomlLexer) lexLocalDate() tomlLexStateFn {
  223. l.emit(tokenLocalDate)
  224. return l.lexRvalue
  225. }
  226. func (l *tomlLexer) lexTrue() tomlLexStateFn {
  227. l.fastForward(4)
  228. l.emit(tokenTrue)
  229. return l.lexRvalue
  230. }
  231. func (l *tomlLexer) lexFalse() tomlLexStateFn {
  232. l.fastForward(5)
  233. l.emit(tokenFalse)
  234. return l.lexRvalue
  235. }
  236. func (l *tomlLexer) lexInf() tomlLexStateFn {
  237. l.fastForward(3)
  238. l.emit(tokenInf)
  239. return l.lexRvalue
  240. }
  241. func (l *tomlLexer) lexNan() tomlLexStateFn {
  242. l.fastForward(3)
  243. l.emit(tokenNan)
  244. return l.lexRvalue
  245. }
  246. func (l *tomlLexer) lexEqual() tomlLexStateFn {
  247. l.next()
  248. l.emit(tokenEqual)
  249. return l.lexRvalue
  250. }
  251. func (l *tomlLexer) lexComma() tomlLexStateFn {
  252. l.next()
  253. l.emit(tokenComma)
  254. if len(l.brackets) > 0 && l.brackets[len(l.brackets)-1] == '{' {
  255. return l.lexVoid
  256. }
  257. return l.lexRvalue
  258. }
  259. // Parse the key and emits its value without escape sequences.
  260. // bare keys, basic string keys and literal string keys are supported.
  261. func (l *tomlLexer) lexKey() tomlLexStateFn {
  262. var sb strings.Builder
  263. for r := l.peek(); isKeyChar(r) || r == '\n' || r == '\r'; r = l.peek() {
  264. if r == '"' {
  265. l.next()
  266. str, err := l.lexStringAsString(`"`, false, true)
  267. if err != nil {
  268. return l.errorf(err.Error())
  269. }
  270. sb.WriteString("\"")
  271. sb.WriteString(str)
  272. sb.WriteString("\"")
  273. l.next()
  274. continue
  275. } else if r == '\'' {
  276. l.next()
  277. str, err := l.lexLiteralStringAsString(`'`, false)
  278. if err != nil {
  279. return l.errorf(err.Error())
  280. }
  281. sb.WriteString("'")
  282. sb.WriteString(str)
  283. sb.WriteString("'")
  284. l.next()
  285. continue
  286. } else if r == '\n' {
  287. return l.errorf("keys cannot contain new lines")
  288. } else if isSpace(r) {
  289. var str strings.Builder
  290. str.WriteString(" ")
  291. // skip trailing whitespace
  292. l.next()
  293. for r = l.peek(); isSpace(r); r = l.peek() {
  294. str.WriteRune(r)
  295. l.next()
  296. }
  297. // break loop if not a dot
  298. if r != '.' {
  299. break
  300. }
  301. str.WriteString(".")
  302. // skip trailing whitespace after dot
  303. l.next()
  304. for r = l.peek(); isSpace(r); r = l.peek() {
  305. str.WriteRune(r)
  306. l.next()
  307. }
  308. sb.WriteString(str.String())
  309. continue
  310. } else if r == '.' {
  311. // skip
  312. } else if !isValidBareChar(r) {
  313. return l.errorf("keys cannot contain %c character", r)
  314. }
  315. sb.WriteRune(r)
  316. l.next()
  317. }
  318. l.emitWithValue(tokenKey, sb.String())
  319. return l.lexVoid
  320. }
  321. func (l *tomlLexer) lexComment(previousState tomlLexStateFn) tomlLexStateFn {
  322. return func() tomlLexStateFn {
  323. for next := l.peek(); next != '\n' && next != eof; next = l.peek() {
  324. if next == '\r' && l.follow("\r\n") {
  325. break
  326. }
  327. l.next()
  328. }
  329. l.ignore()
  330. return previousState
  331. }
  332. }
  333. func (l *tomlLexer) lexLeftBracket() tomlLexStateFn {
  334. l.next()
  335. l.emit(tokenLeftBracket)
  336. l.brackets = append(l.brackets, '[')
  337. return l.lexRvalue
  338. }
  339. func (l *tomlLexer) lexLiteralStringAsString(terminator string, discardLeadingNewLine bool) (string, error) {
  340. var sb strings.Builder
  341. if discardLeadingNewLine {
  342. if l.follow("\r\n") {
  343. l.skip()
  344. l.skip()
  345. } else if l.peek() == '\n' {
  346. l.skip()
  347. }
  348. }
  349. // find end of string
  350. for {
  351. if l.follow(terminator) {
  352. return sb.String(), nil
  353. }
  354. next := l.peek()
  355. if next == eof {
  356. break
  357. }
  358. sb.WriteRune(l.next())
  359. }
  360. return "", errors.New("unclosed string")
  361. }
  362. func (l *tomlLexer) lexLiteralString() tomlLexStateFn {
  363. l.skip()
  364. // handle special case for triple-quote
  365. terminator := "'"
  366. discardLeadingNewLine := false
  367. if l.follow("''") {
  368. l.skip()
  369. l.skip()
  370. terminator = "'''"
  371. discardLeadingNewLine = true
  372. }
  373. str, err := l.lexLiteralStringAsString(terminator, discardLeadingNewLine)
  374. if err != nil {
  375. return l.errorf(err.Error())
  376. }
  377. l.emitWithValue(tokenString, str)
  378. l.fastForward(len(terminator))
  379. l.ignore()
  380. return l.lexRvalue
  381. }
  382. // Lex a string and return the results as a string.
  383. // Terminator is the substring indicating the end of the token.
  384. // The resulting string does not include the terminator.
  385. func (l *tomlLexer) lexStringAsString(terminator string, discardLeadingNewLine, acceptNewLines bool) (string, error) {
  386. var sb strings.Builder
  387. if discardLeadingNewLine {
  388. if l.follow("\r\n") {
  389. l.skip()
  390. l.skip()
  391. } else if l.peek() == '\n' {
  392. l.skip()
  393. }
  394. }
  395. for {
  396. if l.follow(terminator) {
  397. return sb.String(), nil
  398. }
  399. if l.follow("\\") {
  400. l.next()
  401. switch l.peek() {
  402. case '\r':
  403. fallthrough
  404. case '\n':
  405. fallthrough
  406. case '\t':
  407. fallthrough
  408. case ' ':
  409. // skip all whitespace chars following backslash
  410. for strings.ContainsRune("\r\n\t ", l.peek()) {
  411. l.next()
  412. }
  413. case '"':
  414. sb.WriteString("\"")
  415. l.next()
  416. case 'n':
  417. sb.WriteString("\n")
  418. l.next()
  419. case 'b':
  420. sb.WriteString("\b")
  421. l.next()
  422. case 'f':
  423. sb.WriteString("\f")
  424. l.next()
  425. case '/':
  426. sb.WriteString("/")
  427. l.next()
  428. case 't':
  429. sb.WriteString("\t")
  430. l.next()
  431. case 'r':
  432. sb.WriteString("\r")
  433. l.next()
  434. case '\\':
  435. sb.WriteString("\\")
  436. l.next()
  437. case 'u':
  438. l.next()
  439. var code strings.Builder
  440. for i := 0; i < 4; i++ {
  441. c := l.peek()
  442. if !isHexDigit(c) {
  443. return "", errors.New("unfinished unicode escape")
  444. }
  445. l.next()
  446. code.WriteRune(c)
  447. }
  448. intcode, err := strconv.ParseInt(code.String(), 16, 32)
  449. if err != nil {
  450. return "", errors.New("invalid unicode escape: \\u" + code.String())
  451. }
  452. sb.WriteRune(rune(intcode))
  453. case 'U':
  454. l.next()
  455. var code strings.Builder
  456. for i := 0; i < 8; i++ {
  457. c := l.peek()
  458. if !isHexDigit(c) {
  459. return "", errors.New("unfinished unicode escape")
  460. }
  461. l.next()
  462. code.WriteRune(c)
  463. }
  464. intcode, err := strconv.ParseInt(code.String(), 16, 64)
  465. if err != nil {
  466. return "", errors.New("invalid unicode escape: \\U" + code.String())
  467. }
  468. sb.WriteRune(rune(intcode))
  469. default:
  470. return "", errors.New("invalid escape sequence: \\" + string(l.peek()))
  471. }
  472. } else {
  473. r := l.peek()
  474. if 0x00 <= r && r <= 0x1F && r != '\t' && !(acceptNewLines && (r == '\n' || r == '\r')) {
  475. return "", fmt.Errorf("unescaped control character %U", r)
  476. }
  477. l.next()
  478. sb.WriteRune(r)
  479. }
  480. if l.peek() == eof {
  481. break
  482. }
  483. }
  484. return "", errors.New("unclosed string")
  485. }
  486. func (l *tomlLexer) lexString() tomlLexStateFn {
  487. l.skip()
  488. // handle special case for triple-quote
  489. terminator := `"`
  490. discardLeadingNewLine := false
  491. acceptNewLines := false
  492. if l.follow(`""`) {
  493. l.skip()
  494. l.skip()
  495. terminator = `"""`
  496. discardLeadingNewLine = true
  497. acceptNewLines = true
  498. }
  499. str, err := l.lexStringAsString(terminator, discardLeadingNewLine, acceptNewLines)
  500. if err != nil {
  501. return l.errorf(err.Error())
  502. }
  503. l.emitWithValue(tokenString, str)
  504. l.fastForward(len(terminator))
  505. l.ignore()
  506. return l.lexRvalue
  507. }
  508. func (l *tomlLexer) lexTableKey() tomlLexStateFn {
  509. l.next()
  510. if l.peek() == '[' {
  511. // token '[[' signifies an array of tables
  512. l.next()
  513. l.emit(tokenDoubleLeftBracket)
  514. return l.lexInsideTableArrayKey
  515. }
  516. // vanilla table key
  517. l.emit(tokenLeftBracket)
  518. return l.lexInsideTableKey
  519. }
  520. // Parse the key till "]]", but only bare keys are supported
  521. func (l *tomlLexer) lexInsideTableArrayKey() tomlLexStateFn {
  522. for r := l.peek(); r != eof; r = l.peek() {
  523. switch r {
  524. case ']':
  525. if l.currentTokenStop > l.currentTokenStart {
  526. l.emit(tokenKeyGroupArray)
  527. }
  528. l.next()
  529. if l.peek() != ']' {
  530. break
  531. }
  532. l.next()
  533. l.emit(tokenDoubleRightBracket)
  534. return l.lexVoid
  535. case '[':
  536. return l.errorf("table array key cannot contain ']'")
  537. default:
  538. l.next()
  539. }
  540. }
  541. return l.errorf("unclosed table array key")
  542. }
  543. // Parse the key till "]" but only bare keys are supported
  544. func (l *tomlLexer) lexInsideTableKey() tomlLexStateFn {
  545. for r := l.peek(); r != eof; r = l.peek() {
  546. switch r {
  547. case ']':
  548. if l.currentTokenStop > l.currentTokenStart {
  549. l.emit(tokenKeyGroup)
  550. }
  551. l.next()
  552. l.emit(tokenRightBracket)
  553. return l.lexVoid
  554. case '[':
  555. return l.errorf("table key cannot contain ']'")
  556. default:
  557. l.next()
  558. }
  559. }
  560. return l.errorf("unclosed table key")
  561. }
  562. func (l *tomlLexer) lexRightBracket() tomlLexStateFn {
  563. l.next()
  564. l.emit(tokenRightBracket)
  565. if len(l.brackets) == 0 || l.brackets[len(l.brackets)-1] != '[' {
  566. return l.errorf("cannot have ']' here")
  567. }
  568. l.brackets = l.brackets[:len(l.brackets)-1]
  569. return l.lexRvalue
  570. }
  571. type validRuneFn func(r rune) bool
  572. func isValidHexRune(r rune) bool {
  573. return r >= 'a' && r <= 'f' ||
  574. r >= 'A' && r <= 'F' ||
  575. r >= '0' && r <= '9' ||
  576. r == '_'
  577. }
  578. func isValidOctalRune(r rune) bool {
  579. return r >= '0' && r <= '7' || r == '_'
  580. }
  581. func isValidBinaryRune(r rune) bool {
  582. return r == '0' || r == '1' || r == '_'
  583. }
  584. func (l *tomlLexer) lexNumber() tomlLexStateFn {
  585. r := l.peek()
  586. if r == '0' {
  587. follow := l.peekString(2)
  588. if len(follow) == 2 {
  589. var isValidRune validRuneFn
  590. switch follow[1] {
  591. case 'x':
  592. isValidRune = isValidHexRune
  593. case 'o':
  594. isValidRune = isValidOctalRune
  595. case 'b':
  596. isValidRune = isValidBinaryRune
  597. default:
  598. if follow[1] >= 'a' && follow[1] <= 'z' || follow[1] >= 'A' && follow[1] <= 'Z' {
  599. return l.errorf("unknown number base: %s. possible options are x (hex) o (octal) b (binary)", string(follow[1]))
  600. }
  601. }
  602. if isValidRune != nil {
  603. l.next()
  604. l.next()
  605. digitSeen := false
  606. for {
  607. next := l.peek()
  608. if !isValidRune(next) {
  609. break
  610. }
  611. digitSeen = true
  612. l.next()
  613. }
  614. if !digitSeen {
  615. return l.errorf("number needs at least one digit")
  616. }
  617. l.emit(tokenInteger)
  618. return l.lexRvalue
  619. }
  620. }
  621. }
  622. if r == '+' || r == '-' {
  623. l.next()
  624. if l.follow("inf") {
  625. return l.lexInf
  626. }
  627. if l.follow("nan") {
  628. return l.lexNan
  629. }
  630. }
  631. pointSeen := false
  632. expSeen := false
  633. digitSeen := false
  634. for {
  635. next := l.peek()
  636. if next == '.' {
  637. if pointSeen {
  638. return l.errorf("cannot have two dots in one float")
  639. }
  640. l.next()
  641. if !isDigit(l.peek()) {
  642. return l.errorf("float cannot end with a dot")
  643. }
  644. pointSeen = true
  645. } else if next == 'e' || next == 'E' {
  646. expSeen = true
  647. l.next()
  648. r := l.peek()
  649. if r == '+' || r == '-' {
  650. l.next()
  651. }
  652. } else if isDigit(next) {
  653. digitSeen = true
  654. l.next()
  655. } else if next == '_' {
  656. l.next()
  657. } else {
  658. break
  659. }
  660. if pointSeen && !digitSeen {
  661. return l.errorf("cannot start float with a dot")
  662. }
  663. }
  664. if !digitSeen {
  665. return l.errorf("no digit in that number")
  666. }
  667. if pointSeen || expSeen {
  668. l.emit(tokenFloat)
  669. } else {
  670. l.emit(tokenInteger)
  671. }
  672. return l.lexRvalue
  673. }
  674. func (l *tomlLexer) run() {
  675. for state := l.lexVoid; state != nil; {
  676. state = state()
  677. }
  678. }
  679. func init() {
  680. // Regexp for all date/time formats supported by TOML.
  681. // Group 1: nano precision
  682. // Group 2: timezone
  683. //
  684. // /!\ also matches the empty string
  685. //
  686. // Example matches:
  687. // 1979-05-27T07:32:00Z
  688. // 1979-05-27T00:32:00-07:00
  689. // 1979-05-27T00:32:00.999999-07:00
  690. // 1979-05-27 07:32:00Z
  691. // 1979-05-27 00:32:00-07:00
  692. // 1979-05-27 00:32:00.999999-07:00
  693. // 1979-05-27T07:32:00
  694. // 1979-05-27T00:32:00.999999
  695. // 1979-05-27 07:32:00
  696. // 1979-05-27 00:32:00.999999
  697. // 1979-05-27
  698. // 07:32:00
  699. // 00:32:00.999999
  700. 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})?)?`)
  701. }
  702. // Entry point
  703. func lexToml(inputBytes []byte) []token {
  704. runes := bytes.Runes(inputBytes)
  705. l := &tomlLexer{
  706. input: runes,
  707. tokens: make([]token, 0, 256),
  708. line: 1,
  709. col: 1,
  710. endbufferLine: 1,
  711. endbufferCol: 1,
  712. }
  713. l.run()
  714. return l.tokens
  715. }