xref: /aosp_15_r20/external/mesa3d/meson_to_hermetic/meson2python.py (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Workerimport re
2*61046927SAndroid Build Coastguard Workerimport sys
3*61046927SAndroid Build Coastguard Worker
4*61046927SAndroid Build Coastguard Workerfrom lark import Lark, Tree
5*61046927SAndroid Build Coastguard Workerfrom lark.visitors import Interpreter
6*61046927SAndroid Build Coastguard Worker
7*61046927SAndroid Build Coastguard Worker# This grammar derived from:
8*61046927SAndroid Build Coastguard Worker# https://mesonbuild.com/Syntax.html#grammar
9*61046927SAndroid Build Coastguard Workermeson_grammar = r"""
10*61046927SAndroid Build Coastguard Worker    ?start: (statement | COMMENT | NEWLINE)*
11*61046927SAndroid Build Coastguard Worker
12*61046927SAndroid Build Coastguard Worker    ?additive_expression: multiplicative_expression | (additive_expression additive_operator multiplicative_expression)
13*61046927SAndroid Build Coastguard Worker    additive_operator: PLUS | MINUS
14*61046927SAndroid Build Coastguard Worker    argument_list: positional_arguments [COMMA keyword_arguments] [COMMA] | keyword_arguments
15*61046927SAndroid Build Coastguard Worker    array_literal: LBRACKET [expression_list] RBRACKET
16*61046927SAndroid Build Coastguard Worker    ?assignment_statement: assignment_expression
17*61046927SAndroid Build Coastguard Worker    assignment_expression: expression assignment_operator expression
18*61046927SAndroid Build Coastguard Worker    assignment_operator: EQUALS | PLUS_EQUALS
19*61046927SAndroid Build Coastguard Worker    binary_literal: "0b" BINARY_NUMBER
20*61046927SAndroid Build Coastguard Worker    BINARY_NUMBER: /[01]+/
21*61046927SAndroid Build Coastguard Worker    boolean_literal: TRUE | FALSE
22*61046927SAndroid Build Coastguard Worker    build_definition: (NEWLINE | statement)*
23*61046927SAndroid Build Coastguard Worker    condition: expression
24*61046927SAndroid Build Coastguard Worker    ?conditional_expression: logical_or_expression | (logical_or_expression "?" expression ":" expression)
25*61046927SAndroid Build Coastguard Worker    decimal_literal: DECIMAL_NUMBER
26*61046927SAndroid Build Coastguard Worker    DECIMAL_NUMBER: /[0-9][0-9]*/
27*61046927SAndroid Build Coastguard Worker    dictionary_literal: LBRACE [key_value_list] RBRACE
28*61046927SAndroid Build Coastguard Worker    ?equality_expression: relational_expression | (equality_expression equality_operator relational_expression)
29*61046927SAndroid Build Coastguard Worker    equality_operator: DOUBLE_EQUAL | NOT_EQUAL
30*61046927SAndroid Build Coastguard Worker    ?expression: conditional_expression | logical_or_expression
31*61046927SAndroid Build Coastguard Worker    expression_list: expression (COMMA expression)* COMMA?
32*61046927SAndroid Build Coastguard Worker    ?expression_statement: expression
33*61046927SAndroid Build Coastguard Worker    ?function_expression: id_expression LPAREN [argument_list] RPAREN
34*61046927SAndroid Build Coastguard Worker    hex_literal: "0x" HEX_NUMBER
35*61046927SAndroid Build Coastguard Worker    HEX_NUMBER: /[a-fA-F0-9]+/
36*61046927SAndroid Build Coastguard Worker    id_expression: IDENTIFIER
37*61046927SAndroid Build Coastguard Worker    IDENTIFIER: /[a-zA-Z_][a-zA-Z_0-9]*/
38*61046927SAndroid Build Coastguard Worker    identifier_list: id_expression (COMMA id_expression)*
39*61046927SAndroid Build Coastguard Worker    integer_literal: decimal_literal | octal_literal | hex_literal
40*61046927SAndroid Build Coastguard Worker    iteration_statement: FOREACH identifier_list COLON expression NEWLINE (statement | jump_statement)* ENDFOREACH
41*61046927SAndroid Build Coastguard Worker    jump_statement: (BREAK | CONTINUE) NEWLINE
42*61046927SAndroid Build Coastguard Worker    key_value_item: expression COLON expression
43*61046927SAndroid Build Coastguard Worker    key_value_list: key_value_item (COMMA key_value_item)* COMMA?
44*61046927SAndroid Build Coastguard Worker    keyword_item: id_expression ":" expression
45*61046927SAndroid Build Coastguard Worker    keyword_arguments: keyword_item (COMMA keyword_item)* COMMA?
46*61046927SAndroid Build Coastguard Worker    ?literal: integer_literal | string_literal | boolean_literal | array_literal | dictionary_literal
47*61046927SAndroid Build Coastguard Worker    ?logical_and_expression: equality_expression | (logical_and_expression AND ["\\"] equality_expression)
48*61046927SAndroid Build Coastguard Worker    ?logical_or_expression: logical_and_expression | (logical_or_expression OR ["\\"] logical_and_expression)
49*61046927SAndroid Build Coastguard Worker    ?method_expression: postfix_expression ["\\"] DOT function_expression
50*61046927SAndroid Build Coastguard Worker    ?multiplicative_expression: unary_expression | (multiplicative_expression multiplicative_operator unary_expression)
51*61046927SAndroid Build Coastguard Worker    multiplicative_operator: ASTERISK | SLASH | PERCENT
52*61046927SAndroid Build Coastguard Worker    octal_literal: "0o" OCTAL_NUMBER
53*61046927SAndroid Build Coastguard Worker    OCTAL_NUMBER: /[0-7]+/
54*61046927SAndroid Build Coastguard Worker    positional_arguments: expression (COMMA expression)*
55*61046927SAndroid Build Coastguard Worker    postfix_expression: primary_expression | subscript_expression | function_expression | method_expression
56*61046927SAndroid Build Coastguard Worker    ?primary_expression: literal | (LPAREN expression RPAREN) | id_expression
57*61046927SAndroid Build Coastguard Worker    ?relational_expression: additive_expression | (relational_expression relational_operator additive_expression)
58*61046927SAndroid Build Coastguard Worker    relational_operator: GREATER | LESSTHAN | GREATER_OR_EQUAL | LESSTHAN_OR_EQUAL | IN | (NOT IN)
59*61046927SAndroid Build Coastguard Worker    selection_statement: IF condition NEWLINE (statement)* (ELIF condition NEWLINE (statement)*)* [ELSE NEWLINE (statement)*] ENDIF
60*61046927SAndroid Build Coastguard Worker    statement: (expression_statement | selection_statement | iteration_statement | assignment_statement) NEWLINE
61*61046927SAndroid Build Coastguard Worker    string_literal: STRING_SIMPLE_VALUE | STRING_MULTILINE_VALUE
62*61046927SAndroid Build Coastguard Worker    ?subscript_expression: postfix_expression LBRACKET expression RBRACKET
63*61046927SAndroid Build Coastguard Worker    ?unary_expression: postfix_expression | (unary_operator unary_expression)
64*61046927SAndroid Build Coastguard Worker    unary_operator: NOT | DASH
65*61046927SAndroid Build Coastguard Worker
66*61046927SAndroid Build Coastguard Worker    AND: /and/
67*61046927SAndroid Build Coastguard Worker    ASTERISK: /\*/
68*61046927SAndroid Build Coastguard Worker    BREAK: /break/
69*61046927SAndroid Build Coastguard Worker    CONTINUE: /continue/
70*61046927SAndroid Build Coastguard Worker    COLON: /:/
71*61046927SAndroid Build Coastguard Worker    COMMA: /,/
72*61046927SAndroid Build Coastguard Worker    DASH: /-/
73*61046927SAndroid Build Coastguard Worker    DOT: /\./
74*61046927SAndroid Build Coastguard Worker    DOUBLE_EQUAL: /==/
75*61046927SAndroid Build Coastguard Worker    EQUALS: /=/
76*61046927SAndroid Build Coastguard Worker    FOREACH: /foreach/
77*61046927SAndroid Build Coastguard Worker    GREATER: />/
78*61046927SAndroid Build Coastguard Worker    GREATER_OR_EQUAL: />=/
79*61046927SAndroid Build Coastguard Worker    # Raise priorities to avoid elif parsed as a statement
80*61046927SAndroid Build Coastguard Worker    ELIF.1: /elif/
81*61046927SAndroid Build Coastguard Worker    ELSE.1: /else/
82*61046927SAndroid Build Coastguard Worker    ENDIF.1: /endif/
83*61046927SAndroid Build Coastguard Worker    ENDFOREACH: /endforeach/
84*61046927SAndroid Build Coastguard Worker    FALSE: /false/
85*61046927SAndroid Build Coastguard Worker    IF: /if /
86*61046927SAndroid Build Coastguard Worker    IN: / in /
87*61046927SAndroid Build Coastguard Worker    LBRACKET: /\[/
88*61046927SAndroid Build Coastguard Worker    NOT: /not /
89*61046927SAndroid Build Coastguard Worker    NOT_EQUAL: /!=/
90*61046927SAndroid Build Coastguard Worker    RBRACKET: /\]/
91*61046927SAndroid Build Coastguard Worker    LESSTHAN: /</
92*61046927SAndroid Build Coastguard Worker    LESSTHAN_OR_EQUAL: /<=/
93*61046927SAndroid Build Coastguard Worker    LBRACE: /{/
94*61046927SAndroid Build Coastguard Worker    LPAREN: /\(/
95*61046927SAndroid Build Coastguard Worker    RBRACE: /}/
96*61046927SAndroid Build Coastguard Worker    RPAREN: /\)/
97*61046927SAndroid Build Coastguard Worker    OR: /or/
98*61046927SAndroid Build Coastguard Worker    PERCENT: /%/
99*61046927SAndroid Build Coastguard Worker    PLUS: /\+/
100*61046927SAndroid Build Coastguard Worker    MINUS: /-/
101*61046927SAndroid Build Coastguard Worker    PLUS_EQUALS: /\+=/
102*61046927SAndroid Build Coastguard Worker    NEWLINE: ( / *\r?\n/ | COMMENT )+
103*61046927SAndroid Build Coastguard Worker    COMMENT: / *\#.*\n/
104*61046927SAndroid Build Coastguard Worker    SLASH: /\//
105*61046927SAndroid Build Coastguard Worker    STRING_SIMPLE_VALUE: /f?'(.*\\')*.*?'/
106*61046927SAndroid Build Coastguard Worker    STRING_MULTILINE_VALUE: /f?'''.*?'''/s
107*61046927SAndroid Build Coastguard Worker    TRUE: /true/
108*61046927SAndroid Build Coastguard Worker
109*61046927SAndroid Build Coastguard Worker    %import common.WS
110*61046927SAndroid Build Coastguard Worker
111*61046927SAndroid Build Coastguard Worker    %ignore WS
112*61046927SAndroid Build Coastguard Worker    # Comments would be nice to keep, but parsing fails end-of-line comments
113*61046927SAndroid Build Coastguard Worker    %ignore COMMENT
114*61046927SAndroid Build Coastguard Worker"""
115*61046927SAndroid Build Coastguard Worker
116*61046927SAndroid Build Coastguard Worker
117*61046927SAndroid Build Coastguard Workerclass TreeToCode(Interpreter):
118*61046927SAndroid Build Coastguard Worker    indent = ''
119*61046927SAndroid Build Coastguard Worker
120*61046927SAndroid Build Coastguard Worker    def statement(self, tree):
121*61046927SAndroid Build Coastguard Worker        string = ''
122*61046927SAndroid Build Coastguard Worker        for child in tree.children:
123*61046927SAndroid Build Coastguard Worker            if isinstance(child, Tree):
124*61046927SAndroid Build Coastguard Worker                string += self.visit(child)
125*61046927SAndroid Build Coastguard Worker            elif child is not None:
126*61046927SAndroid Build Coastguard Worker                string += child
127*61046927SAndroid Build Coastguard Worker        return self.indent + string
128*61046927SAndroid Build Coastguard Worker
129*61046927SAndroid Build Coastguard Worker    def more_indent(self):
130*61046927SAndroid Build Coastguard Worker        self.indent += '  '
131*61046927SAndroid Build Coastguard Worker
132*61046927SAndroid Build Coastguard Worker    def less_indent(self):
133*61046927SAndroid Build Coastguard Worker        self.indent = self.indent[0 : len(self.indent) - 2]
134*61046927SAndroid Build Coastguard Worker
135*61046927SAndroid Build Coastguard Worker    # Ensure spaces around 'and'
136*61046927SAndroid Build Coastguard Worker    def logical_and_expression(self, tree):
137*61046927SAndroid Build Coastguard Worker        assert len(tree.children) == 3
138*61046927SAndroid Build Coastguard Worker        lhs = self.visit(tree.children[0])
139*61046927SAndroid Build Coastguard Worker        rhs = self.visit(tree.children[2])
140*61046927SAndroid Build Coastguard Worker        return lhs + ' and ' + rhs
141*61046927SAndroid Build Coastguard Worker
142*61046927SAndroid Build Coastguard Worker    # Ensure spaces around 'or'
143*61046927SAndroid Build Coastguard Worker    def logical_or_expression(self, tree):
144*61046927SAndroid Build Coastguard Worker        assert len(tree.children) == 3
145*61046927SAndroid Build Coastguard Worker        lhs = self.visit(tree.children[0])
146*61046927SAndroid Build Coastguard Worker        rhs = self.visit(tree.children[2])
147*61046927SAndroid Build Coastguard Worker        return lhs + ' or ' + rhs
148*61046927SAndroid Build Coastguard Worker
149*61046927SAndroid Build Coastguard Worker    # A ? B : C becomes B if A else C
150*61046927SAndroid Build Coastguard Worker    def conditional_expression(self, tree):
151*61046927SAndroid Build Coastguard Worker        assert len(tree.children) == 3
152*61046927SAndroid Build Coastguard Worker        expr = self.visit(tree.children[0])
153*61046927SAndroid Build Coastguard Worker        first = self.visit(tree.children[1])
154*61046927SAndroid Build Coastguard Worker        second = self.visit(tree.children[2])
155*61046927SAndroid Build Coastguard Worker        return first + ' if ' + expr + ' else ' + second
156*61046927SAndroid Build Coastguard Worker
157*61046927SAndroid Build Coastguard Worker    def assignment_expression(self, tree):
158*61046927SAndroid Build Coastguard Worker        assert len(tree.children) == 3
159*61046927SAndroid Build Coastguard Worker        lhs = self.visit(tree.children[0])
160*61046927SAndroid Build Coastguard Worker        operator = self.visit(tree.children[1])
161*61046927SAndroid Build Coastguard Worker        rhs = self.visit(tree.children[2])
162*61046927SAndroid Build Coastguard Worker        if operator == '+=' and rhs.startswith('{'):
163*61046927SAndroid Build Coastguard Worker            # Convert += to |= for dictionaries
164*61046927SAndroid Build Coastguard Worker            return lhs + ' |= ' + rhs
165*61046927SAndroid Build Coastguard Worker        elif operator == '+=' and rhs.startswith("'"):
166*61046927SAndroid Build Coastguard Worker            # Handle literal string append to list or string
167*61046927SAndroid Build Coastguard Worker            return (
168*61046927SAndroid Build Coastguard Worker                lhs
169*61046927SAndroid Build Coastguard Worker                + ' += '
170*61046927SAndroid Build Coastguard Worker                + '['
171*61046927SAndroid Build Coastguard Worker                + rhs
172*61046927SAndroid Build Coastguard Worker                + '] if isinstance('
173*61046927SAndroid Build Coastguard Worker                + lhs
174*61046927SAndroid Build Coastguard Worker                + ', list) else '
175*61046927SAndroid Build Coastguard Worker                + rhs
176*61046927SAndroid Build Coastguard Worker            )
177*61046927SAndroid Build Coastguard Worker        return lhs + operator + rhs
178*61046927SAndroid Build Coastguard Worker
179*61046927SAndroid Build Coastguard Worker    def iteration_statement(self, tree):
180*61046927SAndroid Build Coastguard Worker        # foreach = tree.children[0]
181*61046927SAndroid Build Coastguard Worker        identifier_list = self.visit(tree.children[1])
182*61046927SAndroid Build Coastguard Worker        # colon = tree.children[2]
183*61046927SAndroid Build Coastguard Worker        id_expression = self.visit(tree.children[3])
184*61046927SAndroid Build Coastguard Worker        # newline = tree.children[4]
185*61046927SAndroid Build Coastguard Worker        string = 'for ' + identifier_list + ' in ' + id_expression
186*61046927SAndroid Build Coastguard Worker        string += (
187*61046927SAndroid Build Coastguard Worker            '.items():\n' if re.search(r',', identifier_list) is not None else ':\n'
188*61046927SAndroid Build Coastguard Worker        )
189*61046927SAndroid Build Coastguard Worker        self.more_indent()
190*61046927SAndroid Build Coastguard Worker        lastindex = len(tree.children) - 1
191*61046927SAndroid Build Coastguard Worker        for child in tree.children[5:lastindex]:
192*61046927SAndroid Build Coastguard Worker            if isinstance(child, Tree):
193*61046927SAndroid Build Coastguard Worker                string += self.visit(child)
194*61046927SAndroid Build Coastguard Worker            elif child is not None:
195*61046927SAndroid Build Coastguard Worker                string += child
196*61046927SAndroid Build Coastguard Worker        self.less_indent()
197*61046927SAndroid Build Coastguard Worker        return string
198*61046927SAndroid Build Coastguard Worker
199*61046927SAndroid Build Coastguard Worker    def selection_statement(self, tree):
200*61046927SAndroid Build Coastguard Worker        string = ''
201*61046927SAndroid Build Coastguard Worker        index = 0
202*61046927SAndroid Build Coastguard Worker        while index < len(tree.children):
203*61046927SAndroid Build Coastguard Worker            prefix = tree.children[index]
204*61046927SAndroid Build Coastguard Worker            index = index + 1
205*61046927SAndroid Build Coastguard Worker            if prefix is None:
206*61046927SAndroid Build Coastguard Worker                continue
207*61046927SAndroid Build Coastguard Worker            if isinstance(prefix, Tree):
208*61046927SAndroid Build Coastguard Worker                exit('unexpected prefix: ' + prefix.pretty())
209*61046927SAndroid Build Coastguard Worker            if re.match(r' *endif', prefix) is not None:
210*61046927SAndroid Build Coastguard Worker                break
211*61046927SAndroid Build Coastguard Worker
212*61046927SAndroid Build Coastguard Worker            if re.match(r'if', prefix) is not None:
213*61046927SAndroid Build Coastguard Worker                condition = self.visit(tree.children[index])
214*61046927SAndroid Build Coastguard Worker                index += 1
215*61046927SAndroid Build Coastguard Worker                # Skip indent here because all statements are prepended with the indentation
216*61046927SAndroid Build Coastguard Worker                string += 'if ' + condition + ':\n'
217*61046927SAndroid Build Coastguard Worker            elif re.match(r'elif', prefix) is not None:
218*61046927SAndroid Build Coastguard Worker                condition = self.visit(tree.children[index])
219*61046927SAndroid Build Coastguard Worker                index = index + 1
220*61046927SAndroid Build Coastguard Worker                string += self.indent + 'elif ' + condition + ':\n'
221*61046927SAndroid Build Coastguard Worker            elif re.match(r'else', prefix) is not None:
222*61046927SAndroid Build Coastguard Worker                string += self.indent + 'else:\n'
223*61046927SAndroid Build Coastguard Worker            else:
224*61046927SAndroid Build Coastguard Worker                exit('Not a prefix: ' + prefix)
225*61046927SAndroid Build Coastguard Worker
226*61046927SAndroid Build Coastguard Worker            # newline = tree.children[index]
227*61046927SAndroid Build Coastguard Worker            index += 1
228*61046927SAndroid Build Coastguard Worker
229*61046927SAndroid Build Coastguard Worker            statement_count = 0
230*61046927SAndroid Build Coastguard Worker            self.more_indent()
231*61046927SAndroid Build Coastguard Worker            while index < len(tree.children):
232*61046927SAndroid Build Coastguard Worker                statement = tree.children[index]
233*61046927SAndroid Build Coastguard Worker                if not isinstance(statement, Tree):
234*61046927SAndroid Build Coastguard Worker                    break
235*61046927SAndroid Build Coastguard Worker                string += self.visit(statement)
236*61046927SAndroid Build Coastguard Worker                index = index + 1
237*61046927SAndroid Build Coastguard Worker                statement_count = statement_count + 1
238*61046927SAndroid Build Coastguard Worker            if statement_count == 0:
239*61046927SAndroid Build Coastguard Worker                string += self.indent + 'noop()\n'
240*61046927SAndroid Build Coastguard Worker            self.less_indent()
241*61046927SAndroid Build Coastguard Worker
242*61046927SAndroid Build Coastguard Worker        return string
243*61046927SAndroid Build Coastguard Worker
244*61046927SAndroid Build Coastguard Worker    def postfix_expression(self, tree):
245*61046927SAndroid Build Coastguard Worker        string = ''
246*61046927SAndroid Build Coastguard Worker        for child in tree.children:
247*61046927SAndroid Build Coastguard Worker            if isinstance(child, Tree):
248*61046927SAndroid Build Coastguard Worker                subtree = self.visit(child)
249*61046927SAndroid Build Coastguard Worker                subtree = re.sub(r'(.+)\.to_int\(\)', r'int(\g<1>)', subtree)
250*61046927SAndroid Build Coastguard Worker                subtree = re.sub(r'(.+)\.to_string\(\)', r'str(\g<1>)', subtree)
251*61046927SAndroid Build Coastguard Worker                subtree = re.sub(r'(.+)\.length\(\)', r'len(\g<1>)', subtree)
252*61046927SAndroid Build Coastguard Worker                subtree = re.sub(r'(.+)\.to_upper\(\)', r'\g<1>.upper()', subtree)
253*61046927SAndroid Build Coastguard Worker                subtree = re.sub(
254*61046927SAndroid Build Coastguard Worker                    r'(.+)\.underscorify\(\)',
255*61046927SAndroid Build Coastguard Worker                    r"\g<1>.replace('.', '_').replace('/', '_')",
256*61046927SAndroid Build Coastguard Worker                    subtree,
257*61046927SAndroid Build Coastguard Worker                )
258*61046927SAndroid Build Coastguard Worker                string += subtree
259*61046927SAndroid Build Coastguard Worker            elif child is not None:
260*61046927SAndroid Build Coastguard Worker                string += child
261*61046927SAndroid Build Coastguard Worker        return string
262*61046927SAndroid Build Coastguard Worker
263*61046927SAndroid Build Coastguard Worker    def function_expression(self, tree):
264*61046927SAndroid Build Coastguard Worker        assert len(tree.children) == 4
265*61046927SAndroid Build Coastguard Worker        identifier = self.visit(tree.children[0])
266*61046927SAndroid Build Coastguard Worker        if identifier == 'import':
267*61046927SAndroid Build Coastguard Worker            identifier = 'module_import'
268*61046927SAndroid Build Coastguard Worker        lparen = tree.children[1]
269*61046927SAndroid Build Coastguard Worker        args = (
270*61046927SAndroid Build Coastguard Worker            self.visit(tree.children[2]) if isinstance(tree.children[2], Tree) else ''
271*61046927SAndroid Build Coastguard Worker        )
272*61046927SAndroid Build Coastguard Worker        rparen = tree.children[3]
273*61046927SAndroid Build Coastguard Worker        if identifier == 'contains':
274*61046927SAndroid Build Coastguard Worker            return 'count' + lparen + args + rparen + ' > 0'
275*61046927SAndroid Build Coastguard Worker        return identifier + lparen + args + rparen
276*61046927SAndroid Build Coastguard Worker
277*61046927SAndroid Build Coastguard Worker    def multiplicative_expression(self, tree):
278*61046927SAndroid Build Coastguard Worker        assert len(tree.children) == 3
279*61046927SAndroid Build Coastguard Worker        lhs = self.visit(tree.children[0])
280*61046927SAndroid Build Coastguard Worker        operator = self.visit(tree.children[1])
281*61046927SAndroid Build Coastguard Worker        rhs = self.visit(tree.children[2])
282*61046927SAndroid Build Coastguard Worker        # Slash used mostly to concatenate strings
283*61046927SAndroid Build Coastguard Worker        if operator == '/':
284*61046927SAndroid Build Coastguard Worker            return (
285*61046927SAndroid Build Coastguard Worker                '('
286*61046927SAndroid Build Coastguard Worker                + lhs
287*61046927SAndroid Build Coastguard Worker                + ' + '
288*61046927SAndroid Build Coastguard Worker                + rhs
289*61046927SAndroid Build Coastguard Worker                + ') if isinstance('
290*61046927SAndroid Build Coastguard Worker                + lhs
291*61046927SAndroid Build Coastguard Worker                + ', str) else ('
292*61046927SAndroid Build Coastguard Worker                + lhs
293*61046927SAndroid Build Coastguard Worker                + ' / '
294*61046927SAndroid Build Coastguard Worker                + rhs
295*61046927SAndroid Build Coastguard Worker                + ')'
296*61046927SAndroid Build Coastguard Worker            )
297*61046927SAndroid Build Coastguard Worker        return lhs + operator + rhs
298*61046927SAndroid Build Coastguard Worker
299*61046927SAndroid Build Coastguard Worker    # Switch from colon to equals
300*61046927SAndroid Build Coastguard Worker    def keyword_item(self, tree):
301*61046927SAndroid Build Coastguard Worker        id_ = self.visit(tree.children[0])
302*61046927SAndroid Build Coastguard Worker        args = self.visit(tree.children[1])
303*61046927SAndroid Build Coastguard Worker        return id_ + '=' + args
304*61046927SAndroid Build Coastguard Worker
305*61046927SAndroid Build Coastguard Worker    def boolean_literal(self, tree):
306*61046927SAndroid Build Coastguard Worker        assert len(tree.children) == 1
307*61046927SAndroid Build Coastguard Worker        value = tree.children[0]
308*61046927SAndroid Build Coastguard Worker        if value == 'true':
309*61046927SAndroid Build Coastguard Worker            return 'True'
310*61046927SAndroid Build Coastguard Worker        elif value == 'false':
311*61046927SAndroid Build Coastguard Worker            return 'False'
312*61046927SAndroid Build Coastguard Worker        exit('Unhandled value: ' + value)
313*61046927SAndroid Build Coastguard Worker
314*61046927SAndroid Build Coastguard Worker    def string_literal(self, tree):
315*61046927SAndroid Build Coastguard Worker        assert len(tree.children) == 1
316*61046927SAndroid Build Coastguard Worker        string = tree.children[0]
317*61046927SAndroid Build Coastguard Worker        string = re.sub(r'(@[0-9]@)', r'{}', string)
318*61046927SAndroid Build Coastguard Worker        if string.startswith('f'):
319*61046927SAndroid Build Coastguard Worker            string = re.sub(r'(@(.+)@)', r'{\g<2>}', string)
320*61046927SAndroid Build Coastguard Worker        return string
321*61046927SAndroid Build Coastguard Worker
322*61046927SAndroid Build Coastguard Worker    def __default__(self, tree):
323*61046927SAndroid Build Coastguard Worker        string = ''
324*61046927SAndroid Build Coastguard Worker        for child in tree.children:
325*61046927SAndroid Build Coastguard Worker            if isinstance(child, Tree):
326*61046927SAndroid Build Coastguard Worker                string += self.visit(child)
327*61046927SAndroid Build Coastguard Worker            elif child is not None:
328*61046927SAndroid Build Coastguard Worker                string += child
329*61046927SAndroid Build Coastguard Worker        return string
330*61046927SAndroid Build Coastguard Worker
331*61046927SAndroid Build Coastguard Worker
332*61046927SAndroid Build Coastguard Worker# Converts the given file from meson to python and returns the content as a string
333*61046927SAndroid Build Coastguard Workerdef meson2python(file_name):
334*61046927SAndroid Build Coastguard Worker    meson_parser = Lark(meson_grammar, parser='earley')
335*61046927SAndroid Build Coastguard Worker    with open(file_name) as f:
336*61046927SAndroid Build Coastguard Worker        # Ensure newline before end of file
337*61046927SAndroid Build Coastguard Worker        tree = meson_parser.parse(f.read() + '\n')
338*61046927SAndroid Build Coastguard Worker        code = TreeToCode().visit(tree)
339*61046927SAndroid Build Coastguard Worker        return code
340*61046927SAndroid Build Coastguard Worker
341*61046927SAndroid Build Coastguard Worker
342*61046927SAndroid Build Coastguard Workerif __name__ == '__main__':
343*61046927SAndroid Build Coastguard Worker    meson2python(sys.argv[1])
344