1# Copyright (c) 2013 ARM Limited
2# All rights reserved
3#
4# The license below extends only to copyright in the software and shall
5# not be construed as granting a license to any other intellectual
6# property including but not limited to intellectual property relating
7# to a hardware implementation of the functionality of the software
8# licensed hereunder.  You may use the software subject to the license
9# terms below provided that you ensure that this notice is replicated
10# unmodified and in its entirety in all distributions of the software,
11# modified or unmodified, in source code or in binary form.
12#
13# Redistribution and use in source and binary forms, with or without
14# modification, are permitted provided that the following conditions are
15# met: redistributions of source code must retain the above copyright
16# notice, this list of conditions and the following disclaimer;
17# redistributions in binary form must reproduce the above copyright
18# notice, this list of conditions and the following disclaimer in the
19# documentation and/or other materials provided with the distribution;
20# neither the name of the copyright holders nor the names of its
21# contributors may be used to endorse or promote products derived from
22# this software without specific prior written permission.
23#
24# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35#
36# Authors: Andrew Bardsley
37
38import re
39
40def list_parser(names):
41    """Parse a list of elements, some of which might be one-level sublists
42    within parentheses, into a a list of lists of those elements.  For
43    example: list_parser('(a,b),c') -> [['a', 'b'], 'c']"""
44    elems = re.split(',', names)
45    ret = []
46    accum = []
47    for elem in elems:
48        if re.search('^\((.*)\)$', elem):
49            accum.append(re.sub('^\((.*)\)', '\\1', elem))
50            ret.append(accum)
51            accum = []
52        elif re.search('^\(', elem):
53            accum.append(re.sub('^\(', '', elem))
54        elif re.search('\)$', elem):
55            accum.append(re.sub('\)$', '', elem))
56            ret.append(accum)
57            accum = []
58        elif len(accum) != 0:
59            accum.append(elem)
60        else:
61            ret.append([elem])
62
63    if len(accum) > 0:
64        print 'Non matching brackets in', names
65
66    return ret
67
68def map2(f, ls):
69    """map to a depth of 2.  That is, given a list of lists, apply
70    f to those innermost elements """
71    return map(lambda l: map(f, l), ls)
72
73def remove_trailing_ws(line):
74    return re.sub('\s*$', '', line)
75
76def remove_leading_and_trailing_ws(line):
77    return re.sub('\s*$', '', re.sub('^\s*', '', line))
78
79def parse_pairs_list(pairString):
80    """parse a string like 'name=value name2=value2' into a
81    list of pairs of ('name', 'value') ..."""
82    ret = []
83    pairs = re.finditer('(\w+)(=("[^"]*"|[^\s]*))?', pairString)
84    for pair in pairs:
85        name, rest, value = pair.groups()
86        if value is not None:
87            value = re.sub('^"(.*)"$', '\\1', value)
88            ret.append((name, value))
89        else:
90            ret.append((name, ''))
91    return ret
92
93def parse_indexed_list(string):
94    """parse a string of the form "(index,value),(index,value)..."
95    into a list of index, value pairs"""
96
97    ret = []
98    pairs = list_parser(string)
99    for pair in pairs:
100        if len(pair) == 2:
101            index, value = pair
102            ret.append((int(index), value))
103
104    return ret
105
106def parse_pairs(pairString):
107    """parse a string like 'name=value name2=value2' into a
108    dictionary of {'name': 'value', 'name2': 'value2'} """
109    return dict(parse_pairs_list(pairString))
110