• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2# Copyright (c) 2012 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6'''Utility to remove comments from JSON files so that they can be parsed by
7json.loads.
8'''
9
10import sys
11
12
13def _Rcount(string, chars):
14  '''Returns the number of consecutive characters from |chars| that occur at the
15  end of |string|.
16  '''
17  return len(string) - len(string.rstrip(chars))
18
19
20def _FindNextToken(string, tokens, start):
21  '''Finds the next token in |tokens| that occurs in |string| from |start|.
22  Returns a tuple (index, token key).
23  '''
24  min_index, min_key = (-1, None)
25  for k in tokens:
26    index = string.find(k, start)
27    if index != -1 and (min_index == -1 or index < min_index):
28      min_index, min_key = (index, k)
29  return (min_index, min_key)
30
31
32def _ReadString(input, start, output):
33  output.append('"')
34  start_range, end_range = (start, input.find('"', start))
35  # \" escapes the ", \\" doesn't, \\\" does, etc.
36  while (end_range != -1 and
37         _Rcount(input[start_range:end_range], '\\') % 2 == 1):
38    start_range, end_range = (end_range, input.find('"', end_range + 1))
39  if end_range == -1:
40    return start_range + 1
41  output.append(input[start:end_range + 1])
42  return end_range + 1
43
44
45def _ReadComment(input, start, output):
46  eol_tokens = ('\n', '\r')
47  eol_token_index, eol_token = _FindNextToken(input, eol_tokens, start)
48  if eol_token is None:
49    return len(input)
50  output.append(eol_token)
51  return eol_token_index + len(eol_token)
52
53
54def Nom(input):
55  token_actions = {
56    '"': _ReadString,
57    '//': _ReadComment,
58  }
59  output = []
60  pos = 0
61  while pos < len(input):
62    token_index, token = _FindNextToken(input, token_actions.keys(), pos)
63    if token is None:
64      output.append(input[pos:])
65      break
66    output.append(input[pos:token_index])
67    pos = token_actions[token](input, token_index + len(token), output)
68  return ''.join(output)
69
70
71if __name__ == '__main__':
72    sys.stdout.write(Nom(sys.stdin.read()))
73