def _parse_parameter(self): """ Parses single parameter """ t = self._next_token() while t.type == TokenType.NEWLINE or t.value == "\n": if not self._tokens_left(): raise ParseError("Expected parameter at end of string") t = self._next_token() if t.type == TokenType.NAME: # Constant or action used as parameter if self._tokens_left() and self._peek_token( ).type == TokenType.OP and self._peek_token().value == '(': # Action used as parameter self.index -= 1 # go step back and reparse as action parameter = self._parse_action() elif self._tokens_left() and t.value in Action.ALL and type( Action.ALL[ t.value]) == dict and self._peek_token().value == '.': # SOMETHING.Action used as parameter self.index -= 1 # go step back and reparse as action parameter = self._parse_action() else: # Constant if not t.value in ActionParser.CONSTS: raise ParseError( "Expected parameter, got '%s' which is not defined" % (t.value, )) parameter = ActionParser.CONSTS[t.value] # Check for dots while self._tokens_left() and self._peek_token( ).type == TokenType.OP and self._peek_token().value == '.': self._next_token() if not self._tokens_left(): raise ParseError("Expected NAME after '.'") t = self._next_token() if not hasattr(parameter, t.value): raise ParseError("%s has no attribute '%s'" % ( parameter, t.value, )) parameter = getattr(parameter, t.value) # Check for ranges (<, >, <=, >=) if self._tokens_left() and self._peek_token().type == TokenType.OP: if self._peek_token().value in RangeOP.OPS: op = self._next_token().value # TODO: Maybe other axes if parameter not in (STICK, SCButtons.LT, SCButtons.RT, SCButtons.X, SCButtons.Y): raise ParseError("'%s' is not trigger nor axis" % (nameof(parameter), )) if not self._tokens_left(): raise ParseError("Excepted number after '%s'" % (op, )) try: number = float(self._next_token().value) except ValueError: raise ParseError("Excepted number after '%s'" % (op, )) parameter = RangeOP(parameter, op, number) return parameter if t.type == TokenType.OP and t.value == "-": if not self._tokens_left( ) or self._peek_token().type != TokenType.NUMBER: raise ParseError("Expected number after '-'") return -self._parse_number() if t.type == TokenType.NUMBER: self.index -= 1 return self._parse_number() if t.type == TokenType.STRING: return t.value[1:-1].decode('string_escape') raise ParseError("Expected parameter, got '%s'" % (t.value, ))