def identify_token(token): """ The function that converts a token from tokenize to a BaseType. """ if isinstance(token, (Comment, String)): return token if token == ' ': return Space() if token == '\t': return Tab() if token == '\\\n': return BrokenEndOfLine() if token in ('(', ')', '[', ']', '{', '}', ',', ';'): return ParserKeyword(token) if token in ('\n', '\r\n'): return EndOfLine(token) if token in ('true', 'false'): return Boolean(token == 'true') try: return Number(int(token)) except ValueError: pass try: return Number(float(token)) except ValueError: pass if token in PREPROCESSORS: return Preprocessor(token) if token.lower() in NAMESPACES: return Namespace(token) elif token.lower() in KEYWORDS: return Keyword(token) else: return Variable(token)
def _getVariableArray(lhs_v, rhs_v, interpreter): # get the variable name if len(rhs_v) != 2: interpreter.exception( SQFParserError( rhs_v.position, 'getVariable requires array of 2 elements (has %d)' % (len(rhs_v)))) if not isinstance(rhs_v.value[0], (String, Nothing)): interpreter.exception( SQFParserError( rhs_v.value[0].position, 'getVariable array first element must be a string (is %s)' % type(rhs_v.value[0]).__name__)) variable = Variable(rhs_v.value[0].value) variable.position = rhs_v.value[0].position outcome = interpreter.value(variable, lhs_v.value) if outcome == Nothing(): outcome = rhs_v.value[1] return outcome
def execute_single(self, statement): assert (isinstance(statement, Statement)) outcome = Nothing() outcome.position = statement.position base_tokens = [] for token in statement.tokens: if not statement.is_base_token(token): self.execute_other(token) else: base_tokens.append(token) if not base_tokens: return outcome # operations that cannot evaluate the value of all base_tokens if type(base_tokens[0]) == DefineStatement: return base_tokens[0] elif base_tokens[0] == Preprocessor("#include"): if len(base_tokens) != 2: exception = SQFParserError(base_tokens[0].position, "#include requires one argument") self.exception(exception) elif type(self.execute_token(base_tokens[1])) != String: exception = SQFParserError( base_tokens[0].position, "#include first argument must be a string") self.exception(exception) return outcome elif isinstance(base_tokens[0], Keyword) and base_tokens[0].value in PREPROCESSORS: # remaining preprocessors are ignored return outcome elif len(base_tokens) == 2 and base_tokens[0] == Keyword('private'): # the rhs may be a variable, so we cannot get the value rhs = self.execute_token(base_tokens[1]) if isinstance(rhs, String): self.add_privates([rhs]) elif isinstance(rhs, Array): value = self.value(rhs) if value.is_undefined: self.exception( SQFWarning( base_tokens[0].position, 'Obfuscated statement. Consider explicitly set what is private.' )) else: self.add_privates(value) elif isinstance(rhs, Variable): var = String('"' + rhs.name + '"') var.position = rhs.position self.add_privates([var]) outcome = PrivateType(rhs) outcome.position = rhs.position self.privates.add(outcome) else: self.exception( SQFParserError(base_tokens[0].position, '`private` used incorrectly')) return outcome # assignment operator elif len(base_tokens) == 3 and base_tokens[1] == Keyword('='): lhs = self.execute_token(base_tokens[0]) if isinstance(lhs, PrivateType): self.privates.remove(lhs) lhs = lhs.variable else: lhs = self.get_variable(base_tokens[0]) if not isinstance(lhs, Variable): self.exception( SQFParserError( base_tokens[0].position, 'lhs of assignment operator must be a variable')) else: # if the rhs_v is code and calls `lhs` (recursion) it will assume lhs is anything (and not Nothing) scope = self.get_scope(lhs.name) if lhs.name not in scope or isinstance(scope[lhs.name], Nothing): scope[lhs.name] = Anything() rhs_v = self.value(base_tokens[2]) self.assign(lhs, rhs_v) if not statement.ending: outcome = rhs_v return outcome # A variable can only be evaluated if we need its value, so we will not call its value until the very end. elif len(base_tokens) == 1 and type( base_tokens[0]) in (Variable, Array): return self.execute_token(base_tokens[0]) # heuristic for defines (that are thus syntactically correct): # - is keyword but upper cased # - first token string starts uppercased elif len(base_tokens) == 1 and type(base_tokens[0]) == Keyword and str( base_tokens[0])[0].isupper(): outcome = Variable(str(base_tokens[0])) outcome.position = base_tokens[0].position return outcome elif is_undefined_define(base_tokens): # get all arguments and compute their value to analyze them if isinstance(base_tokens[1].base_tokens[0], Statement): sub_tokens = base_tokens[1].base_tokens[0].base_tokens else: sub_tokens = base_tokens[0] for sub_token in sub_tokens: self.value(sub_token) # finally, build the outcome outcome = Anything() outcome.position = base_tokens[0].position return outcome # evaluate all the base_tokens, trying to obtain their values values = [] tokens = [] for token in base_tokens: t = self.execute_token(token) v = self.value(t) tokens.append(t) values.append(v) # try to find a match for any expression, both typed and un-typed case_found = None possible_expressions = values_to_expressions(values, EXPRESSIONS_MAP, EXPRESSIONS) for case in possible_expressions: if case.is_signature_match(values): # match first occurrence case_found = case break
def _getVariableString(lhs_v, rhs_v, interpreter): variable = Variable(rhs_v.value) variable.position = rhs_v.position return interpreter.value(variable, lhs_v.value)