summaryrefslogtreecommitdiff
path: root/tools/packaging/monkeyYaml.py
blob: 26ac194b4e8401af37a4e5cd17a21a46dd2f20bd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#!/usr/bin/env python
# Copyright 2014 by Sam Mikes.  All rights reserved.
# This code is governed by the BSD license found in the LICENSE file.

# This code provides a fallback parser that can handle the subset of
# YAML used in test262 frontmatter

import re

mYamlKV = re.compile(r"(.*?):(.*)")
mYamlIntDigits = re.compile(r"^[-0-9]*$")
mYamlFloatDigits = re.compile(r"^[-.0-9eE]*$")
mYamlListPattern = re.compile(r"^\[(.*)\]$")
mYamlMultilineList = re.compile(r"^ *- (.*)$")

def load(str):
    dict = None
    key = None
    emptyLines = 0

    lines = str.splitlines()
    while lines:
        line = lines.pop(0)
        if myIsAllSpaces(line):
            emptyLines += 1
            continue
        result = mYamlKV.match(line)

        if result:
            if not dict:
                dict = {}
            key = result.group(1).strip()
            value = result.group(2).strip()
            (lines, value) = myReadValue(lines, value)
            dict[key] = value
        else:
            if dict and key and key in dict:
                c = " " if emptyLines == 0 else "\n" * emptyLines
                dict[key] += c + line.strip()
            else:
                raise Exception("monkeyYaml is confused at " + line)
        emptyLines = 0
    return dict

def myReadValue(lines, value):
    if value == ">":
        (lines, value) = myMultiline(lines, value)
        value = value + "\n"
        return (lines, value)
    if lines and not value and myMaybeList(lines[0]):
        return myMultilineList(lines, value)
    else:
        return lines, myReadOneLine(value)

def myMaybeList(value):
    return mYamlMultilineList.match(value)

def myMultilineList(lines, value):
    # assume no explcit indentor (otherwise have to parse value)
    value = []
    indent = None
    while lines:
        line = lines.pop(0)
        leading = myLeadingSpaces(line)
        if myIsAllSpaces(line):
            pass
        elif leading < indent:
            lines.insert(0, line)
            break;
        else:
            indent = indent or leading
            value += [myReadOneLine(myRemoveListHeader(indent, line))]
    return (lines, value)

def myRemoveListHeader(indent, line):
    line = line[indent:]
    return mYamlMultilineList.match(line).group(1)

def myReadOneLine(value):
    if mYamlListPattern.match(value):
        return myFlowList(value)
    elif mYamlIntDigits.match(value):
        try:
            value = int(value)
        except ValueError:
            pass
    elif mYamlFloatDigits.match(value):
        try:
            value = float(value)
        except ValueError:
            pass
    return value

def myFlowList(value):
    result = mYamlListPattern.match(value)
    values = result.group(1).split(",")
    return [myReadOneLine(v.strip()) for v in values]

def myMultiline(lines, value):
    # assume no explcit indentor (otherwise have to parse value)
    value = []
    indent = myLeadingSpaces(lines[0])
    while lines:
        line = lines.pop(0)
        if myIsAllSpaces(line):
            value += ["\n"]
        elif myLeadingSpaces(line) < indent:
            lines.insert(0, line)
            break;
        else:
            value += [line[(indent):]]
    value = " ".join(value)
    return (lines, value)

def myIsAllSpaces(line):
    return len(line.strip()) == 0

def myLeadingSpaces(line):
    return len(line) - len(line.lstrip(' '))