| # Copyright 2018 The Chromium Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| from __future__ import print_function |
| import collections |
| import json |
| import os.path |
| import re |
| import sys |
| |
| description = '' |
| |
| |
| primitiveTypes = ['integer', 'number', 'boolean', 'string', 'object', |
| 'any', 'array', 'binary'] |
| |
| |
| def assignType(item, type, is_array=False, map_binary_to_string=False): |
| if is_array: |
| item['type'] = 'array' |
| item['items'] = collections.OrderedDict() |
| assignType(item['items'], type, False, map_binary_to_string) |
| return |
| |
| if type == 'enum': |
| type = 'string' |
| if map_binary_to_string and type == 'binary': |
| type = 'string' |
| if type in primitiveTypes: |
| item['type'] = type |
| else: |
| item['$ref'] = type |
| |
| |
| def createItem(d, experimental, deprecated, name=None): |
| result = collections.OrderedDict(d) |
| if name: |
| result['name'] = name |
| global description |
| if description: |
| result['description'] = description.strip() |
| if experimental: |
| result['experimental'] = True |
| if deprecated: |
| result['deprecated'] = True |
| return result |
| |
| |
| def parse(data, file_name, map_binary_to_string=False): |
| protocol = collections.OrderedDict() |
| protocol['version'] = collections.OrderedDict() |
| protocol['domains'] = [] |
| domain = None |
| item = None |
| subitems = None |
| nukeDescription = False |
| global description |
| lines = data.split('\n') |
| for i in range(0, len(lines)): |
| if nukeDescription: |
| description = '' |
| nukeDescription = False |
| line = lines[i] |
| trimLine = line.strip() |
| |
| if trimLine.startswith('#'): |
| if len(description): |
| description += '\n' |
| description += trimLine[2:] |
| continue |
| else: |
| nukeDescription = True |
| |
| if len(trimLine) == 0: |
| continue |
| |
| match = re.compile( |
| r'^(experimental )?(deprecated )?domain (.*)').match(line) |
| if match: |
| domain = createItem({'domain' : match.group(3)}, match.group(1), |
| match.group(2)) |
| protocol['domains'].append(domain) |
| continue |
| |
| match = re.compile(r'^ depends on ([^\s]+)').match(line) |
| if match: |
| if 'dependencies' not in domain: |
| domain['dependencies'] = [] |
| domain['dependencies'].append(match.group(1)) |
| continue |
| |
| match = re.compile(r'^ (experimental )?(deprecated )?type (.*) ' |
| r'extends (array of )?([^\s]+)').match(line) |
| if match: |
| if 'types' not in domain: |
| domain['types'] = [] |
| item = createItem({'id': match.group(3)}, match.group(1), match.group(2)) |
| assignType(item, match.group(5), match.group(4), map_binary_to_string) |
| domain['types'].append(item) |
| continue |
| |
| match = re.compile( |
| r'^ (experimental )?(deprecated )?(command|event) (.*)').match(line) |
| if match: |
| list = [] |
| if match.group(3) == 'command': |
| if 'commands' in domain: |
| list = domain['commands'] |
| else: |
| list = domain['commands'] = [] |
| else: |
| if 'events' in domain: |
| list = domain['events'] |
| else: |
| list = domain['events'] = [] |
| |
| item = createItem({}, match.group(1), match.group(2), match.group(4)) |
| list.append(item) |
| continue |
| |
| match = re.compile( |
| r'^ (experimental )?(deprecated )?(optional )?' |
| r'(array of )?([^\s]+) ([^\s]+)').match(line) |
| if match: |
| param = createItem({}, match.group(1), match.group(2), match.group(6)) |
| if match.group(3): |
| param['optional'] = True |
| assignType(param, match.group(5), match.group(4), map_binary_to_string) |
| if match.group(5) == 'enum': |
| enumliterals = param['enum'] = [] |
| subitems.append(param) |
| continue |
| |
| match = re.compile(r'^ (parameters|returns|properties)').match(line) |
| if match: |
| subitems = item[match.group(1)] = [] |
| continue |
| |
| match = re.compile(r'^ enum').match(line) |
| if match: |
| enumliterals = item['enum'] = [] |
| continue |
| |
| match = re.compile(r'^version').match(line) |
| if match: |
| continue |
| |
| match = re.compile(r'^ major (\d+)').match(line) |
| if match: |
| protocol['version']['major'] = match.group(1) |
| continue |
| |
| match = re.compile(r'^ minor (\d+)').match(line) |
| if match: |
| protocol['version']['minor'] = match.group(1) |
| continue |
| |
| match = re.compile(r'^ redirect ([^\s]+)').match(line) |
| if match: |
| item['redirect'] = match.group(1) |
| continue |
| |
| match = re.compile(r'^ ( )?[^\s]+$').match(line) |
| if match: |
| # enum literal |
| enumliterals.append(trimLine) |
| continue |
| |
| print('Error in %s:%s, illegal token: \t%s' % (file_name, i, line)) |
| sys.exit(1) |
| return protocol |
| |
| |
| def loads(data, file_name, map_binary_to_string=False): |
| if file_name.endswith(".pdl"): |
| return parse(data, file_name, map_binary_to_string) |
| return json.loads(data) |