tunnckoCore / ideas

:notebook: My centralized place for ideas, thoughts and todos. Raw, PoC implementations and so on... :star:
http://j.mp/1stW47C
6 stars 0 forks source link

JSON AST (first draft) #33

Open tunnckoCore opened 8 years ago

tunnckoCore commented 8 years ago

JSON AST

Pretty naive - first draft, it may have changes - it depends on if it is okey for programmatically usage. It is based on original/default JavaScript's JSON.parse method and little patch to reviver idea (3 lines btw).

// simple json object
// {
//   "bool": true,
//   "num": 123
// }
//
// =>
{
  type: 'object',
  contents: [{
    type: 'property',
    key: {type: 'string', contents: 'bool'},
    value: {type: 'boolean', contents: true},
    contents: [
      {type: 'key', contents: 'bool'},
      {type: 'value', contents: true}
    ]
  }, {
    type: 'property',
    key: {type: 'string', contents: 'num'},
    value: {type: 'number', contents: 123},
    contents: [
      {type: 'key', contents: 'num'},
      {type: 'value', contents: 123}
    ]
  }]
}

// nested json object (package.json-ish)
{
  "name": "pkg-name",
  "files": [
    666,
    "index.js",
    true,
    [false, "nested1", 2222, null]
    null,
  ],
  "private": true,
  "dependencies": {
    "gulp": "^3.9.0",
    "base": false,
    "nested": {
      "obj": "here",
      "and": null,
      "arr": [675, null, true, ["44", null, 555, false], 11, "999"]
      "bar": 456,
    },
    "num": 777,
    "qux": null,
    "keywords": [false, "fxoo", 888, "bxar", null]
  },
  "foo": 123,
  "some": null
}

// results in
// =>
{
  type: 'object',
  contents: [{
    type: 'property',
    key: {type: 'string', contents: 'name'},
    value: {type: 'string', contents: 'pkg-name'},
    contents: [
      {type: 'key', contents: 'name'},
      {type: 'value', contents: 'pkg-name'}
    ]
  }, {
    type: 'property',
    key: {type: 'string', contents: 'files'},
    value: {
      type: 'array', contents: [{
        type: 'item',
        key: {type: 'number', contents: 0},
        value: {type: 'number', contents: 666}
        contents: [
          {type: 'key', contents: 0},
          {type: 'value', contents: 666}
        ]
      }, {
        type: 'item',
        key: {type: 'number', contents: 1},
        value: {type: 'string', contents: 'index.js'}
        contents: [
          {type: 'key', contents: 1},
          {type: 'value', contents: 'index.js'}
        ]
      }, {
        type: 'item',
        key: {type: 'number', contents: 2},
        value: {type: 'boolean', contents: true}
        contents: [
          {type: 'key', contents: 2},
          {type: 'value', contents: true}
        ]
      }, {
        type: 'item',
        key: {type: 'number', contents: 3},
        value: {type: 'array', contents: [{
          type: 'item',
          key: {type: 'number', contents: 0},
          value: {type: 'boolean', contents: false},
          contents: [
            {type: 'key', contents: 0},
            {type: 'value', contents: false}
          ]
        }, {
          type: 'item',
          key: {type: 'number', contents: 1},
          value: {type: 'string', contents: 'nested1'},
          contents: [
            {type: 'key', contents: 1},
            {type: 'value', contents: 'nested1'}
          ]
        }, {
          type: 'item',
          key: {type: 'number', contents: 2},
          value: {type: 'number', contents: 2222},
          contents: [
            {type: 'key', contents: 2},
            {type: 'value', contents: 2222}
          ]
        }, {
          type: 'item',
          key: {type: 'number', contents: 3},
          value: {type: 'null', contents: null},
          contents: [
            {type: 'key', contents: 3},
            {type: 'value', contents: null}
          ]
        }]}
        contents: [
          {type: 'key', contents: 3},
          {type: 'value', contents: [/* same as `value.contents` array */]}
        ]
      }, {
        type: 'item',
        key: {type: 'number', contents: 4},
        value: {type: 'null', contents: null}
        contents: [
          {type: 'key', contents: 4},
          {type: 'value', contents: null}
        ]
      }]
    },
    contents: [
      {type: 'key', contents: 'files'},
      {type: 'value', contents: [/* same as `value.contents` array */]}
    ]
  }, {
    type: 'property',
    key: {type: 'string', contents: 'private'},
    value: {type: 'boolean', contents: true},
    contents: [
      {type: 'key', contents: 'private'},
      {type: 'value', contents: true}
    ]
  }, {
    type: 'property',
    key: {type: 'string', contents: 'dependencies'},
    value: {
      type: 'object',
      contents: [{
        type: 'property',
        key: {type: 'string', contents: 'gulp'},
        value: {type: 'string', contents: '^3.9.0'},
        contents: [
          {type: 'key', contents: 'gulp'},
          {type: 'value', contents: '^3.9.0'}
        ]
      }, {
        type: 'property',
        key: {type: 'string', contents: 'base'},
        value: {type: 'boolean', contents: false},
        contents: [
          {type: 'key', contents: 'base'},
          {type: 'value', contents: false}
        ]
      }, {
        type: 'property',
        key: {type: 'string', contents: 'nested'},
        value: {
          type: 'object',
          contents: [{
            type: 'property',
            key: {type: 'string', contents: 'obj'},
            value: {type: 'string', contents: 'here'},
            contents: [
              {type: 'key', contents: 'obj'},
              {type: 'value', contents: 'here'}
            ]
          }, {
            type: 'property',
            key: {type: 'string', contents: 'and'},
            value: {type: 'null', contents: null},
            contents: [
              {type: 'key', contents: 'and'},
              {type: 'value', contents: null}
            ]
          }, {
            type: 'property',
            key: {type: 'string', contents: 'array'},
            value: {type: 'array', contents: [{
              type: 'item',
              key: {type: 'number', contents: 0},
              value: {type: 'number', contents: 675},
              contents: [
                {type: 'key', contents: 0},
                {type: 'value', contents: 675}
              ]
            }, {
              type: 'item',
              key: {type: 'number', contents: 1},
              value: {type: 'null', contents: null},
              contents: [
                {type: 'key', contents: 1},
                {type: 'value', contents: null}
              ]
            }, {
              type: 'item',
              key: {type: 'number', contents: 2},
              value: {type: 'boolean', contents: true},
              contents: [
                {type: 'key', contents: 2},
                {type: 'value', contents: true}
              ]
            }, {
              type: 'item',
              key: {type: 'number', contents: 3},
              value: {type: 'array', contents: /*["44", null, 555, false]*/ [{
                type: 'item',
                key: {type: 'number', contents: 0},
                value: {type: 'string', contents: '44'},
                contents: [
                  {type: 'key', contents: 0},
                  {type: 'value', contents: '44'}
                ]
              }, {
                type: 'item',
                key: {type: 'number', contents: 1},
                value: {type: 'null', contents: null},
                contents: [
                  {type: 'key', contents: 1},
                  {type: 'value', contents: null}
                ]
              }, {
                type: 'item',
                key: {type: 'number', contents: 2},
                value: {type: 'number', contents: 555},
                contents: [
                  {type: 'key', contents: 2},
                  {type: 'value', contents: 555}
                ]
              }, {
                type: 'item',
                key: {type: 'number', contents: 3},
                value: {type: 'boolean', contents: false},
                contents: [
                  {type: 'key', contents: 3},
                  {type: 'value', contents: false}
                ]
              }]},
              contents: [
                {type: 'key', contents: 3},
                {type: 'value', contents: [/* same as `value.contents` array */]}
              ]
            }, {
              type: 'item',
              key: {type: 'number', contents: 4},
              value: {type: 'number', contents: 11},
              contents: [
                {type: 'key', contents: 4},
                {type: 'value', contents: 11}
              ]
            } ]},
            contents: [
              {type: 'key', contents: 'array'},
              {type: 'value', contents: [/* same as `value.contents` array */]}
            ]
          }, {
            type: 'property',
            key: {type: 'string', contents: 'bar'},
            value: {type: 'number', contents: 456},
            contents: [
              {type: 'key', contents: 'bar'},
              {type: 'value', contents: 456}
            ]
          }]
        },
        contents: [
          {type: 'key', contents: 'nested'},
          {type: 'value', contents: [/* same as `value.contents` array */]}
        ]
      }, {
        type: 'property',
        key: {type: 'string', contents: 'num'},
        value: {type: 'number', contents: 777},
        contents: [
          {type: 'key', contents: 'num'},
          {type: 'value', contents: 777}
        ]
      }, {
        type: 'property',
        key: {type: 'string', contents: 'qux'},
        value: {type: 'null', contents: null},
        contents: [
          {type: 'key', contents: 'qux'},
          {type: 'value', contents: null}
        ]
      }, {
        type: 'property',
        key: {type: 'string', contents: 'keywords'},
        value: {type: 'array', contents: /*[false, "fxoo", 888, "bxar", null]*/[{
          type: 'item',
          key: {type: 'number', contents: 0},
          value: {type: 'boolean', contents: false},
          contents: [
            {type: 'key', contents: 0},
            {type: 'value', contents: false}
          ]
        }, {
          type: 'item',
          key: {type: 'number', contents: 1},
          value: {type: 'string', contents: 'fxoo'},
          contents: [
            {type: 'key', contents: 1},
            {type: 'value', contents: 'fxoo'}
          ]
        }, {
          type: 'item',
          key: {type: 'number', contents: 2},
          value: {type: 'number', contents: 888},
          contents: [
            {type: 'key', contents: 2},
            {type: 'value', contents: 888}
          ]
        }, {
          type: 'item',
          key: {type: 'number', contents: 3},
          value: {type: 'string', contents: 'bxar'},
          contents: [
            {type: 'key', contents: 3},
            {type: 'value', contents: 'bxar'}
          ]
        }, {
          type: 'item',
          key: {type: 'number', contents: 4},
          value: {type: 'null', contents: null},
          contents: [
            {type: 'key', contents: 4},
            {type: 'value', contents: null}
          ]
        }]},
        contents: [
          {type: 'key', contents: 'keywords'},
          {type: 'value', contents: [/* same as `value.contents` array */]}
        ]
      }]
    },
    contents: [
      {type: 'key', contents: 'dependencies'},
      {type: 'value', contents: [/* same as `value.contents` array */]}
    ]
  }, {
    type: 'property',
    key: {type: 'string', contents: 'foo'},
    value: {type: 'number', contents: 123},
    contents: [
      {type: 'key', contents: 'foo'},
      {type: 'value', contents: 123}
    ]
  }, {
    type: 'property',
    key: {type: 'string', contents: 'some'},
    value: {type: 'null', contents: null},
    contents: [
      {type: 'key', contents: 'some'},
      {type: 'value', contents: null}
    ]
  }]
}

// json array
// [
//   "foo",
//   123,
//   "bar",
//   null,
//   {
//     "aaa": "bbb",
//     "ccc": true,
//     "ddd": {
//       "xxx": "yyy",
//       "zzz": 1122
//     }
//   }
//   true
// ]
//
// =>
{
  type: 'array',
  contents: [ {
    type: 'item',
    key: {type: 'number', contents: 0},
    value: {type: 'string', contents: "foo"},
    contents: [
      {type: 'key', contents: 0},
      {type: 'value', contents: "foo"}
    ]
  }, {
    type: 'item',
    key: {type: 'number', contents: 1/* `position` is same as the `.value.position` */},
    value: {type: 'number', contents: 123},
    contents: [
      {type: 'key', contents: 1/* `position` is same as the `.value.position` */},
      {type: 'value', contents: 123}
    ]
  }, {
    type: 'item',
    key: {type: 'number', contents: 2},
    value: {type: 'string', contents: "bar"},
    contents: [
      {type: 'key', contents: 2},
      {type: 'value', contents: "bar"}
    ]
  }, {
    type: 'item',
    key: {type: 'number', contents: 3},
    value: {type: 'null', contents: null},
    contents: [
      {type: 'key', contents: 3},
      {type: 'value', contents: null}
    ]
  }, {
    type: 'item',
    key: {type: 'number', contents: 4},
    value: {
      type: 'object',
      contents: [{
        type: 'property',
        key: {type: 'string', contents: 'aaa'},
        value: {type: 'string', contents: 'bbb'},
        contents: [
          {type: 'key', contents: 'aaa'},
          {type: 'value', contents: 'bbb'}
        ]
      }, {
        type: 'property',
        key: {type: 'string', contents: 'ccc'},
        value: {type: 'boolean', contents: true},
        contents: [
          {type: 'key', contents: 'ccc'},
          {type: 'value', contents: true}
        ]
      }, {
        type: 'property',
        key: {type: 'string', contents: 'ddd'},
        value: {
          type: 'object',
          contents: [{
            type: 'property',
            key: {type: 'string', contents: 'xxx'},
            value: {type: 'string', contents: 'yyy'},
            contents: [
              {type: 'key', contents: 'xxx'},
              {type: 'value', contents: 'yyy'}
            ]
          }, {
            type: 'property',
            key: {type: 'string', contents: 'zzz'},
            value: {type: 'number', contents: 1122},
            contents: [
              {type: 'key', contents: 'zzz'},
              {type: 'value', contents: 1122}
            ]
          }]
        },
        contents: [
          {type: 'key', contents: 'ddd'},
          {type: 'value', contents: [/* same as `value.contents` array */]}
        ]
      }]
    },
    contents: [
      {type: 'key', contents: 4},
      {type: 'value', contents: [/* same as `value.contents` array */]}
    ]
  }, {
    type: 'item',
    key: {type: 'number', contents: 5},
    value: {type: 'boolean', contents: true},
    contents: [
      {type: 'key', contents: 5},
      {type: 'value', contents: true}
    ]
  }]
}
tunnckoCore commented 8 years ago

@TODO: FIX IT (separate the other types)

property node

item node

array node

object node

All other types (except that in item.contents and property.contents) are valid JavaScript types, based on kind-of lib (pretty fast)

So, 4 "major" types, 2 "minor" and all others are JavaScript types ("patch").

tunnckoCore commented 8 years ago

4 major types

2 minor types

4 patch types (javascript's native types - almost)