changeset 72:0654e37583b5

appears to read kdir.js correctly
author Henry S. Thompson <ht@markup.co.uk>
date Thu, 29 Jun 2017 17:58:06 +0100
parents 54bb53434887
children 4bd5de7ac247
files eDecoder.py
diffstat 1 files changed, 86 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/eDecoder.py	Wed Jun 28 19:08:30 2017 +0100
+++ b/eDecoder.py	Thu Jun 29 17:58:06 2017 +0100
@@ -1,10 +1,12 @@
 '''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
+from json.decoder import JSONDecoder, JSONObject, JSONArray,\
+                         _CONSTANTS, WHITESPACE, WHITESPACE_STR, FLAGS, errmsg
 
 import json, re
 
 JSONObject_orig=JSONObject
+JSONArray_orig=JSONArray
 
 class eDecoder(JSONDecoder):
   def __init__(self, encoding=None, object_hook=None, parse_float=None,
@@ -20,26 +22,84 @@
   print('constant: %s'%istr)
   return _CONSTANTS[istr]
 
-IDENT=re.compile(r'[a-zA-Z0-9_.-]+', FLAGS)
+IDENT=re.compile(r'[$]?[A-Z]+[$]?[0-9]+([:][$]?[A-Z]+[$]?[0-9]+)|[a-zA-Z0-9_.-]+', FLAGS)
+
+def eJSONArray(s_and_end, scan_once, _w=WHITESPACE.match, _ws=WHITESPACE_STR):
+  s, end = s_and_end
+  values = []
+  nextchar = s[end:end + 1]
+  if nextchar in _ws:
+    end = _w(s, end + 1).end()
+    nextchar = s[end:end + 1]
+  # Look-ahead for trivial empty array
+  if nextchar == ']':
+    return values, end + 1
+  _append = values.append
+  while True:
+    try:
+      value, end = scan_once(s, end)
+    except StopIteration:
+      # Two possible causes: string empty, or no ident here
+      # Either way, the match will fail and the (original) value error is correct
+      isId = IDENT.match(s,end)
+      if isId:
+        value=isId.group()
+        end=isId.end()
+      else:
+        raise ValueError(errmsg("Expecting object", s, end))
+    _append(value)
+    nextchar = s[end:end + 1]
+    if nextchar in _ws:
+      end = _w(s, end + 1).end()
+      nextchar = s[end:end + 1]
+    end += 1
+    if nextchar == ']':
+      break
+    elif nextchar != ',':
+      raise ValueError(errmsg("Expecting ',' delimiter", s, end))
+    try:
+      if s[end] in _ws:
+        end += 1
+        if s[end] in _ws:
+          end = _w(s, end + 1).end()
+    except IndexError:
+      pass
+
+  return values, end
 
 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)
+  pairs = []
+  pairs_append = pairs.append
+  # Use a slice to prevent IndexError from being raised, the following
+  # check will raise a more specific ValueError if the string is empty
+  nextchar = s[end:end + 1]
+  # Normally we expect nextchar == '"'
+  if nextchar != '"':
+    if nextchar in _ws:
+      end = _w(s, end).end()
+      nextchar = s[end:end + 1]
+    # Trivial empty object
+    if nextchar == '}':
+      if object_pairs_hook is not None:
+        result = object_pairs_hook(pairs)
+        return result, end + 1
+      pairs = {}
+      if object_hook is not None:
+        pairs = object_hook(pairs)
+      return pairs, end + 1
   while True:
-    #key, end = scanstring(s, end, encoding, strict)
-    isId = IDENT.match(s,end)
-    if isId:
-      key=isId.group()
-      end=isId.end()
+    if nextchar=='"':
+      key, end = scanstring(s, end, encoding, strict)
     else:
-      raise ValueError(errmsg(
-        "Expecting property name with or w/o in double quotes", s, end))
-
+      isId = IDENT.match(s,end)
+      if isId:
+        key=isId.group()
+        end=isId.end()
+      else:
+        raise ValueError(errmsg(
+          "Expecting property name with or w/o 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] != ':':
@@ -59,7 +119,14 @@
     try:
       value, end = scan_once(s, end)
     except StopIteration:
-      raise ValueError(errmsg("Expecting object", s, end))
+      # Two possible causes: string empty, or no ident here
+      # Either way, the match will fail and the (original) value error is correct
+      isId = IDENT.match(s,end)
+      if isId:
+        value=isId.group()
+        end=isId.end()
+      else:
+        raise ValueError(errmsg("Expecting object", s, end))
     pairs_append((key, value))
 
     try:
@@ -87,10 +154,8 @@
     except IndexError:
       nextchar = ''
 
-    end += 1
-    if nextchar != '"':
-      raise ValueError(errmsg(
-          "Expecting property name enclosed in double quotes", s, end - 1))
+    if nextchar=='"':
+      end += 1
   if object_pairs_hook is not None:
     result = object_pairs_hook(pairs)
     return result, end
@@ -102,3 +167,4 @@
 
 json.scanner.make_scanner=json.scanner.py_make_scanner
 json.decoder.JSONObject=eJSONObject
+json.decoder.JSONArray=eJSONArray