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+(.+)'
t_DIRECTIVE.__doc__ = r'\#(\w+)\s+(.+)'
def t_REFERENCE(t):
r'([a-zA-Z0-9_\-]+)\s*\'([a-zA-Z0-9_\-\.]+)\''
return t
t_REFERENCE.__doc__ = r'([a-zA-Z0-9_\-]+)\s*\'([a-zA-Z0-9_\-\.]+)\''
def t_UNAME(t):
r'\'([a-zA-Z0-9_\- ]*)\''
return t
t_UNAME.__doc__ = r'\'([a-zA-Z0-9_\- ]*)\''
def t_USTRING(t):
r'"((\\{2})*|(.*?[^\\](\\{2})*))"'
return t
t_USTRING.__doc__ = r'"((\\{2})*|(.*?[^\\](\\{2})*))"'
def t_UFLOAT(t):
r'[-+]?\d*?[.]\d+'
t.value = float(t.value)
return t
t_UFLOAT.__doc__ = r'[-+]?\d*?[.]\d+'
def t_HEX(t):
r'0[xX][0-9a-fA-F]+'
t.type = 'INTEGER'
t.value = int(t.value, 0)
return t
t_HEX.__doc__ = r'0[xX][0-9a-fA-F]+'
def t_INTEGER(t):
r'[-+]?\d+'
t.value = int(t.value)
return t
t_INTEGER.__doc__ = r'[-+]?\d+'
def t_COMMENT(t):
r'(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/)|(//.*)'
t_COMMENT.__doc__ = 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
t_ID.__doc__ = r'[a-zA-Z_][a-zA-Z_0-9]*'
def t_newline(t):
r'\n+'
t.lexer.lineno += len(t.value)
t_newline.__doc__ = r'\n+'
def t_error(t):
pass
lexer = lex.lex()
ZnJvbSBwbHkgaW1wb3J0IGxleAoKcHJpbWl0aXZlX3R5cGVzID0gewogICAgJ2Zsb2F0JzogJ0ZMT0FUJywKICAgICdpbnQnOiAnSU5UJywKICAgICduYW1lJzogJ05BTUUnLAogICAgJ2Jvb2wnOiAnQk9PTCcsCiAgICAnc3RyaW5nJzogJ1NUUklORycsCiAgICAnYnl0ZSc6ICdCWVRFJwp9CgpmdW5jdGlvbl9tb2RpZmllcnMgPSBbCiAgICAnRVhFQycsCiAgICAnRklOQUwnLAogICAgJ0lURVJBVE9SJywKICAgICdMQVRFTlQnLAogICAgJ05BVElWRScsCiAgICAnU0lNVUxBVEVEJywKICAgICdTSU5HVUxBUicsCiAgICAnU1RBVElDJwpdCgpzdHJ1Y3RfbW9kaWZlcnMgPSBbCiAgICAnVFJBTlNJRU5UJwogICAgJ0VYUE9SVCcKICAgICdJTklUJwogICAgJ05BVElWRScKXQoKY2xhc3NfbW9kaWZpZXJzID0gewogICAgJ2Fic3RyYWN0JzogJ0FCU1RSQUNUJywKICAgICdjYWNoZWV4ZW1wdCc6ICdDQUNIRUVYRU1QVCcsCiAgICAnY29sbGFwc2VjYXRlZ29yaWVzJzogJ0NPTExBUFNFQ0FURUdPUklFUycsCiAgICAnY29uZmlnJzogJ0NPTkZJRycsCiAgICAnZGVwZW5kc29uJzogJ0RFUEVORFNPTicsCiAgICAnZG9udGNvbGxhcHNlY2F0ZWdvcmllcyc6ICdET05UQ09MTEFQU0VDQVRFR09SSUVTJywKICAgICdlZGl0aW5saW5lbmV3JzogJ0VESVRJTkxJTkVORVcnLAogICAgJ2V4cG9ydHN0cnVjdHMnOiAnRVhQT1JUU1RSVUNUUycsCiAgICAnaGlkZWNhdGVnb3JpZXMnOiAnSElERUNBVEVHT1JJRVMnLAogICAgJ2hpZGVkcm9wZG93bic6ICdISURFRFJPUERPV04nLAogICAgJ2luc3RhbmNlZCc6ICdJTlNUQU5DRUQnLAogICAgJ25hdGl2ZSc6ICdOQVRJVkUnLAogICAgJ25hdGl2ZXJlcGxpY2F0aW9uJzogJ05BVElWRVJFUExJQ0FUSU9OJywKICAgICdub2V4cG9ydCc6ICdOT0VYUE9SVCcsCiAgICAnbm9uYXRpdmVyZXBsaWNhdGlvbic6ICdOT05BVElWRVJFUExJQ0FUSU9OJywKICAgICdub3RlZGl0aW5saW5lbmV3JzogJ05PVEVESVRJTkxJTkVORVcnLAogICAgJ25vdHBsYWNlYWJsZSc6ICdOT1RQTEFDRUFCTEUnLAogICAgJ3BhcnNlY29uZmlnJzogJ1BBUlNFQ09ORklHJywKICAgICdwZXJvYmplY3Rjb25maWcnOiAnUEVST0JKRUNUQ09ORklHJywKICAgICdwbGFjZWFibGUnOiAnUExBQ0VBQkxFJywKICAgICdzYWZlcmVwbGFjZSc6ICdTQUZFUkVQTEFDRScsCiAgICAnc2hvd2NhdGVnb3JpZXMnOiAnU0hPV0NBVEVHT1JJRVMnLAogICAgJ3RyYW5zaWVudCc6ICdUUkFOU0lFTlQnLAogICAgJ3dpdGhpbic6ICdXSVRISU4nLAogICAgJ3RlbXBsYXRlJzogJ1RFTVBMQVRFJwp9CgphY2Nlc3NfbW9kaWZpZXJzID0gewogICAgJ3ByaXZhdGUnOiAnUFJJVkFURScsCiAgICAncHJvdGVjdGVkJzogJ1BST1RFQ1RFRCcKfQoKZnVuY3Rpb25fcGFyYW1ldGVyX21vZGlmaWVycyA9IHsKICAgICdza2lwJzogJ1NLSVAnLAogICAgJ291dCc6ICdPVVQnLAogICAgJ29wdGlvbmFsJzogJ09QVElPTkFMJywKICAgICdjb2VyY2UnOiAnQ09FUkNFJwp9Cgp2YXJpYWJsZV9tb2RpZmllcnMgPSB7CiAgICAnYXV0b21hdGVkJzogJ0FVVE9NQVRFRCcsCiAgICAnY2FjaGUnOiAnQ0FDSEUnLAogICAgJ2NvbmZpZyc6ICdDT05GSUcnLAogICAgJ2NvbnN0JzogJ0NPTlNUJywKICAgICdkZXByZWNhdGVkJzogJ0RFUFJFQ0FURUQnLAogICAgJ2VkZmluZGFibGUnOiAnRURGSU5EQUJMRScsCiAgICAnZWRpdGNvbnN0JzogJ0VESVRDT05TVCcsCiAgICAnZWRpdGNvbnN0YXJyYXknOiAnRURJVENPTlNUQVJSQVknLAogICAgJ2VkaXRpbmxpbmUnOiAnRURJVElOTElORScsCiAgICAnZWRpdGlubGluZW5vdGlmeSc6ICdFRElUSU5MSU5FTk9USUZZJywKICAgICdlZGl0aW5saW5ldXNlJzogJ0VESVRJTkxJTkVVU0UnLAogICAgJ2V4cG9ydCc6ICdFWFBPUlQnLAogICAgJ25vZXhwb3J0JzogJ05PRVhQT1JUJywKICAgICdnbG9iYWxjb25maWcnOiAnR0xPQkFMQ09ORklHJywKICAgICdpbnB1dCc6ICdJTlBVVCcsCiAgICAnbG9jYWxpemVkJzogJ0xPQ0FMSVpFRCcsCiAgICAnbmF0aXZlJzogJ05BVElWRScsCiAgICAncHJpdmF0ZSc6ICdQUklWQVRFJywKICAgICdwcm90ZWN0ZWQnOiAnUFJPVEVDVEVEJywKICAgICd0cmFuc2llbnQnOiAnVFJBTlNJRU5UJywKICAgICd0cmF2ZWwnOiAnVFJBVkVMJywKfQoKcmVzZXJ2ZWQgPSB7CiAgICAnYWx3YXlzJzogJ0FMV0FZUycsCiAgICAnYXJyYXknOiAnQVJSQVknLAogICAgJ2FycmF5Y291bnQnOiAnQVJSQVlDT1VOVCcsCiAgICAnYXNzZXJ0JzogJ0FTU0VSVCcsCiAgICAnYXV0byc6ICdBVVRPJywKICAgICdhdXRvbWF0ZWQnOiAnQVVUT01BVEVEJywKICAgICdiZWdpbic6ICdCRUdJTicsCiAgICAnYm9vbCc6ICdCT09MJywKICAgICdicmVhayc6ICdCUkVBSycsCiAgICAnYnV0dG9uJzogJ0JVVFRPTicsCiAgICAnYnl0ZSc6ICdCWVRFJywKICAgICdjYXNlJzogJ0NBU0UnLAogICAgJ2NsYXNzJzogJ0NMQVNTJywKICAgICdjb2VyY2UnOiAnQ09FUkNFJywKICAgICdjb2xsYXBzZWNhdGVnb3JpZXMnOiAnQ09MTEFQU0VDQVRFR09SSUVTJywKICAgICdjb250aW51ZSc6ICdDT05USU5VRScsCiAgICAnZGVmYXVsdCc6ICdERUZBVUxUJywKICAgICdkZWZhdWx0cHJvcGVydGllcyc6ICdERUZBVUxUUFJPUEVSVElFUycsCiAgICAnZGVsZWdhdGUnOiAnREVMRUdBVEUnLAogICAgJ2RvJzogJ0RPJywKICAgICdlZGl0aW5saW5lbm90aWZ5JzogJ0VESVRJTkxJTkVOT1RJRlknLAogICAgJ2VkaXRpbmxpbmV1c2UnOiAnRURJVElOTElORVVTRScsCiAgICAnZWxzZSc6ICdFTFNFJywKICAgICdlbmQnOiAnRU5EJywKICAgICdlbnVtJzogJ0VOVU0nLAogICAgJ2VudW1jb3VudCc6ICdFTlVNQ09VTlQnLAogICAgJ2V2ZW50JzogJ0VWRU5UJywKICAgICdleGVjJzogJ0VYRUMnLAogICAgJ2V4cGFuZHMnOiAnRVhQQU5EUycsCiAgICAnZXh0ZW5kcyc6ICdFWFRFTkRTJywKICAgICdmYWxzZSc6ICdGQUxTRScsCiAgICAnZmluYWwnOiAnRklOQUwnLAogICAgJ2Zsb2F0JzogJ0ZMT0FUJywKICAgICdmb3InOiAnRk9SJywKICAgICdmb3JlYWNoJzogJ0ZPUkVBQ0gnLAogICAgJ2Z1bmN0aW9uJzogJ0ZVTkNUSU9OJywKICAgICdnbG9iYWwnOiAnR0xPQkFMJywKICAgICdnbG9iYWxjb25maWcnOiAnR0xPQkFMQ09ORklHJywKICAgICdnb3RvJzogJ0dPVE8nLAogICAgJ2lmJzogJ0lGJywKICAgICdpZ25vcmVzJzogJ0lHTk9SRVMnLAogICAgJ2ltcG9ydCc6ICdJTVBPUlQnLAogICAgJ2luaXQnOiAnSU5JVCcsCiAgICAnaW5wdXQnOiAnSU5QVVQnLAogICAgIydpbnNlcnQnOiAnSU5TRVJUJywKICAgICdpbnQnOiAnSU5UJywKICAgICdpbnRyaW5zaWMnOiAnSU5UUklOU0lDJywKICAgICdpbnZhcmlhbnQnOiAnSU5WQVJJQU5UJywKICAgICdpdGVyYXRvcic6ICdJVEVSQVRPUicsCiAgICAnbGF0ZW50JzogJ0xBVEVOVCcsCiAgICAnbG9jYWwnOiAnTE9DQUwnLAogICAgJ2xvY2FsaXplZCc6ICdMT0NBTElaRUQnLAogICAgJ25hbWUnOiAnTkFNRScsCiAgICAnbmV3JzogJ05FVycsCiAgICAnbm9uZSc6ICdOT05FJywKICAgICdub3VzZXJjcmVhdGUnOiAnTk9VU0VSQ1JFQVRFJywKICAgICdvcGVyYXRvcic6ICdPUEVSQVRPUicsCiAgICAnb3B0aW9uYWwnOiAnT1BUSU9OQUwnLAogICAgJ291dCc6ICdPVVQnLAogICAgJ3Bvc3RvcGVyYXRvcic6ICdQT1NUT1BFUkFUT1InLAogICAgJ3ByZW9wZXJhdG9yJzogJ1BSRU9QRVJBVE9SJywKICAgICdyZWxpYWJsZSc6ICdSRUxJQUJMRScsCiAgICAjJ3JlbW92ZSc6ICdSRU1PVkUnLAogICAgJ3JlcGxpY2F0aW9uJzogJ1JFUExJQ0FUSU9OJywKICAgICdyZXR1cm4nOiAnUkVUVVJOJywKICAgICdybmcnOiAnUk5HJywKICAgICdyb3QnOiAnUk9UJywKICAgICdzZWxmJzogJ1NFTEYnLAogICAgJ3NpbXVsYXRlZCc6ICdTSU1VTEFURUQnLAogICAgJ3Npbmd1bGFyJzogJ1NJTkdVTEFSJywKICAgICdza2lwJzogJ1NLSVAnLAogICAgJ3N0YXRlJzogJ1NUQVRFJywKICAgICdzdGF0aWMnOiAnU1RBVElDJywKICAgICdzdG9wJzogJ1NUT1AnLAogICAgJ3N0cmluZyc6ICdTVFJJTkcnLAogICAgJ3N0cnVjdCc6ICdTVFJVQ1QnLAogICAgJ3N1cGVyJzogJ1NVUEVSJywKICAgICdzd2l0Y2gnOiAnU1dJVENIJywKICAgICd0cnVlJzogJ1RSVUUnLAogICAgJ3VucmVsaWFibGUnOiAnVU5SRUxJQUJMRScsCiAgICAndW50aWwnOiAnVU5USUwnLAogICAgJ3Zhcic6ICdWQVInLAogICAgJ3ZlY3QnOiAnVkVDVCcsCiAgICAnd2hpbGUnOiAnV0hJTEUnLAogICAgIyB0aGUgZm9sbG93aW5nIGFyZSBrZXl3b3JkcyBhZGRlZCBieSB1bGV4CiAgICAndHlwZW9mJzogJ1RZUEVPRicsCiAgICAnc2l6ZW9mJzogJ1NJWkVPRicsCiAgICAndHlwZWRlZic6ICdUWVBFREVGJwp9CgpyZXNlcnZlZC51cGRhdGUoY2xhc3NfbW9kaWZpZXJzKQpyZXNlcnZlZC51cGRhdGUodmFyaWFibGVfbW9kaWZpZXJzKQoKdG9rZW5zID0gWwogICAgJ0NPTU1FTlQnLAogICAgJ1VOQU1FJywKICAgICdJTlRFR0VSJywKICAgICdIRVgnLAogICAgJ1NFTUlDT0xPTicsCiAgICAnTFBBUkVOJywKICAgICdSUEFSRU4nLAogICAgJ0xTUVVBUkUnLAogICAgJ1JTUVVBUkUnLAogICAgJ0xBTkdMRScsCiAgICAnUkFOR0xFJywKICAgICdMQ1VSTFknLAogICAgJ1JDVVJMWScsCiAgICAnQVNTSUdOJywKICAgICdDT01NQScsCiAgICAnUEVSSU9EJywKICAgICdMUVVPVEUnLAogICAgJ1JRVU9URScsCiAgICAnVVNUUklORycsCiAgICAnVUZMT0FUJywKICAgICdFUVVBTCcsCiAgICAnTkVRVUFMJywKICAgICdPUicsCiAgICAnTk9UJywKICAgICdJTkNSRU1FTlQnLAogICAgJ0FERCcsCiAgICAnTVVMVElQTFknLAogICAgJ0FORCcsCiAgICAnTUlOVVMnLAogICAgJ0NPTE9OJywKICAgICdTRVFVQUwnLAogICAgJ01PRFVMVVMnLAogICAgJ1NDT05DQVQnLAogICAgJ1NDT05DQVRTUEFDRScsCiAgICAnRElWSURFJywKICAgICdSRUZFUkVOQ0UnLAogICAgJ0RJUkVDVElWRScsCiAgICAnQU1QRVJTQU5EJywKICAgICdCSVRXSVNFX0FORCcsCiAgICAnQklUV0lTRV9PUicsCiAgICAnTEVGVF9TSElGVCcsCiAgICAnUklHSFRfU0hJRlQnLAogICAgJ1hPUicsCiAgICAnQklUV0lTRV9OT1QnLAogICAgJ0lEJywKICAgICdMRVFVQUwnLAogICAgJ0dFUVVBTCcsCiAgICAnSUFTU0lHTicsCiAgICAnREFTU0lHTicKICAgIF0gKyBsaXN0KHJlc2VydmVkLnZhbHVlcygpKQoKdF9MUEFSRU4gPSByJ1woJwp0X1JQQVJFTiA9IHInXCknCnRfTFNRVUFSRSA9IHInXFsnCnRfUlNRVUFSRSA9IHInXF0nCnRfTEFOR0xFID0gcidcPCcKdF9SQU5HTEUgPSByJ1w+Jwp0X0xDVVJMWSA9IHInXHsnCnRfUkNVUkxZID0gcidcfScKdF9MUVVPVEUgPSByJ1wiJwp0X1JRVU9URSA9IHInXCInCnRfaWdub3JlID0gJ1xyXHQgJwp0X1NFTUlDT0xPTiA9IHInXDsnCnRfQVNTSUdOID0gcidcPScKdF9DT01NQSA9IHInLCcKdF9QRVJJT0QgPSAnXC4nCnRfRVFVQUwgPSByJz09Jwp0X05FUVVBTCA9IHInIT0nCnRfT1IgPSByJ1x8XHwnCnRfTk9UID0gcichJwp0X0lOQ1JFTUVOVCA9IHInXCtcKycKdF9BREQgPSByJ1wrJwp0X01VTFRJUExZID0gcidcKicKdF9BTkQgPSByJ1wmXCYnCnRfTUlOVVMgPSByJy0nCnRfQ09MT04gPSByJzonCnRfU0VRVUFMID0gcid+PScKdF9NT0RVTFVTID0gciclJwp0X1NDT05DQVQgPSByJ1wkJwp0X1NDT05DQVRTUEFDRSA9IHInQCcKdF9ESVZJREUgPSByJy8nCnRfQklUV0lTRV9BTkQgPSByJ1wmJwp0X0JJVFdJU0VfT1IgPSByJ1x8Jwp0X0xFRlRfU0hJRlQgPSByJzw8Jwp0X1JJR0hUX1NISUZUID0gcic+PicKdF9YT1IgPSByJ1xeJwp0X0JJVFdJU0VfTk9UID0gcid+Jwp0X0xFUVVBTCA9IHInXDxcPScKdF9HRVFVQUwgPSByJz49Jwp0X0lBU1NJR04gPSByJ1wrPScKdF9EQVNTSUdOID0gcictPScKCgpkZWYgdF9ESVJFQ1RJVkUodCk6CiAgICByJ1wjKFx3KylccysoLispJwp0X0RJUkVDVElWRS5fX2RvY19fID0gcidcIyhcdyspXHMrKC4rKScKCmRlZiB0X1JFRkVSRU5DRSh0KToKICAgIHInKFthLXpBLVowLTlfXC1dKylccypcJyhbYS16QS1aMC05X1wtXC5dKylcJycKICAgIHJldHVybiB0CnRfUkVGRVJFTkNFLl9fZG9jX18gPSByJyhbYS16QS1aMC05X1wtXSspXHMqXCcoW2EtekEtWjAtOV9cLVwuXSspXCcnCgpkZWYgdF9VTkFNRSh0KToKICAgIHInXCcoW2EtekEtWjAtOV9cLSBdKilcJycKICAgIHJldHVybiB0CnRfVU5BTUUuX19kb2NfXyA9IHInXCcoW2EtekEtWjAtOV9cLSBdKilcJycKCmRlZiB0X1VTVFJJTkcodCk6CiAgICByJyIoKFxcezJ9KSp8KC4qP1teXFxdKFxcezJ9KSopKSInCiAgICByZXR1cm4gdAp0X1VTVFJJTkcuX19kb2NfXyA9IHInIigoXFx7Mn0pKnwoLio/W15cXF0oXFx7Mn0pKikpIicKCmRlZiB0X1VGTE9BVCh0KToKICAgIHInWy0rXT9cZCo/Wy5dXGQrJwogICAgdC52YWx1ZSA9IGZsb2F0KHQudmFsdWUpCiAgICByZXR1cm4gdAp0X1VGTE9BVC5fX2RvY19fID0gcidbLStdP1xkKj9bLl1cZCsnCgpkZWYgdF9IRVgodCk6CiAgICByJzBbeFhdWzAtOWEtZkEtRl0rJwogICAgdC50eXBlID0gJ0lOVEVHRVInCiAgICB0LnZhbHVlID0gaW50KHQudmFsdWUsIDApCiAgICByZXR1cm4gdAp0X0hFWC5fX2RvY19fID0gcicwW3hYXVswLTlhLWZBLUZdKycKCmRlZiB0X0lOVEVHRVIodCk6CiAgICByJ1stK10/XGQrJwogICAgdC52YWx1ZSA9IGludCh0LnZhbHVlKQogICAgcmV0dXJuIHQKdF9JTlRFR0VSLl9fZG9jX18gPSByJ1stK10/XGQrJwoKZGVmIHRfQ09NTUVOVCh0KToKICAgIHInKC9cKihbXipdfFtcclxuXXwoXCorKFteKi9dfFtcclxuXSkpKSpcKisvKXwoLy8uKiknCnRfQ09NTUVOVC5fX2RvY19fID0gcicoL1wqKFteKl18W1xyXG5dfChcKisoW14qL118W1xyXG5dKSkpKlwqKy8pfCgvLy4qKScKCmRlZiB0X0lEKHQpOgogICAgcidbYS16QS1aX11bYS16QS1aXzAtOV0qJwogICAgdC50eXBlID0gcmVzZXJ2ZWQuZ2V0KHQudmFsdWUubG93ZXIoKSwgJ0lEJykKICAgIHJldHVybiB0CnRfSUQuX19kb2NfXyA9IHInW2EtekEtWl9dW2EtekEtWl8wLTldKicKCmRlZiB0X25ld2xpbmUodCk6CiAgICByJ1xuKycKICAgIHQubGV4ZXIubGluZW5vICs9IGxlbih0LnZhbHVlKQp0X25ld2xpbmUuX19kb2NfXyA9IHInXG4rJwoKZGVmIHRfZXJyb3IodCk6CiAgICBwYXNzCgpsZXhlciA9IGxleC5sZXgoKQo=