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.

764 lines
20 KiB

  1. package toml
  2. import (
  3. "fmt"
  4. "strconv"
  5. "strings"
  6. "time"
  7. "unicode/utf8"
  8. "github.com/BurntSushi/toml/internal"
  9. )
  10. type parser struct {
  11. lx *lexer
  12. context Key // Full key for the current hash in scope.
  13. currentKey string // Base key name for everything except hashes.
  14. pos Position // Current position in the TOML file.
  15. ordered []Key // List of keys in the order that they appear in the TOML data.
  16. mapping map[string]interface{} // Map keyname → key value.
  17. types map[string]tomlType // Map keyname → TOML type.
  18. implicits map[string]struct{} // Record implicit keys (e.g. "key.group.names").
  19. }
  20. func parse(data string) (p *parser, err error) {
  21. defer func() {
  22. if r := recover(); r != nil {
  23. if pErr, ok := r.(ParseError); ok {
  24. pErr.input = data
  25. err = pErr
  26. return
  27. }
  28. panic(r)
  29. }
  30. }()
  31. // Read over BOM; do this here as the lexer calls utf8.DecodeRuneInString()
  32. // which mangles stuff.
  33. if strings.HasPrefix(data, "\xff\xfe") || strings.HasPrefix(data, "\xfe\xff") {
  34. data = data[2:]
  35. }
  36. // Examine first few bytes for NULL bytes; this probably means it's a UTF-16
  37. // file (second byte in surrogate pair being NULL). Again, do this here to
  38. // avoid having to deal with UTF-8/16 stuff in the lexer.
  39. ex := 6
  40. if len(data) < 6 {
  41. ex = len(data)
  42. }
  43. if i := strings.IndexRune(data[:ex], 0); i > -1 {
  44. return nil, ParseError{
  45. Message: "files cannot contain NULL bytes; probably using UTF-16; TOML files must be UTF-8",
  46. Position: Position{Line: 1, Start: i, Len: 1},
  47. Line: 1,
  48. input: data,
  49. }
  50. }
  51. p = &parser{
  52. mapping: make(map[string]interface{}),
  53. types: make(map[string]tomlType),
  54. lx: lex(data),
  55. ordered: make([]Key, 0),
  56. implicits: make(map[string]struct{}),
  57. }
  58. for {
  59. item := p.next()
  60. if item.typ == itemEOF {
  61. break
  62. }
  63. p.topLevel(item)
  64. }
  65. return p, nil
  66. }
  67. func (p *parser) panicItemf(it item, format string, v ...interface{}) {
  68. panic(ParseError{
  69. Message: fmt.Sprintf(format, v...),
  70. Position: it.pos,
  71. Line: it.pos.Len,
  72. LastKey: p.current(),
  73. })
  74. }
  75. func (p *parser) panicf(format string, v ...interface{}) {
  76. panic(ParseError{
  77. Message: fmt.Sprintf(format, v...),
  78. Position: p.pos,
  79. Line: p.pos.Line,
  80. LastKey: p.current(),
  81. })
  82. }
  83. func (p *parser) next() item {
  84. it := p.lx.nextItem()
  85. //fmt.Printf("ITEM %-18s line %-3d │ %q\n", it.typ, it.line, it.val)
  86. if it.typ == itemError {
  87. if it.err != nil {
  88. panic(ParseError{
  89. Position: it.pos,
  90. Line: it.pos.Line,
  91. LastKey: p.current(),
  92. err: it.err,
  93. })
  94. }
  95. p.panicItemf(it, "%s", it.val)
  96. }
  97. return it
  98. }
  99. func (p *parser) nextPos() item {
  100. it := p.next()
  101. p.pos = it.pos
  102. return it
  103. }
  104. func (p *parser) bug(format string, v ...interface{}) {
  105. panic(fmt.Sprintf("BUG: "+format+"\n\n", v...))
  106. }
  107. func (p *parser) expect(typ itemType) item {
  108. it := p.next()
  109. p.assertEqual(typ, it.typ)
  110. return it
  111. }
  112. func (p *parser) assertEqual(expected, got itemType) {
  113. if expected != got {
  114. p.bug("Expected '%s' but got '%s'.", expected, got)
  115. }
  116. }
  117. func (p *parser) topLevel(item item) {
  118. switch item.typ {
  119. case itemCommentStart: // # ..
  120. p.expect(itemText)
  121. case itemTableStart: // [ .. ]
  122. name := p.nextPos()
  123. var key Key
  124. for ; name.typ != itemTableEnd && name.typ != itemEOF; name = p.next() {
  125. key = append(key, p.keyString(name))
  126. }
  127. p.assertEqual(itemTableEnd, name.typ)
  128. p.addContext(key, false)
  129. p.setType("", tomlHash)
  130. p.ordered = append(p.ordered, key)
  131. case itemArrayTableStart: // [[ .. ]]
  132. name := p.nextPos()
  133. var key Key
  134. for ; name.typ != itemArrayTableEnd && name.typ != itemEOF; name = p.next() {
  135. key = append(key, p.keyString(name))
  136. }
  137. p.assertEqual(itemArrayTableEnd, name.typ)
  138. p.addContext(key, true)
  139. p.setType("", tomlArrayHash)
  140. p.ordered = append(p.ordered, key)
  141. case itemKeyStart: // key = ..
  142. outerContext := p.context
  143. /// Read all the key parts (e.g. 'a' and 'b' in 'a.b')
  144. k := p.nextPos()
  145. var key Key
  146. for ; k.typ != itemKeyEnd && k.typ != itemEOF; k = p.next() {
  147. key = append(key, p.keyString(k))
  148. }
  149. p.assertEqual(itemKeyEnd, k.typ)
  150. /// The current key is the last part.
  151. p.currentKey = key[len(key)-1]
  152. /// All the other parts (if any) are the context; need to set each part
  153. /// as implicit.
  154. context := key[:len(key)-1]
  155. for i := range context {
  156. p.addImplicitContext(append(p.context, context[i:i+1]...))
  157. }
  158. /// Set value.
  159. val, typ := p.value(p.next(), false)
  160. p.set(p.currentKey, val, typ)
  161. p.ordered = append(p.ordered, p.context.add(p.currentKey))
  162. /// Remove the context we added (preserving any context from [tbl] lines).
  163. p.context = outerContext
  164. p.currentKey = ""
  165. default:
  166. p.bug("Unexpected type at top level: %s", item.typ)
  167. }
  168. }
  169. // Gets a string for a key (or part of a key in a table name).
  170. func (p *parser) keyString(it item) string {
  171. switch it.typ {
  172. case itemText:
  173. return it.val
  174. case itemString, itemMultilineString,
  175. itemRawString, itemRawMultilineString:
  176. s, _ := p.value(it, false)
  177. return s.(string)
  178. default:
  179. p.bug("Unexpected key type: %s", it.typ)
  180. }
  181. panic("unreachable")
  182. }
  183. var datetimeRepl = strings.NewReplacer(
  184. "z", "Z",
  185. "t", "T",
  186. " ", "T")
  187. // value translates an expected value from the lexer into a Go value wrapped
  188. // as an empty interface.
  189. func (p *parser) value(it item, parentIsArray bool) (interface{}, tomlType) {
  190. switch it.typ {
  191. case itemString:
  192. return p.replaceEscapes(it, it.val), p.typeOfPrimitive(it)
  193. case itemMultilineString:
  194. return p.replaceEscapes(it, stripFirstNewline(stripEscapedNewlines(it.val))), p.typeOfPrimitive(it)
  195. case itemRawString:
  196. return it.val, p.typeOfPrimitive(it)
  197. case itemRawMultilineString:
  198. return stripFirstNewline(it.val), p.typeOfPrimitive(it)
  199. case itemInteger:
  200. return p.valueInteger(it)
  201. case itemFloat:
  202. return p.valueFloat(it)
  203. case itemBool:
  204. switch it.val {
  205. case "true":
  206. return true, p.typeOfPrimitive(it)
  207. case "false":
  208. return false, p.typeOfPrimitive(it)
  209. default:
  210. p.bug("Expected boolean value, but got '%s'.", it.val)
  211. }
  212. case itemDatetime:
  213. return p.valueDatetime(it)
  214. case itemArray:
  215. return p.valueArray(it)
  216. case itemInlineTableStart:
  217. return p.valueInlineTable(it, parentIsArray)
  218. default:
  219. p.bug("Unexpected value type: %s", it.typ)
  220. }
  221. panic("unreachable")
  222. }
  223. func (p *parser) valueInteger(it item) (interface{}, tomlType) {
  224. if !numUnderscoresOK(it.val) {
  225. p.panicItemf(it, "Invalid integer %q: underscores must be surrounded by digits", it.val)
  226. }
  227. if numHasLeadingZero(it.val) {
  228. p.panicItemf(it, "Invalid integer %q: cannot have leading zeroes", it.val)
  229. }
  230. num, err := strconv.ParseInt(it.val, 0, 64)
  231. if err != nil {
  232. // Distinguish integer values. Normally, it'd be a bug if the lexer
  233. // provides an invalid integer, but it's possible that the number is
  234. // out of range of valid values (which the lexer cannot determine).
  235. // So mark the former as a bug but the latter as a legitimate user
  236. // error.
  237. if e, ok := err.(*strconv.NumError); ok && e.Err == strconv.ErrRange {
  238. p.panicItemf(it, "Integer '%s' is out of the range of 64-bit signed integers.", it.val)
  239. } else {
  240. p.bug("Expected integer value, but got '%s'.", it.val)
  241. }
  242. }
  243. return num, p.typeOfPrimitive(it)
  244. }
  245. func (p *parser) valueFloat(it item) (interface{}, tomlType) {
  246. parts := strings.FieldsFunc(it.val, func(r rune) bool {
  247. switch r {
  248. case '.', 'e', 'E':
  249. return true
  250. }
  251. return false
  252. })
  253. for _, part := range parts {
  254. if !numUnderscoresOK(part) {
  255. p.panicItemf(it, "Invalid float %q: underscores must be surrounded by digits", it.val)
  256. }
  257. }
  258. if len(parts) > 0 && numHasLeadingZero(parts[0]) {
  259. p.panicItemf(it, "Invalid float %q: cannot have leading zeroes", it.val)
  260. }
  261. if !numPeriodsOK(it.val) {
  262. // As a special case, numbers like '123.' or '1.e2',
  263. // which are valid as far as Go/strconv are concerned,
  264. // must be rejected because TOML says that a fractional
  265. // part consists of '.' followed by 1+ digits.
  266. p.panicItemf(it, "Invalid float %q: '.' must be followed by one or more digits", it.val)
  267. }
  268. val := strings.Replace(it.val, "_", "", -1)
  269. if val == "+nan" || val == "-nan" { // Go doesn't support this, but TOML spec does.
  270. val = "nan"
  271. }
  272. num, err := strconv.ParseFloat(val, 64)
  273. if err != nil {
  274. if e, ok := err.(*strconv.NumError); ok && e.Err == strconv.ErrRange {
  275. p.panicItemf(it, "Float '%s' is out of the range of 64-bit IEEE-754 floating-point numbers.", it.val)
  276. } else {
  277. p.panicItemf(it, "Invalid float value: %q", it.val)
  278. }
  279. }
  280. return num, p.typeOfPrimitive(it)
  281. }
  282. var dtTypes = []struct {
  283. fmt string
  284. zone *time.Location
  285. }{
  286. {time.RFC3339Nano, time.Local},
  287. {"2006-01-02T15:04:05.999999999", internal.LocalDatetime},
  288. {"2006-01-02", internal.LocalDate},
  289. {"15:04:05.999999999", internal.LocalTime},
  290. }
  291. func (p *parser) valueDatetime(it item) (interface{}, tomlType) {
  292. it.val = datetimeRepl.Replace(it.val)
  293. var (
  294. t time.Time
  295. ok bool
  296. err error
  297. )
  298. for _, dt := range dtTypes {
  299. t, err = time.ParseInLocation(dt.fmt, it.val, dt.zone)
  300. if err == nil {
  301. ok = true
  302. break
  303. }
  304. }
  305. if !ok {
  306. p.panicItemf(it, "Invalid TOML Datetime: %q.", it.val)
  307. }
  308. return t, p.typeOfPrimitive(it)
  309. }
  310. func (p *parser) valueArray(it item) (interface{}, tomlType) {
  311. p.setType(p.currentKey, tomlArray)
  312. // p.setType(p.currentKey, typ)
  313. var (
  314. types []tomlType
  315. // Initialize to a non-nil empty slice. This makes it consistent with
  316. // how S = [] decodes into a non-nil slice inside something like struct
  317. // { S []string }. See #338
  318. array = []interface{}{}
  319. )
  320. for it = p.next(); it.typ != itemArrayEnd; it = p.next() {
  321. if it.typ == itemCommentStart {
  322. p.expect(itemText)
  323. continue
  324. }
  325. val, typ := p.value(it, true)
  326. array = append(array, val)
  327. types = append(types, typ)
  328. // XXX: types isn't used here, we need it to record the accurate type
  329. // information.
  330. //
  331. // Not entirely sure how to best store this; could use "key[0]",
  332. // "key[1]" notation, or maybe store it on the Array type?
  333. }
  334. return array, tomlArray
  335. }
  336. func (p *parser) valueInlineTable(it item, parentIsArray bool) (interface{}, tomlType) {
  337. var (
  338. hash = make(map[string]interface{})
  339. outerContext = p.context
  340. outerKey = p.currentKey
  341. )
  342. p.context = append(p.context, p.currentKey)
  343. prevContext := p.context
  344. p.currentKey = ""
  345. p.addImplicit(p.context)
  346. p.addContext(p.context, parentIsArray)
  347. /// Loop over all table key/value pairs.
  348. for it := p.next(); it.typ != itemInlineTableEnd; it = p.next() {
  349. if it.typ == itemCommentStart {
  350. p.expect(itemText)
  351. continue
  352. }
  353. /// Read all key parts.
  354. k := p.nextPos()
  355. var key Key
  356. for ; k.typ != itemKeyEnd && k.typ != itemEOF; k = p.next() {
  357. key = append(key, p.keyString(k))
  358. }
  359. p.assertEqual(itemKeyEnd, k.typ)
  360. /// The current key is the last part.
  361. p.currentKey = key[len(key)-1]
  362. /// All the other parts (if any) are the context; need to set each part
  363. /// as implicit.
  364. context := key[:len(key)-1]
  365. for i := range context {
  366. p.addImplicitContext(append(p.context, context[i:i+1]...))
  367. }
  368. /// Set the value.
  369. val, typ := p.value(p.next(), false)
  370. p.set(p.currentKey, val, typ)
  371. p.ordered = append(p.ordered, p.context.add(p.currentKey))
  372. hash[p.currentKey] = val
  373. /// Restore context.
  374. p.context = prevContext
  375. }
  376. p.context = outerContext
  377. p.currentKey = outerKey
  378. return hash, tomlHash
  379. }
  380. // numHasLeadingZero checks if this number has leading zeroes, allowing for '0',
  381. // +/- signs, and base prefixes.
  382. func numHasLeadingZero(s string) bool {
  383. if len(s) > 1 && s[0] == '0' && !(s[1] == 'b' || s[1] == 'o' || s[1] == 'x') { // Allow 0b, 0o, 0x
  384. return true
  385. }
  386. if len(s) > 2 && (s[0] == '-' || s[0] == '+') && s[1] == '0' {
  387. return true
  388. }
  389. return false
  390. }
  391. // numUnderscoresOK checks whether each underscore in s is surrounded by
  392. // characters that are not underscores.
  393. func numUnderscoresOK(s string) bool {
  394. switch s {
  395. case "nan", "+nan", "-nan", "inf", "-inf", "+inf":
  396. return true
  397. }
  398. accept := false
  399. for _, r := range s {
  400. if r == '_' {
  401. if !accept {
  402. return false
  403. }
  404. }
  405. // isHexadecimal is a superset of all the permissable characters
  406. // surrounding an underscore.
  407. accept = isHexadecimal(r)
  408. }
  409. return accept
  410. }
  411. // numPeriodsOK checks whether every period in s is followed by a digit.
  412. func numPeriodsOK(s string) bool {
  413. period := false
  414. for _, r := range s {
  415. if period && !isDigit(r) {
  416. return false
  417. }
  418. period = r == '.'
  419. }
  420. return !period
  421. }
  422. // Set the current context of the parser, where the context is either a hash or
  423. // an array of hashes, depending on the value of the `array` parameter.
  424. //
  425. // Establishing the context also makes sure that the key isn't a duplicate, and
  426. // will create implicit hashes automatically.
  427. func (p *parser) addContext(key Key, array bool) {
  428. var ok bool
  429. // Always start at the top level and drill down for our context.
  430. hashContext := p.mapping
  431. keyContext := make(Key, 0)
  432. // We only need implicit hashes for key[0:-1]
  433. for _, k := range key[0 : len(key)-1] {
  434. _, ok = hashContext[k]
  435. keyContext = append(keyContext, k)
  436. // No key? Make an implicit hash and move on.
  437. if !ok {
  438. p.addImplicit(keyContext)
  439. hashContext[k] = make(map[string]interface{})
  440. }
  441. // If the hash context is actually an array of tables, then set
  442. // the hash context to the last element in that array.
  443. //
  444. // Otherwise, it better be a table, since this MUST be a key group (by
  445. // virtue of it not being the last element in a key).
  446. switch t := hashContext[k].(type) {
  447. case []map[string]interface{}:
  448. hashContext = t[len(t)-1]
  449. case map[string]interface{}:
  450. hashContext = t
  451. default:
  452. p.panicf("Key '%s' was already created as a hash.", keyContext)
  453. }
  454. }
  455. p.context = keyContext
  456. if array {
  457. // If this is the first element for this array, then allocate a new
  458. // list of tables for it.
  459. k := key[len(key)-1]
  460. if _, ok := hashContext[k]; !ok {
  461. hashContext[k] = make([]map[string]interface{}, 0, 4)
  462. }
  463. // Add a new table. But make sure the key hasn't already been used
  464. // for something else.
  465. if hash, ok := hashContext[k].([]map[string]interface{}); ok {
  466. hashContext[k] = append(hash, make(map[string]interface{}))
  467. } else {
  468. p.panicf("Key '%s' was already created and cannot be used as an array.", key)
  469. }
  470. } else {
  471. p.setValue(key[len(key)-1], make(map[string]interface{}))
  472. }
  473. p.context = append(p.context, key[len(key)-1])
  474. }
  475. // set calls setValue and setType.
  476. func (p *parser) set(key string, val interface{}, typ tomlType) {
  477. p.setValue(key, val)
  478. p.setType(key, typ)
  479. }
  480. // setValue sets the given key to the given value in the current context.
  481. // It will make sure that the key hasn't already been defined, account for
  482. // implicit key groups.
  483. func (p *parser) setValue(key string, value interface{}) {
  484. var (
  485. tmpHash interface{}
  486. ok bool
  487. hash = p.mapping
  488. keyContext Key
  489. )
  490. for _, k := range p.context {
  491. keyContext = append(keyContext, k)
  492. if tmpHash, ok = hash[k]; !ok {
  493. p.bug("Context for key '%s' has not been established.", keyContext)
  494. }
  495. switch t := tmpHash.(type) {
  496. case []map[string]interface{}:
  497. // The context is a table of hashes. Pick the most recent table
  498. // defined as the current hash.
  499. hash = t[len(t)-1]
  500. case map[string]interface{}:
  501. hash = t
  502. default:
  503. p.panicf("Key '%s' has already been defined.", keyContext)
  504. }
  505. }
  506. keyContext = append(keyContext, key)
  507. if _, ok := hash[key]; ok {
  508. // Normally redefining keys isn't allowed, but the key could have been
  509. // defined implicitly and it's allowed to be redefined concretely. (See
  510. // the `valid/implicit-and-explicit-after.toml` in toml-test)
  511. //
  512. // But we have to make sure to stop marking it as an implicit. (So that
  513. // another redefinition provokes an error.)
  514. //
  515. // Note that since it has already been defined (as a hash), we don't
  516. // want to overwrite it. So our business is done.
  517. if p.isArray(keyContext) {
  518. p.removeImplicit(keyContext)
  519. hash[key] = value
  520. return
  521. }
  522. if p.isImplicit(keyContext) {
  523. p.removeImplicit(keyContext)
  524. return
  525. }
  526. // Otherwise, we have a concrete key trying to override a previous
  527. // key, which is *always* wrong.
  528. p.panicf("Key '%s' has already been defined.", keyContext)
  529. }
  530. hash[key] = value
  531. }
  532. // setType sets the type of a particular value at a given key. It should be
  533. // called immediately AFTER setValue.
  534. //
  535. // Note that if `key` is empty, then the type given will be applied to the
  536. // current context (which is either a table or an array of tables).
  537. func (p *parser) setType(key string, typ tomlType) {
  538. keyContext := make(Key, 0, len(p.context)+1)
  539. keyContext = append(keyContext, p.context...)
  540. if len(key) > 0 { // allow type setting for hashes
  541. keyContext = append(keyContext, key)
  542. }
  543. // Special case to make empty keys ("" = 1) work.
  544. // Without it it will set "" rather than `""`.
  545. // TODO: why is this needed? And why is this only needed here?
  546. if len(keyContext) == 0 {
  547. keyContext = Key{""}
  548. }
  549. p.types[keyContext.String()] = typ
  550. }
  551. // Implicit keys need to be created when tables are implied in "a.b.c.d = 1" and
  552. // "[a.b.c]" (the "a", "b", and "c" hashes are never created explicitly).
  553. func (p *parser) addImplicit(key Key) { p.implicits[key.String()] = struct{}{} }
  554. func (p *parser) removeImplicit(key Key) { delete(p.implicits, key.String()) }
  555. func (p *parser) isImplicit(key Key) bool { _, ok := p.implicits[key.String()]; return ok }
  556. func (p *parser) isArray(key Key) bool { return p.types[key.String()] == tomlArray }
  557. func (p *parser) addImplicitContext(key Key) {
  558. p.addImplicit(key)
  559. p.addContext(key, false)
  560. }
  561. // current returns the full key name of the current context.
  562. func (p *parser) current() string {
  563. if len(p.currentKey) == 0 {
  564. return p.context.String()
  565. }
  566. if len(p.context) == 0 {
  567. return p.currentKey
  568. }
  569. return fmt.Sprintf("%s.%s", p.context, p.currentKey)
  570. }
  571. func stripFirstNewline(s string) string {
  572. if len(s) > 0 && s[0] == '\n' {
  573. return s[1:]
  574. }
  575. if len(s) > 1 && s[0] == '\r' && s[1] == '\n' {
  576. return s[2:]
  577. }
  578. return s
  579. }
  580. // Remove newlines inside triple-quoted strings if a line ends with "\".
  581. func stripEscapedNewlines(s string) string {
  582. split := strings.Split(s, "\n")
  583. if len(split) < 1 {
  584. return s
  585. }
  586. escNL := false // Keep track of the last non-blank line was escaped.
  587. for i, line := range split {
  588. line = strings.TrimRight(line, " \t\r")
  589. if len(line) == 0 || line[len(line)-1] != '\\' {
  590. split[i] = strings.TrimRight(split[i], "\r")
  591. if !escNL && i != len(split)-1 {
  592. split[i] += "\n"
  593. }
  594. continue
  595. }
  596. escBS := true
  597. for j := len(line) - 1; j >= 0 && line[j] == '\\'; j-- {
  598. escBS = !escBS
  599. }
  600. if escNL {
  601. line = strings.TrimLeft(line, " \t\r")
  602. }
  603. escNL = !escBS
  604. if escBS {
  605. split[i] += "\n"
  606. continue
  607. }
  608. split[i] = line[:len(line)-1] // Remove \
  609. if len(split)-1 > i {
  610. split[i+1] = strings.TrimLeft(split[i+1], " \t\r")
  611. }
  612. }
  613. return strings.Join(split, "")
  614. }
  615. func (p *parser) replaceEscapes(it item, str string) string {
  616. replaced := make([]rune, 0, len(str))
  617. s := []byte(str)
  618. r := 0
  619. for r < len(s) {
  620. if s[r] != '\\' {
  621. c, size := utf8.DecodeRune(s[r:])
  622. r += size
  623. replaced = append(replaced, c)
  624. continue
  625. }
  626. r += 1
  627. if r >= len(s) {
  628. p.bug("Escape sequence at end of string.")
  629. return ""
  630. }
  631. switch s[r] {
  632. default:
  633. p.bug("Expected valid escape code after \\, but got %q.", s[r])
  634. return ""
  635. case ' ', '\t':
  636. p.panicItemf(it, "invalid escape: '\\%c'", s[r])
  637. return ""
  638. case 'b':
  639. replaced = append(replaced, rune(0x0008))
  640. r += 1
  641. case 't':
  642. replaced = append(replaced, rune(0x0009))
  643. r += 1
  644. case 'n':
  645. replaced = append(replaced, rune(0x000A))
  646. r += 1
  647. case 'f':
  648. replaced = append(replaced, rune(0x000C))
  649. r += 1
  650. case 'r':
  651. replaced = append(replaced, rune(0x000D))
  652. r += 1
  653. case '"':
  654. replaced = append(replaced, rune(0x0022))
  655. r += 1
  656. case '\\':
  657. replaced = append(replaced, rune(0x005C))
  658. r += 1
  659. case 'u':
  660. // At this point, we know we have a Unicode escape of the form
  661. // `uXXXX` at [r, r+5). (Because the lexer guarantees this
  662. // for us.)
  663. escaped := p.asciiEscapeToUnicode(it, s[r+1:r+5])
  664. replaced = append(replaced, escaped)
  665. r += 5
  666. case 'U':
  667. // At this point, we know we have a Unicode escape of the form
  668. // `uXXXX` at [r, r+9). (Because the lexer guarantees this
  669. // for us.)
  670. escaped := p.asciiEscapeToUnicode(it, s[r+1:r+9])
  671. replaced = append(replaced, escaped)
  672. r += 9
  673. }
  674. }
  675. return string(replaced)
  676. }
  677. func (p *parser) asciiEscapeToUnicode(it item, bs []byte) rune {
  678. s := string(bs)
  679. hex, err := strconv.ParseUint(strings.ToLower(s), 16, 32)
  680. if err != nil {
  681. p.bug("Could not parse '%s' as a hexadecimal number, but the lexer claims it's OK: %s", s, err)
  682. }
  683. if !utf8.ValidRune(rune(hex)) {
  684. p.panicItemf(it, "Escaped character '\\u%s' is not valid UTF-8.", s)
  685. }
  686. return rune(hex)
  687. }