view eDecoder.py @ 71:54bb53434887

begin work on decoder that allows identifiers as keys and values
author Henry S. Thompson <ht@markup.co.uk>
date Wed, 28 Jun 2017 19:08:30 +0100
parents
children 0654e37583b5
line wrap: on
line source

'''Extend JSON to support atoms as properties and class names'''
from json import decoder
from json.decoder import JSONDecoder, JSONObject, _CONSTANTS, WHITESPACE, WHITESPACE_STR, FLAGS, errmsg

import json, re

JSONObject_orig=JSONObject

class eDecoder(JSONDecoder):
  def __init__(self, encoding=None, object_hook=None, parse_float=None,
            parse_int=None, parse_constant=None, strict=True,
            object_pairs_hook=None):

    self.parse_object = eJSONObject
    super(eDecoder,self).__init__(encoding, object_hook, parse_float,
                                  parse_int, e_parse_constant, strict,
                                  object_pairs_hook)

def e_parse_constant(istr):
  print('constant: %s'%istr)
  return _CONSTANTS[istr]

IDENT=re.compile(r'[a-zA-Z0-9_.-]+', FLAGS)

def eJSONObject(s_and_end, encoding, strict, scan_once, object_hook,
               object_pairs_hook, _w=WHITESPACE.match, _ws=WHITESPACE_STR):
  s, end = s_and_end
  if (s[end] in ('"','}') or
      (s[end] in _ws and
       s[_w(s,end).end()] in ('"','}'))):
    return JSONObject_orig(s_and_end, encoding, strict, scan_once, object_hook,
                           object_pairs_hook, _w, _ws)
  while True:
    #key, end = scanstring(s, end, encoding, strict)
    isId = IDENT.match(s,end)
    if isId:
      key=isId.group()
      end=isId.end()
    else:
      raise ValueError(errmsg(
        "Expecting property name with or w/o in double quotes", s, end))

    # To skip some function call overhead we optimize the fast paths where
    # the JSON key separator is ": " or just ":".
    if s[end:end + 1] != ':':
      end = _w(s, end).end()
      if s[end:end + 1] != ':':
        raise ValueError(errmsg("Expecting ':' delimiter", s, end))
    end += 1

    try:
      if s[end] in _ws:
        end += 1
        if s[end] in _ws:
          end = _w(s, end + 1).end()
    except IndexError:
      pass

    try:
      value, end = scan_once(s, end)
    except StopIteration:
      raise ValueError(errmsg("Expecting object", s, end))
    pairs_append((key, value))

    try:
      nextchar = s[end]
      if nextchar in _ws:
        end = _w(s, end + 1).end()
        nextchar = s[end]
    except IndexError:
      nextchar = ''
    end += 1

    if nextchar == '}':
      break
    elif nextchar != ',':
      raise ValueError(errmsg("Expecting ',' delimiter", s, end - 1))

    try:
      nextchar = s[end]
      if nextchar in _ws:
        end += 1
        nextchar = s[end]
        if nextchar in _ws:
          end = _w(s, end + 1).end()
          nextchar = s[end]
    except IndexError:
      nextchar = ''

    end += 1
    if nextchar != '"':
      raise ValueError(errmsg(
          "Expecting property name enclosed in double quotes", s, end - 1))
  if object_pairs_hook is not None:
    result = object_pairs_hook(pairs)
    return result, end
  pairs = dict(pairs)
  if object_hook is not None:
    pairs = object_hook(pairs)
  return pairs, end
  

json.scanner.make_scanner=json.scanner.py_make_scanner
json.decoder.JSONObject=eJSONObject