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