11cb0ef41Sopenharmony_ci# Copyright 2018 The Chromium Authors. All rights reserved.
21cb0ef41Sopenharmony_ci# Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci# found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_cifrom __future__ import print_function
61cb0ef41Sopenharmony_ciimport collections
71cb0ef41Sopenharmony_ciimport json
81cb0ef41Sopenharmony_ciimport os.path
91cb0ef41Sopenharmony_ciimport re
101cb0ef41Sopenharmony_ciimport sys
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_cidescription = ''
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ciprimitiveTypes = ['integer', 'number', 'boolean', 'string', 'object', 'any', 'array', 'binary']
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_cidef assignType(item, type, is_array=False, map_binary_to_string=False):
191cb0ef41Sopenharmony_ci    if is_array:
201cb0ef41Sopenharmony_ci        item['type'] = 'array'
211cb0ef41Sopenharmony_ci        item['items'] = collections.OrderedDict()
221cb0ef41Sopenharmony_ci        assignType(item['items'], type, False, map_binary_to_string)
231cb0ef41Sopenharmony_ci        return
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci    if type == 'enum':
261cb0ef41Sopenharmony_ci        type = 'string'
271cb0ef41Sopenharmony_ci    if map_binary_to_string and type == 'binary':
281cb0ef41Sopenharmony_ci        type = 'string'
291cb0ef41Sopenharmony_ci    if type in primitiveTypes:
301cb0ef41Sopenharmony_ci        item['type'] = type
311cb0ef41Sopenharmony_ci    else:
321cb0ef41Sopenharmony_ci        item['$ref'] = type
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_cidef createItem(d, experimental, deprecated, name=None):
361cb0ef41Sopenharmony_ci    result = collections.OrderedDict(d)
371cb0ef41Sopenharmony_ci    if name:
381cb0ef41Sopenharmony_ci        result['name'] = name
391cb0ef41Sopenharmony_ci    global description
401cb0ef41Sopenharmony_ci    if description:
411cb0ef41Sopenharmony_ci        result['description'] = description.strip()
421cb0ef41Sopenharmony_ci    if experimental:
431cb0ef41Sopenharmony_ci        result['experimental'] = True
441cb0ef41Sopenharmony_ci    if deprecated:
451cb0ef41Sopenharmony_ci        result['deprecated'] = True
461cb0ef41Sopenharmony_ci    return result
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_cidef parse(data, file_name, map_binary_to_string=False):
501cb0ef41Sopenharmony_ci    protocol = collections.OrderedDict()
511cb0ef41Sopenharmony_ci    protocol['version'] = collections.OrderedDict()
521cb0ef41Sopenharmony_ci    protocol['domains'] = []
531cb0ef41Sopenharmony_ci    domain = None
541cb0ef41Sopenharmony_ci    item = None
551cb0ef41Sopenharmony_ci    subitems = None
561cb0ef41Sopenharmony_ci    nukeDescription = False
571cb0ef41Sopenharmony_ci    global description
581cb0ef41Sopenharmony_ci    lines = data.split('\n')
591cb0ef41Sopenharmony_ci    for i in range(0, len(lines)):
601cb0ef41Sopenharmony_ci        if nukeDescription:
611cb0ef41Sopenharmony_ci            description = ''
621cb0ef41Sopenharmony_ci            nukeDescription = False
631cb0ef41Sopenharmony_ci        line = lines[i]
641cb0ef41Sopenharmony_ci        trimLine = line.strip()
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci        if trimLine.startswith('#'):
671cb0ef41Sopenharmony_ci            if len(description):
681cb0ef41Sopenharmony_ci              description += '\n'
691cb0ef41Sopenharmony_ci            description += trimLine[2:]
701cb0ef41Sopenharmony_ci            continue
711cb0ef41Sopenharmony_ci        else:
721cb0ef41Sopenharmony_ci            nukeDescription = True
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci        if len(trimLine) == 0:
751cb0ef41Sopenharmony_ci            continue
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci        match = re.compile(r'^(experimental )?(deprecated )?domain (.*)').match(line)
781cb0ef41Sopenharmony_ci        if match:
791cb0ef41Sopenharmony_ci            domain = createItem({'domain' : match.group(3)}, match.group(1), match.group(2))
801cb0ef41Sopenharmony_ci            protocol['domains'].append(domain)
811cb0ef41Sopenharmony_ci            continue
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci        match = re.compile(r'^  depends on ([^\s]+)').match(line)
841cb0ef41Sopenharmony_ci        if match:
851cb0ef41Sopenharmony_ci            if 'dependencies' not in domain:
861cb0ef41Sopenharmony_ci                domain['dependencies'] = []
871cb0ef41Sopenharmony_ci            domain['dependencies'].append(match.group(1))
881cb0ef41Sopenharmony_ci            continue
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci        match = re.compile(r'^  (experimental )?(deprecated )?type (.*) extends (array of )?([^\s]+)').match(line)
911cb0ef41Sopenharmony_ci        if match:
921cb0ef41Sopenharmony_ci            if 'types' not in domain:
931cb0ef41Sopenharmony_ci                domain['types'] = []
941cb0ef41Sopenharmony_ci            item = createItem({'id': match.group(3)}, match.group(1), match.group(2))
951cb0ef41Sopenharmony_ci            assignType(item, match.group(5), match.group(4), map_binary_to_string)
961cb0ef41Sopenharmony_ci            domain['types'].append(item)
971cb0ef41Sopenharmony_ci            continue
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci        match = re.compile(r'^  (experimental )?(deprecated )?(command|event) (.*)').match(line)
1001cb0ef41Sopenharmony_ci        if match:
1011cb0ef41Sopenharmony_ci            list = []
1021cb0ef41Sopenharmony_ci            if match.group(3) == 'command':
1031cb0ef41Sopenharmony_ci                if 'commands' in domain:
1041cb0ef41Sopenharmony_ci                    list = domain['commands']
1051cb0ef41Sopenharmony_ci                else:
1061cb0ef41Sopenharmony_ci                    list = domain['commands'] = []
1071cb0ef41Sopenharmony_ci            else:
1081cb0ef41Sopenharmony_ci                if 'events' in domain:
1091cb0ef41Sopenharmony_ci                    list = domain['events']
1101cb0ef41Sopenharmony_ci                else:
1111cb0ef41Sopenharmony_ci                    list = domain['events'] = []
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ci            item = createItem({}, match.group(1), match.group(2), match.group(4))
1141cb0ef41Sopenharmony_ci            list.append(item)
1151cb0ef41Sopenharmony_ci            continue
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci        match = re.compile(r'^      (experimental )?(deprecated )?(optional )?(array of )?([^\s]+) ([^\s]+)').match(line)
1181cb0ef41Sopenharmony_ci        if match:
1191cb0ef41Sopenharmony_ci            param = createItem({}, match.group(1), match.group(2), match.group(6))
1201cb0ef41Sopenharmony_ci            if match.group(3):
1211cb0ef41Sopenharmony_ci                param['optional'] = True
1221cb0ef41Sopenharmony_ci            assignType(param, match.group(5), match.group(4), map_binary_to_string)
1231cb0ef41Sopenharmony_ci            if match.group(5) == 'enum':
1241cb0ef41Sopenharmony_ci                enumliterals = param['enum'] = []
1251cb0ef41Sopenharmony_ci            subitems.append(param)
1261cb0ef41Sopenharmony_ci            continue
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_ci        match = re.compile(r'^    (parameters|returns|properties)').match(line)
1291cb0ef41Sopenharmony_ci        if match:
1301cb0ef41Sopenharmony_ci            subitems = item[match.group(1)] = []
1311cb0ef41Sopenharmony_ci            continue
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ci        match = re.compile(r'^    enum').match(line)
1341cb0ef41Sopenharmony_ci        if match:
1351cb0ef41Sopenharmony_ci            enumliterals = item['enum'] = []
1361cb0ef41Sopenharmony_ci            continue
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci        match = re.compile(r'^version').match(line)
1391cb0ef41Sopenharmony_ci        if match:
1401cb0ef41Sopenharmony_ci            continue
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_ci        match = re.compile(r'^  major (\d+)').match(line)
1431cb0ef41Sopenharmony_ci        if match:
1441cb0ef41Sopenharmony_ci            protocol['version']['major'] = match.group(1)
1451cb0ef41Sopenharmony_ci            continue
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_ci        match = re.compile(r'^  minor (\d+)').match(line)
1481cb0ef41Sopenharmony_ci        if match:
1491cb0ef41Sopenharmony_ci            protocol['version']['minor'] = match.group(1)
1501cb0ef41Sopenharmony_ci            continue
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_ci        match = re.compile(r'^    redirect ([^\s]+)').match(line)
1531cb0ef41Sopenharmony_ci        if match:
1541cb0ef41Sopenharmony_ci            item['redirect'] = match.group(1)
1551cb0ef41Sopenharmony_ci            continue
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ci        match = re.compile(r'^      (  )?[^\s]+$').match(line)
1581cb0ef41Sopenharmony_ci        if match:
1591cb0ef41Sopenharmony_ci            # enum literal
1601cb0ef41Sopenharmony_ci            enumliterals.append(trimLine)
1611cb0ef41Sopenharmony_ci            continue
1621cb0ef41Sopenharmony_ci
1631cb0ef41Sopenharmony_ci        print('Error in %s:%s, illegal token: \t%s' % (file_name, i, line))
1641cb0ef41Sopenharmony_ci        sys.exit(1)
1651cb0ef41Sopenharmony_ci    return protocol
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ci
1681cb0ef41Sopenharmony_cidef loads(data, file_name, map_binary_to_string=False):
1691cb0ef41Sopenharmony_ci    if file_name.endswith(".pdl"):
1701cb0ef41Sopenharmony_ci        return parse(data, file_name, map_binary_to_string)
1711cb0ef41Sopenharmony_ci    return json.loads(data)
172