Subversion Repositories Kolibri OS

Rev

Rev 9357 | Rev 9377 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
9367 Boppan 1
# Copyright Magomed Kostoev
2
# Published under MIT license
3
 
4
class Rule:
5
    pass
6
 
7
def get_config(config_name):
8
    if config_name == "KPACK_CMD":
9
        # Just never pack the file for now
10
        return ""
11
    else:
12
        print(f"Unknown config name: {config_name}")
13
        exit(-1)
14
 
15
def skip_whitespaces(src, ptr):
16
    while len(src) > ptr and src[ptr] == " ":
17
        ptr += 1
18
    return ptr
19
 
20
# Returns True if @src has @string starting from @ptr index
21
def match_string(src, ptr, string):
22
    if len(src) <= ptr + len(string):
23
        return False
24
    for i in range(len(string)):
25
        if src[ptr + i] != string[i]:
26
            return False
27
    return True
28
 
29
def parse_tup_getconfig(src, ptr):
30
    # Skip get straight to the argument
31
    ptr += len("tup.getconfig(")
32
    ptr = skip_whitespaces(src, ptr)
33
    if src[ptr] != "\"":
34
        print("Expected \"config name\" as tup.getconfig parameter")
35
        exit()
36
    (config_name, ptr) = parse_string(src, ptr)
37
    ptr = skip_whitespaces(src, ptr)
38
    # Skip closing parenthese of the tup.getconfig call
39
    assert(src[ptr] == ")")
40
    ptr += 1
41
    return (get_config(config_name), ptr)
42
 
43
def parse_string(src, ptr):
44
    ptr += 1
45
    string = ""
46
    while src[ptr] != "\"":
47
        string += src[ptr]
48
        ptr += 1
49
    # Skip the closing "\""
50
    ptr += 1
51
    ptr = skip_whitespaces(src, ptr)
52
    # Check if we have concatination here
53
    if match_string(src, ptr, ".."):
54
        # Skip the ".."
55
        ptr += 2
56
        # The expression parsing should result in a string
57
        (string_to_add, ptr) = parse_expression(src, ptr)
58
        # Concat our string to the resulting string
59
        string += string_to_add
60
    return (string, ptr)
61
 
62
def parse_expression(src, ptr):
63
    ptr = skip_whitespaces(src, ptr)
64
    result = "WAT?!"
65
    if src[ptr] == "\"":
66
        (result, ptr) = parse_string(src, ptr)
67
    elif match_string(src, ptr, "tup.getconfig("):
68
        (result, ptr) = parse_tup_getconfig(src, ptr)
69
    else:
70
        print(f"Can't handle anything starting with '{src[ptr]}'")
71
        exit(-1)
72
    ptr = skip_whitespaces(src, ptr)
73
    return (result, ptr)
74
 
75
def expect_comma(src, ptr):
76
    comma_skept = False
77
    ptr = skip_whitespaces(src, ptr)
78
    if src[ptr] == ",":
79
        ptr += 1
80
        return (True, ptr)
81
    else:
82
        return (False, ptr)
83
 
84
def parse_arguments(src, ptr):
85
    result = []
86
    # Parse first argument
87
    (argument, ptr) = parse_expression(src, ptr)
88
    result.append(argument)
89
    (comma_encoutered, ptr) = expect_comma(src, ptr)
90
    # Parse the second argument if it's there
91
    if comma_encoutered:
92
        (argument, ptr) = parse_expression(src, ptr)
93
        result.append(argument)
94
        (comma_encoutered, ptr) = expect_comma(src, ptr)
95
    # Parse third argument if it's there
96
    if comma_encoutered:
97
        (argument, ptr) = parse_expression(src, ptr)
98
        result.append(argument)
99
    return result
100
 
101
def parse_rule(src, ptr):
102
    # Get straight to the first argument
103
    ptr += len("tup.rule(")
104
    # Parse the arguments
105
    args = parse_arguments(src, ptr)
106
    # Build the rule object
107
    result = Rule()
108
    if len(args) == 3:
109
        result.input = args[0]
110
        result.command = args[1]
111
        result.output = args[2]
112
        # Replace %f with input file in rule's command
113
        if type(result.input == str):
114
            result.command = result.command.replace("%f", result.input)
115
        else:
116
            print("Command building with non-string tup.rule's first argument"
117
                + " isn't implemented")
118
            exit()
119
        # Replace %o with output file in rule's command
120
        if type(result.output == str):
121
            result.command = result.command.replace("%o", result.output)
122
        else:
123
            print("Command building with non-string tup.rule's first argument"
124
                + " isn't implemented")
125
            exit()
126
    elif len(args) == 2:
127
        result.input = []
128
        result.command = args[0]
129
        result.output = args[1]
130
    else:
131
        print(f"tup.rule can only take 2 or 3 arguments, not {len(args)}")
132
        exit(-1)
133
    # Unify the API - return arrays as input and output
134
    if type(result.input) == str:
135
        result.input = [ result.input ]
136
    else:
137
        assert(type(result.input) == list)
138
    if type(result.output) == str:
139
        result.output = [ result.output ]
140
    else:
141
        assert(type(result.output) == list)
142
    return result
143
 
144
def parse(file_name):
145
    rules = []
146
    with open(file_name) as f:
147
        tupfile = f.read()
148
    rule_begin_index = tupfile.find("tup.rule(")
149
    while (rule_begin_index != -1):
150
        rules.append(parse_rule(tupfile, rule_begin_index))
151
        # Find the next tup.rule call
152
        rule_begin_index = tupfile.find("tup.rule(", rule_begin_index + len("tup.rule("))
153
    return rules