index.js 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. 'use strict'
  2. exports.parse = function (source, transform) {
  3. return new ArrayParser(source, transform).parse()
  4. }
  5. class ArrayParser {
  6. constructor (source, transform) {
  7. this.source = source
  8. this.transform = transform || identity
  9. this.position = 0
  10. this.entries = []
  11. this.recorded = []
  12. this.dimension = 0
  13. }
  14. isEof () {
  15. return this.position >= this.source.length
  16. }
  17. nextCharacter () {
  18. var character = this.source[this.position++]
  19. if (character === '\\') {
  20. return {
  21. value: this.source[this.position++],
  22. escaped: true
  23. }
  24. }
  25. return {
  26. value: character,
  27. escaped: false
  28. }
  29. }
  30. record (character) {
  31. this.recorded.push(character)
  32. }
  33. newEntry (includeEmpty) {
  34. var entry
  35. if (this.recorded.length > 0 || includeEmpty) {
  36. entry = this.recorded.join('')
  37. if (entry === 'NULL' && !includeEmpty) {
  38. entry = null
  39. }
  40. if (entry !== null) entry = this.transform(entry)
  41. this.entries.push(entry)
  42. this.recorded = []
  43. }
  44. }
  45. consumeDimensions () {
  46. if (this.source[0] === '[') {
  47. while (!this.isEof()) {
  48. var char = this.nextCharacter()
  49. if (char.value === '=') break
  50. }
  51. }
  52. }
  53. parse (nested) {
  54. var character, parser, quote
  55. this.consumeDimensions()
  56. while (!this.isEof()) {
  57. character = this.nextCharacter()
  58. if (character.value === '{' && !quote) {
  59. this.dimension++
  60. if (this.dimension > 1) {
  61. parser = new ArrayParser(this.source.substr(this.position - 1), this.transform)
  62. this.entries.push(parser.parse(true))
  63. this.position += parser.position - 2
  64. }
  65. } else if (character.value === '}' && !quote) {
  66. this.dimension--
  67. if (!this.dimension) {
  68. this.newEntry()
  69. if (nested) return this.entries
  70. }
  71. } else if (character.value === '"' && !character.escaped) {
  72. if (quote) this.newEntry(true)
  73. quote = !quote
  74. } else if (character.value === ',' && !quote) {
  75. this.newEntry()
  76. } else {
  77. this.record(character.value)
  78. }
  79. }
  80. if (this.dimension !== 0) {
  81. throw new Error('array dimension not balanced')
  82. }
  83. return this.entries
  84. }
  85. }
  86. function identity (value) {
  87. return value
  88. }