-# Copyright (c) 2010, 2011 Nicira Networks
+# Copyright (c) 2010, 2011, 2012 Nicira, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
import StringIO
import sys
+__pychecker__ = 'no-stringiter'
+
escapes = {ord('"'): u"\\\"",
ord("\\"): u"\\\\",
ord("\b"): u"\\b",
def to_stream(obj, stream, pretty=False, sort_keys=True):
_Serializer(stream, pretty, sort_keys).serialize(obj)
+
def to_file(obj, name, pretty=False, sort_keys=True):
stream = open(name, "w")
try:
finally:
stream.close()
+
def to_string(obj, pretty=False, sort_keys=True):
output = StringIO.StringIO()
to_stream(obj, output, pretty, sort_keys)
output.close()
return s
+
def from_stream(stream):
p = Parser(check_trailer=True)
while True:
break
return p.finish()
+
def from_file(name):
stream = open(name, "r")
try:
finally:
stream.close()
+
def from_string(s):
try:
s = unicode(s, 'utf-8')
p.feed(s)
return p.finish()
+
class Parser(object):
## Maximum height of parsing stack. ##
MAX_HEIGHT = 1000
self.line_number = 0
self.column_number = 0
self.byte_number = 0
-
+
# Parsing.
self.parse_state = Parser.__parse_start
self.stack = []
def __lex_start_space(self, c):
pass
+
def __lex_start_alpha(self, c):
self.buffer = c
self.lex_state = Parser.__lex_keyword
+
def __lex_start_token(self, c):
self.__parser_input(c)
+
def __lex_start_number(self, c):
self.buffer = c
self.lex_state = Parser.__lex_number
+
def __lex_start_string(self, _):
self.lex_state = Parser.__lex_string
+
def __lex_start_error(self, c):
if ord(c) >= 32 and ord(c) < 128:
self.__error("invalid character '%s'" % c)
for c in "-0123456789":
__lex_start_actions[c] = __lex_start_number
__lex_start_actions['"'] = __lex_start_string
+
def __lex_start(self, c):
Parser.__lex_start_actions.get(
c, Parser.__lex_start_error)(self, c)
__lex_alpha = {}
for c in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ":
__lex_alpha[c] = True
+
def __lex_finish_keyword(self):
if self.buffer == "false":
self.__parser_input(False)
self.__parser_input(None)
else:
self.__error("invalid keyword '%s'" % self.buffer)
+
def __lex_keyword(self, c):
if c in Parser.__lex_alpha:
self.buffer += c
self.__lex_finish_keyword()
return False
- __number_re = re.compile("(-)?(0|[1-9][0-9]*)(?:\.([0-9]+))?(?:[eE]([-+]?[0-9]+))?$")
+ __number_re = re.compile("(-)?(0|[1-9][0-9]*)"
+ "(?:\.([0-9]+))?(?:[eE]([-+]?[0-9]+))?$")
+
def __lex_finish_number(self):
s = self.buffer
m = Parser.__number_re.match(s)
if m:
- sign, integer, fraction, exp = m.groups()
+ sign, integer, fraction, exp = m.groups()
if (exp is not None and
(long(exp) > sys.maxint or long(exp) < -sys.maxint - 1)):
self.__error("exponent outside valid range")
if significand == 0:
self.__parser_input(0)
return
- elif significand <= 2**63:
- while pow10 > 0 and significand <= 2*63:
+ elif significand <= 2 ** 63:
+ while pow10 > 0 and significand <= 2 ** 63:
significand *= 10
pow10 -= 1
while pow10 < 0 and significand % 10 == 0:
significand /= 10
pow10 += 1
if (pow10 == 0 and
- ((not sign and significand < 2**63) or
- (sign and significand <= 2**63))):
+ ((not sign and significand < 2 ** 63) or
+ (sign and significand <= 2 ** 63))):
if sign:
self.__parser_input(-significand)
else:
self.__error("exponent must contain at least one digit")
else:
self.__error("syntax error in number")
-
+
def __lex_number(self, c):
if c in ".0123456789eE-+":
self.buffer += c
return False
__4hex_re = re.compile("[0-9a-fA-F]{4}")
+
def __lex_4hex(self, s):
if len(s) < 4:
self.__error("quoted string ends within \\u escape")
self.__error("null bytes not supported in quoted strings")
else:
return int(s, 16)
+
@staticmethod
def __is_leading_surrogate(c):
"""Returns true if 'c' is a Unicode code point for a leading
surrogate."""
return c >= 0xd800 and c <= 0xdbff
+
@staticmethod
def __is_trailing_surrogate(c):
"""Returns true if 'c' is a Unicode code point for a trailing
surrogate."""
return c >= 0xdc00 and c <= 0xdfff
+
@staticmethod
def __utf16_decode_surrogate_pair(leading, trailing):
"""Returns the unicode code point corresponding to leading surrogate
"n": u"\n",
"r": u"\r",
"t": u"\t"}
+
def __lex_finish_string(self):
inp = self.buffer
out = u""
elif inp[0] != u'u':
self.__error("bad escape \\%s" % inp[0])
return
-
+
c0 = self.__lex_4hex(inp[1:5])
if c0 is None:
return
self.buffer += c
self.lex_state = Parser.__lex_string
return True
+
def __lex_string(self, c):
if c == '\\':
self.buffer += c
return True
def __lex_input(self, c):
- self.byte_number += 1
- if c == '\n':
- self.column_number = 0
- self.line_number += 1
- else:
- self.column_number += 1
-
eat = self.lex_state(self, c)
assert eat is True or eat is False
return eat
self.__push_array()
else:
self.__error("syntax error at beginning of input")
+
def __parse_end(self, unused_token, unused_string):
self.__error("trailing garbage at end of input")
+
def __parse_object_init(self, token, string):
if token == '}':
self.__parser_pop()
else:
self.__parse_object_name(token, string)
+
def __parse_object_name(self, token, string):
if token == 'string':
self.member_name = string
self.parse_state = Parser.__parse_object_colon
else:
self.__error("syntax error parsing object expecting string")
+
def __parse_object_colon(self, token, unused_string):
if token == ":":
self.parse_state = Parser.__parse_object_value
else:
self.__error("syntax error parsing object expecting ':'")
+
def __parse_object_value(self, token, string):
self.__parse_value(token, string, Parser.__parse_object_next)
+
def __parse_object_next(self, token, unused_string):
if token == ",":
self.parse_state = Parser.__parse_object_name
self.__parser_pop()
else:
self.__error("syntax error expecting '}' or ','")
+
def __parse_array_init(self, token, string):
if token == ']':
self.__parser_pop()
else:
self.__parse_array_value(token, string)
+
def __parse_array_value(self, token, string):
self.__parse_value(token, string, Parser.__parse_array_next)
+
def __parse_array_next(self, token, unused_string):
if token == ",":
self.parse_state = Parser.__parse_array_value
self.__parser_pop()
else:
self.__error("syntax error expecting ']' or ','")
+
def __parser_input(self, token, string=None):
self.lex_state = Parser.__lex_start
self.buffer = ""
else:
self.__error("input exceeds maximum nesting depth %d" %
Parser.MAX_HEIGHT)
+
def __push_object(self):
self.__parser_push({}, Parser.__parse_object_init)
+
def __push_array(self):
self.__parser_push([], Parser.__parse_array_init)
while True:
if self.done or i >= len(s):
return i
- if self.__lex_input(s[i]):
+
+ c = s[i]
+ if self.__lex_input(c):
+ self.byte_number += 1
+ if c == '\n':
+ self.column_number = 0
+ self.line_number += 1
+ else:
+ self.column_number += 1
+
i += 1
def is_done(self):