from ply import lex
primitive_types = {
'float' : 'FLOAT' ,
'int' : 'INT' ,
'name' : 'NAME' ,
'bool' : 'BOOL' ,
'string' : 'STRING' ,
'byte' : 'BYTE'
}
function_modifiers = [
'EXEC' ,
'FINAL' ,
'ITERATOR' ,
'LATENT' ,
'NATIVE' ,
'SIMULATED' ,
'SINGULAR' ,
'STATIC'
]
struct_modifers = [
'TRANSIENT'
'EXPORT'
'INIT'
'NATIVE'
]
class_modifiers = {
'abstract' : 'ABSTRACT' ,
'cacheexempt' : 'CACHEEXEMPT' ,
'collapsecategories' : 'COLLAPSECATEGORIES' ,
'config' : 'CONFIG' ,
'dependson' : 'DEPENDSON' ,
'dontcollapsecategories' : 'DONTCOLLAPSECATEGORIES' ,
'editinlinenew' : 'EDITINLINENEW' ,
'exportstructs' : 'EXPORTSTRUCTS' ,
'hidecategories' : 'HIDECATEGORIES' ,
'hidedropdown' : 'HIDEDROPDOWN' ,
'instanced' : 'INSTANCED' ,
'native' : 'NATIVE' ,
'nativereplication' : 'NATIVEREPLICATION' ,
'noexport' : 'NOEXPORT' ,
'nonativereplication' : 'NONATIVEREPLICATION' ,
'noteditinlinenew' : 'NOTEDITINLINENEW' ,
'notplaceable' : 'NOTPLACEABLE' ,
'parseconfig' : 'PARSECONFIG' ,
'perobjectconfig' : 'PEROBJECTCONFIG' ,
'placeable' : 'PLACEABLE' ,
'safereplace' : 'SAFEREPLACE' ,
'showcategories' : 'SHOWCATEGORIES' ,
'transient' : 'TRANSIENT' ,
'within' : 'WITHIN' ,
'template' : 'TEMPLATE'
}
access_modifiers = {
'private' : 'PRIVATE' ,
'protected' : 'PROTECTED'
}
function_parameter_modifiers = {
'skip' : 'SKIP' ,
'out' : 'OUT' ,
'optional' : 'OPTIONAL' ,
'coerce' : 'COERCE'
}
variable_modifiers = {
'automated' : 'AUTOMATED' ,
'cache' : 'CACHE' ,
'config' : 'CONFIG' ,
'const' : 'CONST' ,
'deprecated' : 'DEPRECATED' ,
'edfindable' : 'EDFINDABLE' ,
'editconst' : 'EDITCONST' ,
'editconstarray' : 'EDITCONSTARRAY' ,
'editinline' : 'EDITINLINE' ,
'editinlinenotify' : 'EDITINLINENOTIFY' ,
'editinlineuse' : 'EDITINLINEUSE' ,
'export' : 'EXPORT' ,
'noexport' : 'NOEXPORT' ,
'globalconfig' : 'GLOBALCONFIG' ,
'input' : 'INPUT' ,
'localized' : 'LOCALIZED' ,
'native' : 'NATIVE' ,
'private' : 'PRIVATE' ,
'protected' : 'PROTECTED' ,
'transient' : 'TRANSIENT' ,
'travel' : 'TRAVEL' ,
}
reserved = {
'always' : 'ALWAYS' ,
'array' : 'ARRAY' ,
'arraycount' : 'ARRAYCOUNT' ,
'assert' : 'ASSERT' ,
'auto' : 'AUTO' ,
'automated' : 'AUTOMATED' ,
'begin' : 'BEGIN' ,
'bool' : 'BOOL' ,
'break' : 'BREAK' ,
'button' : 'BUTTON' ,
'byte' : 'BYTE' ,
'case' : 'CASE' ,
'class' : 'CLASS' ,
'coerce' : 'COERCE' ,
'collapsecategories' : 'COLLAPSECATEGORIES' ,
'continue' : 'CONTINUE' ,
'default' : 'DEFAULT' ,
'defaultproperties' : 'DEFAULTPROPERTIES' ,
'delegate' : 'DELEGATE' ,
'do' : 'DO' ,
'editinlinenotify' : 'EDITINLINENOTIFY' ,
'editinlineuse' : 'EDITINLINEUSE' ,
'else' : 'ELSE' ,
'end' : 'END' ,
'enum' : 'ENUM' ,
'enumcount' : 'ENUMCOUNT' ,
'event' : 'EVENT' ,
'exec' : 'EXEC' ,
'expands' : 'EXPANDS' ,
'extends' : 'EXTENDS' ,
'false' : 'FALSE' ,
'final' : 'FINAL' ,
'float' : 'FLOAT' ,
'for' : 'FOR' ,
'foreach' : 'FOREACH' ,
'function' : 'FUNCTION' ,
'global' : 'GLOBAL' ,
'globalconfig' : 'GLOBALCONFIG' ,
'goto' : 'GOTO' ,
'if' : 'IF' ,
'ignores' : 'IGNORES' ,
'import' : 'IMPORT' ,
'init' : 'INIT' ,
'input' : 'INPUT' ,
#'insert': 'INSERT',
'int' : 'INT' ,
'intrinsic' : 'INTRINSIC' ,
'invariant' : 'INVARIANT' ,
'iterator' : 'ITERATOR' ,
'latent' : 'LATENT' ,
'local' : 'LOCAL' ,
'localized' : 'LOCALIZED' ,
'name' : 'NAME' ,
'new' : 'NEW' ,
'none' : 'NONE' ,
'nousercreate' : 'NOUSERCREATE' ,
'operator' : 'OPERATOR' ,
'optional' : 'OPTIONAL' ,
'out' : 'OUT' ,
'postoperator' : 'POSTOPERATOR' ,
'preoperator' : 'PREOPERATOR' ,
'reliable' : 'RELIABLE' ,
#'remove': 'REMOVE',
'replication' : 'REPLICATION' ,
'return' : 'RETURN' ,
'rng' : 'RNG' ,
'rot' : 'ROT' ,
'self' : 'SELF' ,
'simulated' : 'SIMULATED' ,
'singular' : 'SINGULAR' ,
'skip' : 'SKIP' ,
'state' : 'STATE' ,
'static' : 'STATIC' ,
'stop' : 'STOP' ,
'string' : 'STRING' ,
'struct' : 'STRUCT' ,
'super' : 'SUPER' ,
'switch' : 'SWITCH' ,
'true' : 'TRUE' ,
'unreliable' : 'UNRELIABLE' ,
'until' : 'UNTIL' ,
'var' : 'VAR' ,
'vect' : 'VECT' ,
'while' : 'WHILE' ,
# the following are keywords added by ulex
'typeof' : 'TYPEOF' ,
'sizeof' : 'SIZEOF' ,
'typedef' : 'TYPEDEF'
}
reserved.update ( class_modifiers)
reserved.update ( variable_modifiers)
tokens = [
'COMMENT' ,
'UNAME' ,
'INTEGER' ,
'HEX' ,
'SEMICOLON' ,
'LPAREN' ,
'RPAREN' ,
'LSQUARE' ,
'RSQUARE' ,
'LANGLE' ,
'RANGLE' ,
'LCURLY' ,
'RCURLY' ,
'ASSIGN' ,
'COMMA' ,
'PERIOD' ,
'LQUOTE' ,
'RQUOTE' ,
'USTRING' ,
'UFLOAT' ,
'EQUAL' ,
'NEQUAL' ,
'OR' ,
'NOT' ,
'INCREMENT' ,
'ADD' ,
'MULTIPLY' ,
'AND' ,
'MINUS' ,
'COLON' ,
'SEQUAL' ,
'MODULUS' ,
'SCONCAT' ,
'SCONCATSPACE' ,
'DIVIDE' ,
'REFERENCE' ,
'DIRECTIVE' ,
'AMPERSAND' ,
'BITWISE_AND' ,
'BITWISE_OR' ,
'LEFT_SHIFT' ,
'RIGHT_SHIFT' ,
'XOR' ,
'BITWISE_NOT' ,
'ID' ,
'LEQUAL' ,
'GEQUAL' ,
'IASSIGN' ,
'DASSIGN'
] + list ( reserved.values ( ) )
t_LPAREN = r'\( '
t_RPAREN = r'\) '
t_LSQUARE = r'\[ '
t_RSQUARE = r'\] '
t_LANGLE = r'\< '
t_RANGLE = r'\> '
t_LCURLY = r'\{ '
t_RCURLY = r'\} '
t_LQUOTE = r'\" '
t_RQUOTE = r'\" '
t_ignore = '\r \t '
t_SEMICOLON = r'\; '
t_ASSIGN = r'\= '
t_COMMA = r','
t_PERIOD = '\. '
t_EQUAL = r'=='
t_NEQUAL = r'!='
t_OR = r'\| \| '
t_NOT = r'!'
t_INCREMENT = r'\+ \+ '
t_ADD = r'\+ '
t_MULTIPLY = r'\* '
t_AND = r'\& \& '
t_MINUS = r'-'
t_COLON = r':'
t_SEQUAL = r'~='
t_MODULUS = r'%'
t_SCONCAT = r'\$ '
t_SCONCATSPACE = r'@'
t_DIVIDE = r'/'
t_BITWISE_AND = r'\& '
t_BITWISE_OR = r'\| '
t_LEFT_SHIFT = r'<<'
t_RIGHT_SHIFT = r'>>'
t_XOR = r'\^ '
t_BITWISE_NOT = r'~'
t_LEQUAL = r'\< \= '
t_GEQUAL = r'>='
t_IASSIGN = r'\+ ='
t_DASSIGN = r'-='
def t_DIRECTIVE( t) :
r'\# (\w +)\s +(.+)'
def t_REFERENCE( t) :
r'([a-zA-Z0-9_\- ]+)\s *\' ([a-zA-Z0-9_\- \. ]+)\' '
return t
def t_UNAME( t) :
r'\' ([a-zA-Z0-9_\- ]*)\' '
return t
def t_USTRING( t) :
r'"((\\ {2})*|(.*?[^\\ ](\\ {2})*))"'
return t
def t_UFLOAT( t) :
r'[-+]?\d *?[.]\d +'
t.value = float ( t.value )
return t
def t_HEX( t) :
r'0[xX][0-9a-fA-F]+'
t.type = 'INTEGER'
t.value = int ( t.value , 0 )
return t
def t_INTEGER( t) :
r'[-+]?\d +'
t.value = int ( t.value )
return t
def t_COMMENT( t) :
r'(/\* ([^*]|[\r \n ]|(\* +([^*/]|[\r \n ])))*\* +/)|(//.*)'
def t_ID( t) :
r'[a-zA-Z_][a-zA-Z_0-9]*'
t.type = reserved.get ( t.value .lower ( ) , 'ID' )
return t
def t_newline( t) :
r'\n +'
t.lexer .lineno += len ( t.value )
def t_error( t) :
pass
lexer = lex.lex ( )
ZnJvbSBwbHkgaW1wb3J0IGxleAoKcHJpbWl0aXZlX3R5cGVzID0gewogICAgJ2Zsb2F0JzogJ0ZMT0FUJywKICAgICdpbnQnOiAnSU5UJywKICAgICduYW1lJzogJ05BTUUnLAogICAgJ2Jvb2wnOiAnQk9PTCcsCiAgICAnc3RyaW5nJzogJ1NUUklORycsCiAgICAnYnl0ZSc6ICdCWVRFJwp9CgpmdW5jdGlvbl9tb2RpZmllcnMgPSBbCiAgICAnRVhFQycsCiAgICAnRklOQUwnLAogICAgJ0lURVJBVE9SJywKICAgICdMQVRFTlQnLAogICAgJ05BVElWRScsCiAgICAnU0lNVUxBVEVEJywKICAgICdTSU5HVUxBUicsCiAgICAnU1RBVElDJwpdCgpzdHJ1Y3RfbW9kaWZlcnMgPSBbCiAgICAnVFJBTlNJRU5UJwogICAgJ0VYUE9SVCcKICAgICdJTklUJwogICAgJ05BVElWRScKXQoKY2xhc3NfbW9kaWZpZXJzID0gewogICAgJ2Fic3RyYWN0JzogJ0FCU1RSQUNUJywKICAgICdjYWNoZWV4ZW1wdCc6ICdDQUNIRUVYRU1QVCcsCiAgICAnY29sbGFwc2VjYXRlZ29yaWVzJzogJ0NPTExBUFNFQ0FURUdPUklFUycsCiAgICAnY29uZmlnJzogJ0NPTkZJRycsCiAgICAnZGVwZW5kc29uJzogJ0RFUEVORFNPTicsCiAgICAnZG9udGNvbGxhcHNlY2F0ZWdvcmllcyc6ICdET05UQ09MTEFQU0VDQVRFR09SSUVTJywKICAgICdlZGl0aW5saW5lbmV3JzogJ0VESVRJTkxJTkVORVcnLAogICAgJ2V4cG9ydHN0cnVjdHMnOiAnRVhQT1JUU1RSVUNUUycsCiAgICAnaGlkZWNhdGVnb3JpZXMnOiAnSElERUNBVEVHT1JJRVMnLAogICAgJ2hpZGVkcm9wZG93bic6ICdISURFRFJPUERPV04nLAogICAgJ2luc3RhbmNlZCc6ICdJTlNUQU5DRUQnLAogICAgJ25hdGl2ZSc6ICdOQVRJVkUnLAogICAgJ25hdGl2ZXJlcGxpY2F0aW9uJzogJ05BVElWRVJFUExJQ0FUSU9OJywKICAgICdub2V4cG9ydCc6ICdOT0VYUE9SVCcsCiAgICAnbm9uYXRpdmVyZXBsaWNhdGlvbic6ICdOT05BVElWRVJFUExJQ0FUSU9OJywKICAgICdub3RlZGl0aW5saW5lbmV3JzogJ05PVEVESVRJTkxJTkVORVcnLAogICAgJ25vdHBsYWNlYWJsZSc6ICdOT1RQTEFDRUFCTEUnLAogICAgJ3BhcnNlY29uZmlnJzogJ1BBUlNFQ09ORklHJywKICAgICdwZXJvYmplY3Rjb25maWcnOiAnUEVST0JKRUNUQ09ORklHJywKICAgICdwbGFjZWFibGUnOiAnUExBQ0VBQkxFJywKICAgICdzYWZlcmVwbGFjZSc6ICdTQUZFUkVQTEFDRScsCiAgICAnc2hvd2NhdGVnb3JpZXMnOiAnU0hPV0NBVEVHT1JJRVMnLAogICAgJ3RyYW5zaWVudCc6ICdUUkFOU0lFTlQnLAogICAgJ3dpdGhpbic6ICdXSVRISU4nLAogICAgJ3RlbXBsYXRlJzogJ1RFTVBMQVRFJwp9CgphY2Nlc3NfbW9kaWZpZXJzID0gewogICAgJ3ByaXZhdGUnOiAnUFJJVkFURScsCiAgICAncHJvdGVjdGVkJzogJ1BST1RFQ1RFRCcKfQoKZnVuY3Rpb25fcGFyYW1ldGVyX21vZGlmaWVycyA9IHsKICAgICdza2lwJzogJ1NLSVAnLAogICAgJ291dCc6ICdPVVQnLAogICAgJ29wdGlvbmFsJzogJ09QVElPTkFMJywKICAgICdjb2VyY2UnOiAnQ09FUkNFJwp9Cgp2YXJpYWJsZV9tb2RpZmllcnMgPSB7CiAgICAnYXV0b21hdGVkJzogJ0FVVE9NQVRFRCcsCiAgICAnY2FjaGUnOiAnQ0FDSEUnLAogICAgJ2NvbmZpZyc6ICdDT05GSUcnLAogICAgJ2NvbnN0JzogJ0NPTlNUJywKICAgICdkZXByZWNhdGVkJzogJ0RFUFJFQ0FURUQnLAogICAgJ2VkZmluZGFibGUnOiAnRURGSU5EQUJMRScsCiAgICAnZWRpdGNvbnN0JzogJ0VESVRDT05TVCcsCiAgICAnZWRpdGNvbnN0YXJyYXknOiAnRURJVENPTlNUQVJSQVknLAogICAgJ2VkaXRpbmxpbmUnOiAnRURJVElOTElORScsCiAgICAnZWRpdGlubGluZW5vdGlmeSc6ICdFRElUSU5MSU5FTk9USUZZJywKICAgICdlZGl0aW5saW5ldXNlJzogJ0VESVRJTkxJTkVVU0UnLAogICAgJ2V4cG9ydCc6ICdFWFBPUlQnLAogICAgJ25vZXhwb3J0JzogJ05PRVhQT1JUJywKICAgICdnbG9iYWxjb25maWcnOiAnR0xPQkFMQ09ORklHJywKICAgICdpbnB1dCc6ICdJTlBVVCcsCiAgICAnbG9jYWxpemVkJzogJ0xPQ0FMSVpFRCcsCiAgICAnbmF0aXZlJzogJ05BVElWRScsCiAgICAncHJpdmF0ZSc6ICdQUklWQVRFJywKICAgICdwcm90ZWN0ZWQnOiAnUFJPVEVDVEVEJywKICAgICd0cmFuc2llbnQnOiAnVFJBTlNJRU5UJywKICAgICd0cmF2ZWwnOiAnVFJBVkVMJywKfQoKcmVzZXJ2ZWQgPSB7CiAgICAnYWx3YXlzJzogJ0FMV0FZUycsCiAgICAnYXJyYXknOiAnQVJSQVknLAogICAgJ2FycmF5Y291bnQnOiAnQVJSQVlDT1VOVCcsCiAgICAnYXNzZXJ0JzogJ0FTU0VSVCcsCiAgICAnYXV0byc6ICdBVVRPJywKICAgICdhdXRvbWF0ZWQnOiAnQVVUT01BVEVEJywKICAgICdiZWdpbic6ICdCRUdJTicsCiAgICAnYm9vbCc6ICdCT09MJywKICAgICdicmVhayc6ICdCUkVBSycsCiAgICAnYnV0dG9uJzogJ0JVVFRPTicsCiAgICAnYnl0ZSc6ICdCWVRFJywKICAgICdjYXNlJzogJ0NBU0UnLAogICAgJ2NsYXNzJzogJ0NMQVNTJywKICAgICdjb2VyY2UnOiAnQ09FUkNFJywKICAgICdjb2xsYXBzZWNhdGVnb3JpZXMnOiAnQ09MTEFQU0VDQVRFR09SSUVTJywKICAgICdjb250aW51ZSc6ICdDT05USU5VRScsCiAgICAnZGVmYXVsdCc6ICdERUZBVUxUJywKICAgICdkZWZhdWx0cHJvcGVydGllcyc6ICdERUZBVUxUUFJPUEVSVElFUycsCiAgICAnZGVsZWdhdGUnOiAnREVMRUdBVEUnLAogICAgJ2RvJzogJ0RPJywKICAgICdlZGl0aW5saW5lbm90aWZ5JzogJ0VESVRJTkxJTkVOT1RJRlknLAogICAgJ2VkaXRpbmxpbmV1c2UnOiAnRURJVElOTElORVVTRScsCiAgICAnZWxzZSc6ICdFTFNFJywKICAgICdlbmQnOiAnRU5EJywKICAgICdlbnVtJzogJ0VOVU0nLAogICAgJ2VudW1jb3VudCc6ICdFTlVNQ09VTlQnLAogICAgJ2V2ZW50JzogJ0VWRU5UJywKICAgICdleGVjJzogJ0VYRUMnLAogICAgJ2V4cGFuZHMnOiAnRVhQQU5EUycsCiAgICAnZXh0ZW5kcyc6ICdFWFRFTkRTJywKICAgICdmYWxzZSc6ICdGQUxTRScsCiAgICAnZmluYWwnOiAnRklOQUwnLAogICAgJ2Zsb2F0JzogJ0ZMT0FUJywKICAgICdmb3InOiAnRk9SJywKICAgICdmb3JlYWNoJzogJ0ZPUkVBQ0gnLAogICAgJ2Z1bmN0aW9uJzogJ0ZVTkNUSU9OJywKICAgICdnbG9iYWwnOiAnR0xPQkFMJywKICAgICdnbG9iYWxjb25maWcnOiAnR0xPQkFMQ09ORklHJywKICAgICdnb3RvJzogJ0dPVE8nLAogICAgJ2lmJzogJ0lGJywKICAgICdpZ25vcmVzJzogJ0lHTk9SRVMnLAogICAgJ2ltcG9ydCc6ICdJTVBPUlQnLAogICAgJ2luaXQnOiAnSU5JVCcsCiAgICAnaW5wdXQnOiAnSU5QVVQnLAogICAgIydpbnNlcnQnOiAnSU5TRVJUJywKICAgICdpbnQnOiAnSU5UJywKICAgICdpbnRyaW5zaWMnOiAnSU5UUklOU0lDJywKICAgICdpbnZhcmlhbnQnOiAnSU5WQVJJQU5UJywKICAgICdpdGVyYXRvcic6ICdJVEVSQVRPUicsCiAgICAnbGF0ZW50JzogJ0xBVEVOVCcsCiAgICAnbG9jYWwnOiAnTE9DQUwnLAogICAgJ2xvY2FsaXplZCc6ICdMT0NBTElaRUQnLAogICAgJ25hbWUnOiAnTkFNRScsCiAgICAnbmV3JzogJ05FVycsCiAgICAnbm9uZSc6ICdOT05FJywKICAgICdub3VzZXJjcmVhdGUnOiAnTk9VU0VSQ1JFQVRFJywKICAgICdvcGVyYXRvcic6ICdPUEVSQVRPUicsCiAgICAnb3B0aW9uYWwnOiAnT1BUSU9OQUwnLAogICAgJ291dCc6ICdPVVQnLAogICAgJ3Bvc3RvcGVyYXRvcic6ICdQT1NUT1BFUkFUT1InLAogICAgJ3ByZW9wZXJhdG9yJzogJ1BSRU9QRVJBVE9SJywKICAgICdyZWxpYWJsZSc6ICdSRUxJQUJMRScsCiAgICAjJ3JlbW92ZSc6ICdSRU1PVkUnLAogICAgJ3JlcGxpY2F0aW9uJzogJ1JFUExJQ0FUSU9OJywKICAgICdyZXR1cm4nOiAnUkVUVVJOJywKICAgICdybmcnOiAnUk5HJywKICAgICdyb3QnOiAnUk9UJywKICAgICdzZWxmJzogJ1NFTEYnLAogICAgJ3NpbXVsYXRlZCc6ICdTSU1VTEFURUQnLAogICAgJ3Npbmd1bGFyJzogJ1NJTkdVTEFSJywKICAgICdza2lwJzogJ1NLSVAnLAogICAgJ3N0YXRlJzogJ1NUQVRFJywKICAgICdzdGF0aWMnOiAnU1RBVElDJywKICAgICdzdG9wJzogJ1NUT1AnLAogICAgJ3N0cmluZyc6ICdTVFJJTkcnLAogICAgJ3N0cnVjdCc6ICdTVFJVQ1QnLAogICAgJ3N1cGVyJzogJ1NVUEVSJywKICAgICdzd2l0Y2gnOiAnU1dJVENIJywKICAgICd0cnVlJzogJ1RSVUUnLAogICAgJ3VucmVsaWFibGUnOiAnVU5SRUxJQUJMRScsCiAgICAndW50aWwnOiAnVU5USUwnLAogICAgJ3Zhcic6ICdWQVInLAogICAgJ3ZlY3QnOiAnVkVDVCcsCiAgICAnd2hpbGUnOiAnV0hJTEUnLAogICAgIyB0aGUgZm9sbG93aW5nIGFyZSBrZXl3b3JkcyBhZGRlZCBieSB1bGV4CiAgICAndHlwZW9mJzogJ1RZUEVPRicsCiAgICAnc2l6ZW9mJzogJ1NJWkVPRicsCiAgICAndHlwZWRlZic6ICdUWVBFREVGJwp9CgpyZXNlcnZlZC51cGRhdGUoY2xhc3NfbW9kaWZpZXJzKQpyZXNlcnZlZC51cGRhdGUodmFyaWFibGVfbW9kaWZpZXJzKQoKdG9rZW5zID0gWwogICAgJ0NPTU1FTlQnLAogICAgJ1VOQU1FJywKICAgICdJTlRFR0VSJywKICAgICdIRVgnLAogICAgJ1NFTUlDT0xPTicsCiAgICAnTFBBUkVOJywKICAgICdSUEFSRU4nLAogICAgJ0xTUVVBUkUnLAogICAgJ1JTUVVBUkUnLAogICAgJ0xBTkdMRScsCiAgICAnUkFOR0xFJywKICAgICdMQ1VSTFknLAogICAgJ1JDVVJMWScsCiAgICAnQVNTSUdOJywKICAgICdDT01NQScsCiAgICAnUEVSSU9EJywKICAgICdMUVVPVEUnLAogICAgJ1JRVU9URScsCiAgICAnVVNUUklORycsCiAgICAnVUZMT0FUJywKICAgICdFUVVBTCcsCiAgICAnTkVRVUFMJywKICAgICdPUicsCiAgICAnTk9UJywKICAgICdJTkNSRU1FTlQnLAogICAgJ0FERCcsCiAgICAnTVVMVElQTFknLAogICAgJ0FORCcsCiAgICAnTUlOVVMnLAogICAgJ0NPTE9OJywKICAgICdTRVFVQUwnLAogICAgJ01PRFVMVVMnLAogICAgJ1NDT05DQVQnLAogICAgJ1NDT05DQVRTUEFDRScsCiAgICAnRElWSURFJywKICAgICdSRUZFUkVOQ0UnLAogICAgJ0RJUkVDVElWRScsCiAgICAnQU1QRVJTQU5EJywKICAgICdCSVRXSVNFX0FORCcsCiAgICAnQklUV0lTRV9PUicsCiAgICAnTEVGVF9TSElGVCcsCiAgICAnUklHSFRfU0hJRlQnLAogICAgJ1hPUicsCiAgICAnQklUV0lTRV9OT1QnLAogICAgJ0lEJywKICAgICdMRVFVQUwnLAogICAgJ0dFUVVBTCcsCiAgICAnSUFTU0lHTicsCiAgICAnREFTU0lHTicKICAgIF0gKyBsaXN0KHJlc2VydmVkLnZhbHVlcygpKQoKdF9MUEFSRU4gPSByJ1woJwp0X1JQQVJFTiA9IHInXCknCnRfTFNRVUFSRSA9IHInXFsnCnRfUlNRVUFSRSA9IHInXF0nCnRfTEFOR0xFID0gcidcPCcKdF9SQU5HTEUgPSByJ1w+Jwp0X0xDVVJMWSA9IHInXHsnCnRfUkNVUkxZID0gcidcfScKdF9MUVVPVEUgPSByJ1wiJwp0X1JRVU9URSA9IHInXCInCnRfaWdub3JlID0gJ1xyXHQgJwp0X1NFTUlDT0xPTiA9IHInXDsnCnRfQVNTSUdOID0gcidcPScKdF9DT01NQSA9IHInLCcKdF9QRVJJT0QgPSAnXC4nCnRfRVFVQUwgPSByJz09Jwp0X05FUVVBTCA9IHInIT0nCnRfT1IgPSByJ1x8XHwnCnRfTk9UID0gcichJwp0X0lOQ1JFTUVOVCA9IHInXCtcKycKdF9BREQgPSByJ1wrJwp0X01VTFRJUExZID0gcidcKicKdF9BTkQgPSByJ1wmXCYnCnRfTUlOVVMgPSByJy0nCnRfQ09MT04gPSByJzonCnRfU0VRVUFMID0gcid+PScKdF9NT0RVTFVTID0gciclJwp0X1NDT05DQVQgPSByJ1wkJwp0X1NDT05DQVRTUEFDRSA9IHInQCcKdF9ESVZJREUgPSByJy8nCnRfQklUV0lTRV9BTkQgPSByJ1wmJwp0X0JJVFdJU0VfT1IgPSByJ1x8Jwp0X0xFRlRfU0hJRlQgPSByJzw8Jwp0X1JJR0hUX1NISUZUID0gcic+PicKdF9YT1IgPSByJ1xeJwp0X0JJVFdJU0VfTk9UID0gcid+Jwp0X0xFUVVBTCA9IHInXDxcPScKdF9HRVFVQUwgPSByJz49Jwp0X0lBU1NJR04gPSByJ1wrPScKdF9EQVNTSUdOID0gcictPScKCgpkZWYgdF9ESVJFQ1RJVkUodCk6CiAgICByJ1wjKFx3KylccysoLispJwoKCmRlZiB0X1JFRkVSRU5DRSh0KToKICAgIHInKFthLXpBLVowLTlfXC1dKylccypcJyhbYS16QS1aMC05X1wtXC5dKylcJycKICAgIHJldHVybiB0CgoKZGVmIHRfVU5BTUUodCk6CiAgICByJ1wnKFthLXpBLVowLTlfXC0gXSopXCcnCiAgICByZXR1cm4gdAoKCmRlZiB0X1VTVFJJTkcodCk6CiAgICByJyIoKFxcezJ9KSp8KC4qP1teXFxdKFxcezJ9KSopKSInCiAgICByZXR1cm4gdAoKCmRlZiB0X1VGTE9BVCh0KToKICAgIHInWy0rXT9cZCo/Wy5dXGQrJwogICAgdC52YWx1ZSA9IGZsb2F0KHQudmFsdWUpCiAgICByZXR1cm4gdAoKCmRlZiB0X0hFWCh0KToKICAgIHInMFt4WF1bMC05YS1mQS1GXSsnCiAgICB0LnR5cGUgPSAnSU5URUdFUicKICAgIHQudmFsdWUgPSBpbnQodC52YWx1ZSwgMCkKICAgIHJldHVybiB0CgoKZGVmIHRfSU5URUdFUih0KToKICAgIHInWy0rXT9cZCsnCiAgICB0LnZhbHVlID0gaW50KHQudmFsdWUpCiAgICByZXR1cm4gdAoKCmRlZiB0X0NPTU1FTlQodCk6CiAgICByJygvXCooW14qXXxbXHJcbl18KFwqKyhbXiovXXxbXHJcbl0pKSkqXCorLyl8KC8vLiopJwoKCmRlZiB0X0lEKHQpOgogICAgcidbYS16QS1aX11bYS16QS1aXzAtOV0qJwogICAgdC50eXBlID0gcmVzZXJ2ZWQuZ2V0KHQudmFsdWUubG93ZXIoKSwgJ0lEJykKICAgIHJldHVybiB0CgoKZGVmIHRfbmV3bGluZSh0KToKICAgIHInXG4rJwogICAgdC5sZXhlci5saW5lbm8gKz0gbGVuKHQudmFsdWUpCgoKZGVmIHRfZXJyb3IodCk6CiAgICBwYXNzCgpsZXhlciA9IGxleC5sZXgoKQo=