def t_INITIAL_SHARP(self, t): r'\#' if self.find_column(t) == 1: t.lexer.begin('preproc') else: syntax_error(t.lexer.lineno, "illegal character '%s'" % t.value[0])
def make_node(cls, id_, arglist, lineno): """ Creates an array access. A(x1, x2, ..., xn) """ assert isinstance(arglist, SymbolARGLIST) variable = gl.SYMBOL_TABLE.access_array(id_, lineno) if variable is None: return None if len(variable.bounds) != len(arglist): syntax_error( lineno, "Array '%s' has %i dimensions, not %i" % (variable.name, len(variable.bounds), len(arglist))) return None # Checks for array subscript range if the subscript is constant # e.g. A(1) is a constant subscript access for i, b in zip(arglist, variable.bounds): btype = gl.SYMBOL_TABLE.basic_types[gl.BOUND_TYPE] lower_bound = NUMBER(b.lower, type_=btype, lineno=lineno) i.value = BINARY.make_node('MINUS', TYPECAST.make_node( btype, i.value, lineno), lower_bound, lineno, func=lambda x, y: x - y, type_=btype) if is_number(i.value) or is_const(i.value): val = i.value.value if val < 0 or val > b.count: warning(lineno, "Array '%s' subscript out of range" % id_) # Returns the variable entry and the node return cls(variable, arglist, lineno)
def t_MACROS(t): r'__[a-zA-Z]+__' if t.value in macros: t.type = t.value return t syntax_error(t.lexer.lineno, "unknown macro '%s'" % t.value)
def make_node(lower, upper, lineno): """ Creates an array bound """ if not is_static(lower, upper): syntax_error(lineno, 'Array bounds must be constants') return None if isinstance(lower, SymbolVAR): lower = lower.value if isinstance(upper, SymbolVAR): upper = upper.value lower.value = int(lower.value) upper.value = int(upper.value) if lower.value < 0: syntax_error(lineno, 'Array bounds must be greater than 0') return None if lower.value > upper.value: syntax_error( lineno, 'Lower array bound must be less or equal to upper one') return None return SymbolBOUND(lower.value, upper.value)
def t_INITIAL_preproc_error(self, t): # error handling rule syntax_error(t.lexer.lineno, "illegal character '%s'" % t.value[0])
def t_INITIAL_bin_string_asm_preproc_comment_error(t): syntax_error(t.lineno, "illegal character '%s'" % t.value[0])
def t_INITIAL_bin_string_asm_preproc_comment_ERROR(t): r'.' syntax_error(t.lineno, "ignoring illegal character '%s'" % t.value[0]) return t
def make_node(cls, new_type, node, lineno): """ Creates a node containing the type cast of the given one. If new_type == node.type, then nothing is done, and the same node is returned. Returns None on failure (and calls syntax_error) """ assert isinstance(new_type, SymbolTYPE) # None (null) means the given AST node is empty (usually an error) if node is None: return None # Do nothing. Return None assert isinstance(node, Symbol), '<%s> is not a Symbol' % node # The source and dest types are the same if new_type == node.type_: return node # Do nothing. Return as is # TODO: Create a base scalar type if isinstance(node, SymbolVARARRAY): if new_type.size == node.type_.size and TYPE.string not in ( new_type, node.type_): return node syntax_error( lineno, "Array {} type does not match parameter type".format( node.name)) return None STRTYPE = TYPE.string # Typecasting, at the moment, only for number if node.type_ == STRTYPE: syntax_error( lineno, 'Cannot convert string to a value. ' 'Use VAL() function') return None # Converting from string to number is done by STR if new_type == STRTYPE: syntax_error( lineno, 'Cannot convert value to string. ' 'Use STR() function') return None # If the given operand is a constant, perform a static typecast if is_CONST(node): node.expr = cls(new_type, node.expr, lineno) return node if not is_number(node) and not is_const(node): return cls(new_type, node, lineno) # It's a number. So let's convert it directly if is_const(node): node = SymbolNUMBER(node.value, node.lineno, node.type_) if new_type.is_basic and not TYPE.is_integral( new_type): # not an integer node.value = float(node.value) else: # It's an integer new_val = (int(node.value) & ((1 << (8 * new_type.size)) - 1) ) # Mask it if node.value >= 0 and node.value != new_val: errmsg.warning_conversion_lose_digits(node.lineno) node.value = new_val elif node.value < 0 and (1 << (new_type.size * 8)) + \ node.value != new_val: # Test for positive to negative coercion errmsg.warning_conversion_lose_digits(node.lineno) node.value = new_val - (1 << (new_type.size * 8)) node.type_ = new_type return node
def make_node(cls, operator, left, right, lineno, func=None, type_=None): """ Creates a binary node for a binary operation, e.g. A + 6 => '+' (A, 6) in prefix notation. Parameters: -operator: the binary operation token. e.g. 'PLUS' for A + 6 -left: left operand -right: right operand -func: is a lambda function used when constant folding is applied -type_: resulting type (to enforce it). If no type_ is specified the resulting one will be guessed. """ if left is None or right is None: return None a, b = left, right # short form names # Check for constant non-numeric operations c_type = common_type(a, b) # Resulting operation type or None if c_type: # there must be a common type for a and b if is_numeric(a, b) and (is_const(a) or is_number(a)) and \ (is_const(b) or is_number(b)): if func is not None: a = SymbolTYPECAST.make_node(c_type, a, lineno) # ensure type b = SymbolTYPECAST.make_node(c_type, b, lineno) # ensure type return SymbolNUMBER(func(a.value, b.value), type_=type_, lineno=lineno) if is_static(a, b): a = SymbolTYPECAST.make_node(c_type, a, lineno) # ensure type b = SymbolTYPECAST.make_node(c_type, b, lineno) # ensure type return SymbolCONST(cls(operator, a, b, lineno, type_=type_, func=func), lineno=lineno) if operator in ('BNOT', 'BAND', 'BOR', 'BXOR', 'NOT', 'AND', 'OR', 'XOR', 'MINUS', 'MULT', 'DIV', 'SHL', 'SHR') and \ not is_numeric(a, b): syntax_error(lineno, 'Operator %s cannot be used with STRINGS' % operator) return None if is_string(a, b) and func is not None: # Are they STRING Constants? if operator == 'PLUS': return SymbolSTRING(func(a.value, b.value), lineno) return SymbolNUMBER(int(func(a.text, b.text)), type_=TYPE.ubyte, lineno=lineno) # Convert to u8 (boolean) if operator in ('BNOT', 'BAND', 'BOR', 'BXOR'): if TYPE.is_decimal(c_type): c_type = TYPE.long_ if a.type_ != b.type_ and TYPE.string in (a.type_, b.type_): c_type = a.type_ # Will give an error based on the fist operand if operator not in ('SHR', 'SHL'): a = SymbolTYPECAST.make_node(c_type, a, lineno) b = SymbolTYPECAST.make_node(c_type, b, lineno) if a is None or b is None: return None if type_ is None: if operator in ('LT', 'GT', 'EQ', 'LE', 'GE', 'NE', 'AND', 'OR', 'XOR', 'NOT'): type_ = TYPE.ubyte # Boolean type else: type_ = c_type return cls(operator, a, b, type_=type_, lineno=lineno)