<s> import re <EOL> from . mesonlib import MesonException <EOL> class ParseException ( MesonException ) : <EOL> def __init__ ( self , text , lineno , colno ) : <EOL> super ( ) . __init__ ( text ) <EOL> self . lineno = lineno <EOL> self . colno = colno <EOL> class Token : <EOL> def __init__ ( self , tid , lineno , colno , value ) : <EOL> self . tid = tid <EOL> self . lineno = lineno <EOL> self . colno = colno <EOL> self . value = value <EOL> def __eq__ ( self , other ) : <EOL> if isinstance ( other , str ) : <EOL> return self . tid == other <EOL> return self . tid == other . tid <EOL> class Lexer : <EOL> def __init__ ( self ) : <EOL> self . keywords = { '<STR_LIT:true>' , '<STR_LIT:false>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' } <EOL> self . token_specification = [ <EOL> ( '<STR_LIT:ignore>' , re . compile ( r'<STR_LIT>' ) ) , <EOL> ( '<STR_LIT:id>' , re . compile ( '<STR_LIT>' ) ) , <EOL> ( '<STR_LIT>' , re . compile ( r'<STR_LIT>' ) ) , <EOL> ( '<STR_LIT>' , re . compile ( r'<STR_LIT>' ) ) , <EOL> ( '<STR_LIT>' , re . compile ( r'<STR_LIT:\n>' ) ) , <EOL> ( '<STR_LIT>' , re . compile ( r"<STR_LIT>" , re . M ) ) , <EOL> ( '<STR_LIT>' , re . compile ( r'<STR_LIT>' ) ) , <EOL> ( '<STR_LIT>' , re . compile ( r'<STR_LIT>' ) ) , <EOL> ( '<STR_LIT>' , re . compile ( r'<STR_LIT>' ) ) , <EOL> ( '<STR_LIT>' , re . compile ( r'<STR_LIT>' ) ) , <EOL> ( '<STR_LIT>' , re . compile ( r'<STR_LIT>' ) ) , <EOL> ( '<STR_LIT>' , re . compile ( r'<STR_LIT:">' ) ) , <EOL> ( '<STR_LIT:string>' , re . compile ( r"<STR_LIT>" ) ) , <EOL> ( '<STR_LIT>' , re . compile ( r'<STR_LIT:U+002C>' ) ) , <EOL> ( '<STR_LIT>' , re . compile ( r'<STR_LIT>' ) ) , <EOL> ( '<STR_LIT>' , re . compile ( r'<STR_LIT>' ) ) , <EOL> ( '<STR_LIT>' , re . compile ( r'<STR_LIT>' ) ) , <EOL> ( '<STR_LIT>' , re . compile ( r'<STR_LIT:->' ) ) , <EOL> ( '<STR_LIT>' , re . compile ( r'<STR_LIT>' ) ) , <EOL> ( '<STR_LIT>' , re . compile ( r'<STR_LIT:/>' ) ) , <EOL> ( '<STR_LIT>' , re . compile ( r'<STR_LIT::>' ) ) , <EOL> ( '<STR_LIT>' , re . compile ( r'<STR_LIT>' ) ) , <EOL> ( '<STR_LIT>' , re . compile ( r'<STR_LIT>' ) ) , <EOL> ( '<STR_LIT>' , re . compile ( r'<STR_LIT:=>' ) ) , <EOL> ( '<STR_LIT>' , re . compile ( r'<STR_LIT>' ) ) , <EOL> ( '<STR_LIT>' , re . compile ( r'<STR_LIT:<>' ) ) , <EOL> ( '<STR_LIT>' , re . compile ( r'<STR_LIT>' ) ) , <EOL> ( '<STR_LIT>' , re . compile ( r'<STR_LIT:>>' ) ) , <EOL> ] <EOL> def lex ( self , code ) : <EOL> lineno = <NUM_LIT:1> <EOL> line_start = <NUM_LIT:0> <EOL> loc = <NUM_LIT:0> ; <EOL> par_count = <NUM_LIT:0> <EOL> bracket_count = <NUM_LIT:0> <EOL> col = <NUM_LIT:0> <EOL> while ( loc < len ( code ) ) : <EOL> matched = False <EOL> value = None <EOL> for ( tid , reg ) in self . token_specification : <EOL> mo = reg . match ( code , loc ) <EOL> if mo : <EOL> curline = lineno <EOL> col = mo . start ( ) - line_start <EOL> matched = True <EOL> loc = mo . end ( ) <EOL> match_text = mo . group ( ) <EOL> if tid == '<STR_LIT:ignore>' or tid == '<STR_LIT>' : <EOL> break <EOL> elif tid == '<STR_LIT>' : <EOL> par_count += <NUM_LIT:1> <EOL> elif tid == '<STR_LIT>' : <EOL> par_count -= <NUM_LIT:1> <EOL> elif tid == '<STR_LIT>' : <EOL> bracket_count += <NUM_LIT:1> <EOL> elif tid == '<STR_LIT>' : <EOL> bracket_count -= <NUM_LIT:1> <EOL> elif tid == '<STR_LIT>' : <EOL> raise ParseException ( '<STR_LIT>' , lineno , col ) <EOL> elif tid == '<STR_LIT:string>' : <EOL> value = match_text [ <NUM_LIT:1> : - <NUM_LIT:1> ] . replace ( r"<STR_LIT>" , "<STR_LIT:'>" ) . replace ( r"<STR_LIT>" . strip ( ) , r"<STR_LIT>" . strip ( ) ) . replace ( "<STR_LIT>" , "<STR_LIT:\n>" ) <EOL> elif tid == '<STR_LIT>' : <EOL> tid = '<STR_LIT:string>' <EOL> value = match_text [ <NUM_LIT:3> : - <NUM_LIT:3> ] <EOL> lines = match_text . split ( '<STR_LIT:\n>' ) <EOL> if len ( lines ) > <NUM_LIT:1> : <EOL> lineno += len ( lines ) - <NUM_LIT:1> <EOL> line_start = mo . end ( ) - len ( lines [ - <NUM_LIT:1> ] ) <EOL> elif tid == '<STR_LIT>' : <EOL> value = int ( match_text ) <EOL> elif tid == '<STR_LIT>' or tid == '<STR_LIT>' : <EOL> lineno += <NUM_LIT:1> <EOL> line_start = loc <EOL> if par_count > <NUM_LIT:0> or bracket_count > <NUM_LIT:0> : <EOL> break <EOL> elif tid == '<STR_LIT:id>' : <EOL> if match_text in self . keywords : <EOL> tid = match_text <EOL> else : <EOL> value = match_text <EOL> yield Token ( tid , curline , col , value ) <EOL> break <EOL> if not matched : <EOL> raise ParseException ( '<STR_LIT>' , lineno , col ) <EOL> class BooleanNode : <EOL> def __init__ ( self , token , value ) : <EOL> self . lineno = token . lineno <EOL> self . colno = token . colno <EOL> self . value = value <EOL> assert ( isinstance ( self . value , bool ) ) <EOL> class IdNode : <EOL> def __init__ ( self , token ) : <EOL> self . lineno = token . lineno <EOL> self . colno = token . colno <EOL> self . value = token . value <EOL> assert ( isinstance ( self . value , str ) ) <EOL> def __str__ ( self ) : <EOL> return "<STR_LIT>" % ( self . value , self . lineno , self . colno ) <EOL> class NumberNode : <EOL> def __init__ ( self , token ) : <EOL> self . lineno = token . lineno <EOL> self . colno = token . colno <EOL> self . value = token . value <EOL> assert ( isinstance ( self . value , int ) ) <EOL> class StringNode : <EOL> def __init__ ( self , token ) : <EOL> self . lineno = token . lineno <EOL> self . colno = token . colno <EOL> self . value = token . value <EOL> assert ( isinstance ( self . value , str ) ) <EOL> def __str__ ( self ) : <EOL> return "<STR_LIT>" % ( self . value , self . lineno , self . colno ) <EOL> class ArrayNode : <EOL> def __init__ ( self , args ) : <EOL> self . lineno = args . lineno <EOL> self . colno = args . colno <EOL> self . args = args <EOL> class EmptyNode : <EOL> def __init__ ( self ) : <EOL> self . lineno = <NUM_LIT:0> <EOL> self . colno = <NUM_LIT:0> <EOL> self . value = None <EOL> class OrNode : <EOL> def __init__ ( self , lineno , colno , left , right ) : <EOL> self . lineno = lineno <EOL> self . colno = colno <EOL> self . left = left <EOL> self . right = right <EOL> class AndNode : <EOL> def __init__ ( self , lineno , colno , left , right ) : <EOL> self . lineno = lineno <EOL> self . colno = colno <EOL> self . left = left <EOL> self . right = right <EOL> class ComparisonNode : <EOL> def __init__ ( self , lineno , colno , ctype , left , right ) : <EOL> self . lineno = lineno <EOL> self . colno = colno <EOL> self . left = left <EOL> self . right = right <EOL> self . ctype = ctype <EOL> class ArithmeticNode : <EOL> def __init__ ( self , lineno , colno , operation , left , right ) : <EOL> self . lineno = lineno <EOL> self . colno = colno <EOL> self . left = left <EOL> self . right = right <EOL> self . operation = operation <EOL> class NotNode : <EOL> def __init__ ( self , lineno , colno , value ) : <EOL> self . lineno = lineno <EOL> self . colno = colno <EOL> self . value = value <EOL> class CodeBlockNode : <EOL> def __init__ ( self , lineno , colno ) : <EOL> self . lineno = lineno <EOL> self . colno = colno <EOL> self . lines = [ ] <EOL> class IndexNode : <EOL> def __init__ ( self , iobject , index ) : <EOL> self . iobject = iobject <EOL> self . index = index <EOL> self . lineno = iobject . lineno <EOL> self . colno = iobject . colno <EOL> class MethodNode : <EOL> def __init__ ( self , lineno , colno , source_object , name , args ) : <EOL> self . lineno = lineno <EOL> self . colno = colno <EOL> self . source_object = source_object <EOL> self . name = name <EOL> assert ( isinstance ( self . name , str ) ) <EOL> self . args = args <EOL> class FunctionNode : <EOL> def __init__ ( self , lineno , colno , func_name , args ) : <EOL> self . lineno = lineno <EOL> self . colno = colno <EOL> self . func_name = func_name <EOL> assert ( isinstance ( func_name , str ) ) <EOL> self . args = args <EOL> class AssignmentNode : <EOL> def __init__ ( self , lineno , colno , var_name , value ) : <EOL> self . lineno = lineno <EOL> self . colno = colno <EOL> self . var_name = var_name <EOL> assert ( isinstance ( var_name , str ) ) <EOL> self . value = value <EOL> class PlusAssignmentNode : <EOL> def __init__ ( self , lineno , colno , var_name , value ) : <EOL> self . lineno = lineno <EOL> self . colno = colno <EOL> self . var_name = var_name <EOL> assert ( isinstance ( var_name , str ) ) <EOL> self . value = value <EOL> class ForeachClauseNode ( ) : <EOL> def __init__ ( self , lineno , colno , varname , items , block ) : <EOL> self . lineno = lineno <EOL> self . colno = colno <EOL> self . varname = varname <EOL> self . items = items <EOL> self . block = block <EOL> class IfClauseNode ( ) : <EOL> def __init__ ( self , lineno , colno ) : <EOL> self . lineno = lineno <EOL> self . colno = colno <EOL> self . ifs = [ ] <EOL> self . elseblock = EmptyNode ( ) <EOL> class UMinusNode ( ) : <EOL> def __init__ ( self , lineno , colno , value ) : <EOL> self . lineno = lineno <EOL> self . colno = colno <EOL> self . value = value <EOL> class IfNode ( ) : <EOL> def __init__ ( self , lineno , colno , condition , block ) : <EOL> self . lineno = lineno <EOL> self . colno = colno <EOL> self . condition = condition <EOL> self . block = block <EOL> class ArgumentNode ( ) : <EOL> def __init__ ( self , token ) : <EOL> self . lineno = token . lineno <EOL> self . colno = token . colno <EOL> self . arguments = [ ] <EOL> self . kwargs = { } <EOL> self . order_error = False <EOL> def prepend ( self , statement ) : <EOL> if self . num_kwargs ( ) > <NUM_LIT:0> : <EOL> self . order_error = True <EOL> if not isinstance ( statement , EmptyNode ) : <EOL> self . arguments = [ statement ] + self . arguments <EOL> def append ( self , statement ) : <EOL> if self . num_kwargs ( ) > <NUM_LIT:0> : <EOL> self . order_error = True <EOL> if not isinstance ( statement , EmptyNode ) : <EOL> self . arguments = self . arguments + [ statement ] <EOL> def set_kwarg ( self , name , value ) : <EOL> self . kwargs [ name ] = value <EOL> def num_args ( self ) : <EOL> return len ( self . arguments ) <EOL> def num_kwargs ( self ) : <EOL> return len ( self . kwargs ) <EOL> def incorrect_order ( self ) : <EOL> return self . order_error <EOL> def __len__ ( self ) : <EOL> return self . num_args ( ) <EOL> comparison_map = { '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT:<>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT:>>' , <EOL> '<STR_LIT>' : '<STR_LIT>' <EOL> } <EOL> class Parser : <EOL> def __init__ ( self , code ) : <EOL> self . stream = Lexer ( ) . lex ( code ) <EOL> self . getsym ( ) <EOL> def getsym ( self ) : <EOL> try : <EOL> self . current = next ( self . stream ) <EOL> except StopIteration : <EOL> self . current = Token ( '<STR_LIT>' , <NUM_LIT:0> , <NUM_LIT:0> , None ) <EOL> def accept ( self , s ) : <EOL> if self . current . tid == s : <EOL> self . getsym ( ) <EOL> return True <EOL> return False <EOL> def expect ( self , s ) : <EOL> if self . accept ( s ) : <EOL> return True <EOL> raise ParseException ( '<STR_LIT>' % ( s , self . current . tid ) , self . current . lineno , self . current . colno ) <EOL> def parse ( self ) : <EOL> block = self . codeblock ( ) <EOL> self . expect ( '<STR_LIT>' ) <EOL> return block <EOL> def statement ( self ) : <EOL> return self . e1 ( ) <EOL> def e1 ( self ) : <EOL> left = self . e2 ( ) <EOL> if self . accept ( '<STR_LIT>' ) : <EOL> value = self . e1 ( ) <EOL> if not isinstance ( left , IdNode ) : <EOL> raise ParseException ( '<STR_LIT>' , left . lineno , left . colno ) <EOL> return PlusAssignmentNode ( left . lineno , left . colno , left . value , value ) <EOL> elif self . accept ( '<STR_LIT>' ) : <EOL> value = self . e1 ( ) <EOL> if not isinstance ( left , IdNode ) : <EOL> raise ParseException ( '<STR_LIT>' , <EOL> left . lineno , left . colno ) <EOL> return AssignmentNode ( left . lineno , left . colno , left . value , value ) <EOL> return left <EOL> def e2 ( self ) : <EOL> left = self . e3 ( ) <EOL> while self . accept ( '<STR_LIT>' ) : <EOL> left = OrNode ( left . lineno , left . colno , left , self . e3 ( ) ) <EOL> return left <EOL> def e3 ( self ) : <EOL> left = self . e4 ( ) <EOL> while self . accept ( '<STR_LIT>' ) : <EOL> left = AndNode ( left . lineno , left . colno , left , self . e4 ( ) ) <EOL> return left <EOL> def e4 ( self ) : <EOL> left = self . e5 ( ) <EOL> for nodename , operator_type in comparison_map . items ( ) : <EOL> if self . accept ( nodename ) : <EOL> return ComparisonNode ( left . lineno , left . colno , operator_type , left , self . e5 ( ) ) <EOL> return left <EOL> def e5 ( self ) : <EOL> return self . e5add ( ) <EOL> def e5add ( self ) : <EOL> left = self . e5sub ( ) <EOL> if self . accept ( '<STR_LIT>' ) : <EOL> return ArithmeticNode ( left . lineno , left . colno , '<STR_LIT>' , left , self . e5add ( ) ) <EOL> return left <EOL> def e5sub ( self ) : <EOL> left = self . e5mul ( ) <EOL> if self . accept ( '<STR_LIT>' ) : <EOL> return ArithmeticNode ( left . lineno , left . colno , '<STR_LIT>' , left , self . e5sub ( ) ) <EOL> return left <EOL> def e5mul ( self ) : <EOL> left = self . e5div ( ) <EOL> if self . accept ( '<STR_LIT>' ) : <EOL> return ArithmeticNode ( left . lineno , left . colno , '<STR_LIT>' , left , self . e5mul ( ) ) <EOL> return left <EOL> def e5div ( self ) : <EOL> left = self . e6 ( ) <EOL> if self . accept ( '<STR_LIT>' ) : <EOL> return ArithmeticNode ( left . lineno , left . colno , '<STR_LIT>' , left , self . e5div ( ) ) <EOL> return left <EOL> def e6 ( self ) : <EOL> if self . accept ( '<STR_LIT>' ) : <EOL> return NotNode ( self . current . lineno , self . current . colno , self . e7 ( ) ) <EOL> if self . accept ( '<STR_LIT>' ) : <EOL> return UMinusNode ( self . current . lineno , self . current . colno , self . e7 ( ) ) <EOL> return self . e7 ( ) <EOL> def e7 ( self ) : <EOL> left = self . e8 ( ) <EOL> if self . accept ( '<STR_LIT>' ) : <EOL> args = self . args ( ) <EOL> self . expect ( '<STR_LIT>' ) <EOL> if not isinstance ( left , IdNode ) : <EOL> raise ParseException ( '<STR_LIT>' , <EOL> left . lineno , left . colno ) <EOL> left = FunctionNode ( left . lineno , left . colno , left . value , args ) <EOL> go_again = True <EOL> while go_again : <EOL> go_again = False <EOL> if self . accept ( '<STR_LIT>' ) : <EOL> go_again = True <EOL> left = self . method_call ( left ) <EOL> if self . accept ( '<STR_LIT>' ) : <EOL> go_again = True <EOL> left = self . index_call ( left ) <EOL> return left <EOL> def e8 ( self ) : <EOL> if self . accept ( '<STR_LIT>' ) : <EOL> e = self . statement ( ) <EOL> self . expect ( '<STR_LIT>' ) <EOL> return e <EOL> elif self . accept ( '<STR_LIT>' ) : <EOL> args = self . args ( ) <EOL> self . expect ( '<STR_LIT>' ) <EOL> return ArrayNode ( args ) <EOL> else : <EOL> return self . e9 ( ) <EOL> def e9 ( self ) : <EOL> t = self . current <EOL> if self . accept ( '<STR_LIT:true>' ) : <EOL> return BooleanNode ( t , True ) ; <EOL> if self . accept ( '<STR_LIT:false>' ) : <EOL> return BooleanNode ( t , False ) <EOL> if self . accept ( '<STR_LIT:id>' ) : <EOL> return IdNode ( t ) <EOL> if self . accept ( '<STR_LIT>' ) : <EOL> return NumberNode ( t ) <EOL> if self . accept ( '<STR_LIT:string>' ) : <EOL> return StringNode ( t ) <EOL> return EmptyNode ( ) <EOL> def args ( self ) : <EOL> s = self . statement ( ) <EOL> a = ArgumentNode ( s ) <EOL> while not isinstance ( s , EmptyNode ) : <EOL> if self . accept ( '<STR_LIT>' ) : <EOL> a . append ( s ) <EOL> elif self . accept ( '<STR_LIT>' ) : <EOL> if not isinstance ( s , IdNode ) : <EOL> raise ParseException ( '<STR_LIT>' , <EOL> s . lineno , s . colno ) <EOL> a . set_kwarg ( s . value , self . statement ( ) ) <EOL> if not self . accept ( '<STR_LIT>' ) : <EOL> return a <EOL> else : <EOL> a . append ( s ) <EOL> return a <EOL> s = self . statement ( ) <EOL> return a <EOL> def method_call ( self , source_object ) : <EOL> methodname = self . e9 ( ) <EOL> if not ( isinstance ( methodname , IdNode ) ) : <EOL> raise ParseException ( '<STR_LIT>' , <EOL> self . current . lineno , self . current . colno ) <EOL> self . expect ( '<STR_LIT>' ) <EOL> args = self . args ( ) <EOL> self . expect ( '<STR_LIT>' ) <EOL> method = MethodNode ( methodname . lineno , methodname . colno , source_object , methodname . value , args ) <EOL> if self . accept ( '<STR_LIT>' ) : <EOL> return self . method_call ( method ) <EOL> return method <EOL> def index_call ( self , source_object ) : <EOL> index_statement = self . statement ( ) <EOL> self . expect ( '<STR_LIT>' ) <EOL> return IndexNode ( source_object , index_statement ) <EOL> def foreachblock ( self ) : <EOL> t = self . current <EOL> self . expect ( '<STR_LIT:id>' ) <EOL> varname = t <EOL> self . expect ( '<STR_LIT>' ) <EOL> items = self . statement ( ) <EOL> block = self . codeblock ( ) <EOL> return ForeachClauseNode ( varname . lineno , varname . colno , varname , items , block ) <EOL> def ifblock ( self ) : <EOL> condition = self . statement ( ) <EOL> clause = IfClauseNode ( condition . lineno , condition . colno ) <EOL> block = self . codeblock ( ) <EOL> clause . ifs . append ( IfNode ( clause . lineno , clause . colno , condition , block ) ) <EOL> self . elseifblock ( clause ) <EOL> clause . elseblock = self . elseblock ( ) <EOL> return clause <EOL> def elseifblock ( self , clause ) : <EOL> while self . accept ( '<STR_LIT>' ) : <EOL> s = self . statement ( ) <EOL> self . expect ( '<STR_LIT>' ) <EOL> b = self . codeblock ( ) <EOL> clause . ifs . append ( IfNode ( s . lineno , s . colno , s , b ) ) <EOL> def elseblock ( self ) : <EOL> if self . accept ( '<STR_LIT>' ) : <EOL> self . expect ( '<STR_LIT>' ) <EOL> return self . codeblock ( ) <EOL> def line ( self ) : <EOL> if self . current == '<STR_LIT>' : <EOL> return EmptyNode ( ) <EOL> if self . accept ( '<STR_LIT>' ) : <EOL> block = self . ifblock ( ) <EOL> self . expect ( '<STR_LIT>' ) <EOL> return block <EOL> if self . accept ( '<STR_LIT>' ) : <EOL> block = self . foreachblock ( ) <EOL> self . expect ( '<STR_LIT>' ) <EOL> return block <EOL> return self . statement ( ) <EOL> def codeblock ( self ) : <EOL> block = CodeBlockNode ( self . current . lineno , self . current . colno ) <EOL> cond = True <EOL> while cond : <EOL> curline = self . line ( ) <EOL> if not isinstance ( curline , EmptyNode ) : <EOL> block . lines . append ( curline ) <EOL> cond = self . accept ( '<STR_LIT>' ) <EOL> return block </s>
