Beispiel #1
0
def validate_token(token, validation):
    """Validate that token matches given requirement."""
    # Unsigned int.
    if "u" == validation:
        if not is_glsl_int_unsigned(token):
            return None
    # Int.
    elif "i" == validation:
        if not is_glsl_int(token):
            return None
    # Float.
    elif "f" == validation:
        if not is_glsl_float(token):
            return None
    # Access.
    elif "a" == validation:
        if not is_glsl_access(token):
            return None
    # Operator =.
    elif validation in ("="):
        if (not is_glsl_operator(token)) or (not token.isAssignment()):
            return None
    # Control.
    elif "c" == validation:
        if not is_glsl_control(token):
            return None
    # In/out.
    elif "o" == validation:
        if not is_glsl_inout(token):
            return None
    # Operator.
    elif "p" == validation:
        if not is_glsl_operator(token):
            return None
    # Type.
    elif "t" == validation:
        if not is_glsl_type(token):
            return None
    # Terminator.
    elif ";" == validation:
        if not is_glsl_terminator(token):
            return None
    # Valid identifier name.
    elif "n" == validation:
        if not is_glsl_name(token):
            return None
    # Select from options.
    elif validation.find("|") >= 0:
        variations = list(filter(lambda x: x, validation.split("|")))
        if not check_token(token, variations):
            return None
    # Unknown validation.
    else:
        raise RuntimeError("unknown token request '%s'" % (validation))
    # On success, return token as-is.
    return token
Beispiel #2
0
def validate_token(token, validation):
    """Validate that token matches given requirement."""
    # Unsigned int.
    if "u" == validation:
        if not is_glsl_int_unsigned(token):
            return None
    # Int.
    elif "i" == validation:
        if not is_glsl_int(token):
            return None
    # Float.
    elif "f" == validation:
        if not is_glsl_float(token):
            return None
    # Access.
    elif "a" == validation:
        if not is_glsl_access(token):
            return None
    # Operator =.
    elif validation in ("="):
        if (not is_glsl_operator(token)) or (not token.isAssignment()):
            return None
    # Control.
    elif "c" == validation:
        if not is_glsl_control(token):
            return None
    # In/out.
    elif "o" == validation:
        if not is_glsl_inout(token):
            return None
    # Operator.
    elif "p" == validation:
        if not is_glsl_operator(token):
            return None
    # Type.
    elif "t" == validation:
        if not is_glsl_type(token):
            return None
    # Terminator.
    elif ";" == validation:
        if not is_glsl_terminator(token):
            return None
    # Valid identifier name.
    elif "n" == validation:
        if not is_glsl_name(token):
            return None
    # Select from options.
    elif validation.find("|") >= 0:
        variations = list(filter(lambda x: x, validation.split("|")))
        if not check_token(token, variations):
            return None
    # Unknown validation.
    else:
        raise RuntimeError("unknown token request '%s'" % (validation))
    # On success, return token as-is.
    return token
Beispiel #3
0
 def findHighestPrioOperatorMiddle(self):
     """Find highest priority operator from elements in the middle."""
     prio = -1
     for ii in self.__middle:
         mid = ii.getSingleChildMiddleNonToken()
         if is_glsl_operator(mid):
             prio = max(prio, mid.getPrecedence())
     return prio
Beispiel #4
0
 def findHighestPrioOperatorMiddle(self):
     """Find highest priority operator from elements in the middle."""
     prio = -1
     for ii in self.__middle:
         mid = ii.getSingleChildMiddleNonToken()
         if is_glsl_operator(mid):
             prio = max(prio, mid.getPrecedence())
     return prio
Beispiel #5
0
 def findSiblingOperatorRight(self):
     """Find nearest right operator."""
     if not self.__parent:
         return None
     mid = self.__parent.getSingleChildMiddleNonToken()
     if not is_glsl_operator(mid):
         return None
     if self.__parent.getSingleChildRight() != self:
         return mid
     return self.__parent.findSiblingOperatorRight()
Beispiel #6
0
 def collapseIdentity(self):
     """Collapse identity transforms that do not do anything."""
     oper = self.getSingleChildMiddleNonToken()
     if not is_glsl_operator(oper):
         raise RuntimeError("must be an operator to collapse identities")
     left_token = self.getSingleChildLeft()
     right_token = self.getSingleChildRight()
     # If right or left tokens not found, not eligible for identity collapse.
     if (not left_token) or (not right_token):
         return False
     left = left_token.getSingleChild()
     right = right_token.getSingleChild()
     # Can't collapse if either side is in itself an operator.
     if is_glsl_operator(left) or is_glsl_operator(right):
         return False
     # Multiply by one.
     if oper.getOperator() == "*":
         if is_glsl_number(left) and (left.getFloat() == 1.0):
             self.collapseMiddleLeft()
             return True
         if is_glsl_number(right) and (right.getFloat() == 1.0):
             self.collapseMiddleRight()
             return True
     # Divide by one.
     elif oper.getOperator() == "/":
         if is_glsl_number(right) and (right.getFloat() == 1.0):
             self.collapseMiddleRight()
             return True
     # Substract zero.
     elif oper.getOperator() == "-":
         if is_glsl_number(right) and (right.getFloat() == 0.0):
             self.collapseMiddleRight()
             return True
     # Add zero.
     elif oper.getOperator() == "+":
         if is_glsl_number(left) and (left.getFloat() == 0.0):
             self.collapseMiddleLeft()
             return True
         if is_glsl_number(right) and (right.getFloat() == 0.0):
             self.collapseMiddleRight()
             return True
     # No collapses found.
     return False
Beispiel #7
0
 def findSiblingOperatorRight(self):
     """Find nearest right operator."""
     if not self.__parent:
         return None
     mid = self.__parent.getSingleChildMiddleNonToken()
     if not is_glsl_operator(mid):
         return None
     if self.__parent.getSingleChildRight() != self:
         return mid
     return self.__parent.findSiblingOperatorRight()
Beispiel #8
0
 def collapseIdentity(self):
     """Collapse identity transforms that do not do anything."""
     oper = self.getSingleChildMiddleNonToken()
     if not is_glsl_operator(oper):
         raise RuntimeError("must be an operator to collapse identities")
     left_token = self.getSingleChildLeft()
     right_token = self.getSingleChildRight()
     # If right or left tokens not found, not eligible for identity collapse.
     if (not left_token) or (not right_token):
         return False
     left = left_token.getSingleChild()
     right = right_token.getSingleChild()
     # Can't collapse if either side is in itself an operator.
     if is_glsl_operator(left) or is_glsl_operator(right):
         return False
     # Multiply by one.
     if oper.getOperator() == "*":
         if is_glsl_number(left) and (left.getFloat() == 1.0):
             self.collapseMiddleLeft()
             return True
         if is_glsl_number(right) and (right.getFloat() == 1.0):
             self.collapseMiddleRight()
             return True
     # Divide by one.
     elif oper.getOperator() == "/":
         if is_glsl_number(right) and (right.getFloat() == 1.0):
             self.collapseMiddleRight()
             return True
     # Substract zero.
     elif oper.getOperator() == "-":
         if is_glsl_number(right) and (right.getFloat() == 0.0):
             self.collapseMiddleRight()
             return True
     # Add zero.
     elif oper.getOperator() == "+":
         if is_glsl_number(left) and (left.getFloat() == 0.0):
             self.collapseMiddleLeft()
             return True
         if is_glsl_number(right) and (right.getFloat() == 0.0):
             self.collapseMiddleRight()
             return True
     # No collapses found.
     return False
Beispiel #9
0
 def findEqualToken(self, orig):
     """Find a token or a number that has equal priority to given token."""
     mid = self.getSingleChildMiddleNonToken()
     if not mid:
         return (None, None)
     if is_glsl_number(mid):
         return (orig, self)
     if is_glsl_operator(mid):
         if mid.getPrecedence() is orig.getPrecedenceIfOperator():
             lt = self.getSingleChildLeft()
             if lt and lt.getSingleChildMiddleNonToken():
                 (lt_oper, lt_token) = lt.findEqualToken(self)
                 if lt_oper and lt_token:
                     return (lt_oper, lt_token)
             rt = self.getSingleChildRight()
             if rt and rt.getSingleChildMiddleNonToken():
                 (rt_oper, rt_token) = rt.findEqualToken(self)
                 if rt_oper and rt_token:
                     return (rt_oper, rt_token)
     return (None, None)
Beispiel #10
0
 def findEqualToken(self, orig):
     """Find a token or a number that has equal priority to given token."""
     mid = self.getSingleChildMiddleNonToken()
     if not mid:
         return (None, None)
     if is_glsl_number(mid):
         return (orig, self)
     if is_glsl_operator(mid):
         if mid.getPrecedence() is orig.getPrecedenceIfOperator():
             lt = self.getSingleChildLeft()
             if lt and lt.getSingleChildMiddleNonToken():
                 (lt_oper, lt_token) = lt.findEqualToken(self)
                 if lt_oper and lt_token:
                     return (lt_oper, lt_token)
             rt = self.getSingleChildRight()
             if rt and rt.getSingleChildMiddleNonToken():
                 (rt_oper, rt_token) = rt.findEqualToken(self)
                 if rt_oper and rt_token:
                     return (rt_oper, rt_token)
     return (None, None)
Beispiel #11
0
def token_tree_build(lst):
    """Builds and balances a token tree from given list."""
    # Ensure all list elements are tokens.
    lst = token_list_create(lst)
    # Might be that everything is lost at this point.
    if not lst:
        return None
    # Start iteration over tokenized list.
    bracket_count = 0
    paren_count = 0
    first_bracket_index = -1
    first_paren_index = -1
    lowest_operator = None
    lowest_operator_index = -1
    for ii in range(len(lst)):
        vv = lst[ii].getSingleChild()
        # Count parens.
        if is_glsl_paren(vv):
            # Bracket case.
            if vv.isBracket():
                new_bracket_count = vv.updateBracket(bracket_count)
                if new_bracket_count == bracket_count:
                    raise RuntimeError("wut?")
                bracket_count = new_bracket_count
                # Split on brackets reaching 0.
                if 0 >= bracket_count:
                    if 0 > first_bracket_index:
                        raise RuntimeError("bracket inconsistency")
                    return token_tree_split_paren(lst, first_bracket_index, ii)
                elif (1 == bracket_count) and (0 > first_bracket_index):
                    first_bracket_index = ii
            # Paren case.
            elif vv.isParen():
                new_paren_count = vv.updateParen(paren_count)
                if new_paren_count == paren_count:
                    raise RuntimeError("wut?")
                paren_count = new_paren_count
                # Split on parens reaching 0.
                if 0 >= paren_count:
                    if 0 > first_paren_index:
                        raise RuntimeError("paren inconsistency")
                    return token_tree_split_paren(lst, first_paren_index, ii)
                elif (1 == paren_count) and (0 > first_paren_index):
                    first_paren_index = ii
            # Curly braces impossible.
            else:
                raise RuntimeError("unknown paren object '%s'" % (str(vv)))
        # If we're not within parens, consider operators.
        if is_glsl_operator(vv) and (0 >= bracket_count) and (0 >=
                                                              paren_count):
            if (not lowest_operator) or (vv < lowest_operator):
                lowest_operator = vv
                lowest_operator_index = ii
    # Iteration done. Make a tiny subtree on the lowest operator position and continue.
    if lowest_operator:
        ret = GlslToken(lowest_operator)
        left_block = []
        right_block = []
        left = None
        right = None
        # Get extending list left and right.
        if lowest_operator_index >= 2:
            left_block = lst[:(lowest_operator_index - 1)]
        if lowest_operator_index <= len(lst) - 3:
            right_block = lst[(lowest_operator_index + 2):]
        # Check for left existing.
        if lowest_operator_index >= 1:
            left = lst[lowest_operator_index - 1]
            ret.addLeft(left)
        elif not (lowest_operator in ("-", "++", "--", "!")):
            raise RuntimeError("left component nonexistent for operator '%s'" %
                               (str(lowest_operator)))
        # Check for right existing.
        if lowest_operator_index <= len(lst) - 2:
            right = lst[lowest_operator_index + 1]
            ret.addRight(right)
        elif not (lowest_operator in ("++", "--")):
            raise RuntimeError(
                "right component nonexistent for operator '%s'" %
                (str(lowest_operator)))
        return token_tree_build(left_block + [ret] + right_block)
    # Only option at this point is that the list has no operators and no parens - return as itself.
    return GlslToken(lst)
Beispiel #12
0
 def simplify(self):
     """Perform any simple simplification and stop."""
     # Remove parens.
     if self.isSurroundedByParens():
         middle_lst = self.flattenMiddle()
         #debug_str = " ".join(map(lambda x: str(x), middle_lst))
         #if debug_str.find("normalize") > -1:
         #  print(debug_str)
         # Single expression.
         if len(middle_lst) == 1:
             if self.removeParens():
                 return True
         # Number or name with access.
         elif len(middle_lst) == 2:
             mid_lt = middle_lst[0]
             mid_rt = middle_lst[1]
             if (is_glsl_name(mid_lt)
                     or is_glsl_number(mid_lt)) and is_glsl_access(mid_rt):
                 if self.removeParens():
                     return True
         # Single function call or indexing (with potential access).
         elif len(middle_lst) >= 3:
             mid_name = middle_lst[0]
             mid_opening = middle_lst[1]
             last_index = -1
             mid_ending = middle_lst[last_index]
             # If last part is access, try the element before that instead.
             if is_glsl_access(mid_ending) and (len(middle_lst) >= 4):
                 last_index = -2
                 mid_ending = middle_lst[last_index]
             # Check for function call or indexing format.
             if (is_glsl_name(mid_name)
                     or is_glsl_type(mid_name)) and is_glsl_paren(
                         mid_opening) and mid_opening.matches(mid_ending):
                 if is_single_call_or_access_list(middle_lst[2:last_index],
                                                  mid_opening):
                     if self.removeParens():
                         return True
         # Only contains lower-priority operators compared to outside.
         paren_rt = self.__right[0].getSingleChild()
         elem_rt = self.findRightSiblingElementFromParentTree(paren_rt)
         prio = self.findHighestPrioOperatorMiddle()
         # Right element cannot be access or bracket.
         if (prio >= 0) and (not is_glsl_access(elem_rt)) and (elem_rt !=
                                                               "["):
             left = self.findSiblingOperatorLeft()
             right = self.findSiblingOperatorRight()
             if left:
                 if left.getPrecedence() > prio:
                     if right:
                         if right.getPrecedence() >= prio:
                             if self.removeParens():
                                 return True
                     else:
                         if self.removeParens():
                             return True
             elif right:
                 if right.getPrecedence() >= prio:
                     if self.removeParens():
                         return True
             else:
                 if self.removeParens():
                     return True
     # Recurse down.
     for ii in self.__left:
         if ii.simplify():
             return True
     for ii in self.__right:
         if ii.simplify():
             return True
     for ii in self.__middle:
         if is_glsl_token(ii):
             if ii.simplify():
                 return True
     # Perform operations only after removing any possible parens.
     if (len(self.__middle) == 1):
         oper = self.__middle[0]
         if is_glsl_operator(oper) and oper.isApplicable():
             # Try to remove trivial cases.
             if self.collapseIdentity():
                 return True
             (left_parent, left_token) = self.findEqualTokenLeft(self)
             (right_parent, right_token) = self.findEqualTokenRight(self)
             if left_parent and left_token and right_parent and right_token:
                 # Trivial case - leaf entry that can just be applied.
                 if left_parent is right_parent:
                     if not (left_parent is self):
                         raise RuntimeError(
                             "left and right operator resolve as '%s' not matching self '%s'"
                             % (str(left_parent), str(self)))
                     result = self.applyOperator(oper, left_token,
                                                 right_token)
                     if not (result is None):
                         # Remove sides from parent.
                         left_token.removeFromParent()
                         right_token.removeFromParent()
                         self.__middle = [result]
                         return True
                 # Nontrivial cases.
                 left_oper = left_parent.getSingleChildMiddleNonToken()
                 right_oper = right_parent.getSingleChildMiddleNonToken()
                 result = None
                 # Double divide -> multiply.
                 if (left_oper == "/") and (
                         right_oper
                         == "/") and left_token.isSingleChildRight():
                     result = self.applyOperator(interpret_operator("*"),
                                                 left_token, right_token)
                 # Same operation -> can be just applied.
                 elif left_parent == right_parent:
                     result = self.applyOperator(left_oper, left_token,
                                                 right_token)
                 # Substract addition: <something> - a + b => <something> + (b - a)
                 elif (left_oper
                       == "-") and (oper == "+") and (oper is right_oper):
                     result = self.applyOperator(left_oper, right_token,
                                                 left_token)
                     # If b - a is negative, replace it with its absolute value which is going to get subtracted.
                     if result.getFloat() < 0.0:
                         right_oper.setOperator("-")
                         if is_glsl_int(result):
                             result = interpret_int(
                                 str(abs(result.getInt())))
                         elif is_glsl_float(result):
                             number_string = str(abs(result.getFloat()))
                             (integer_part,
                              decimal_part) = number_string.split(".")
                             result = interpret_float(
                                 integer_part, decimal_part)
                         else:
                             raise RuntimeError(
                                 "unknown result object '%s'" %
                                 (str(result)))
                 # TODO: further cases.
                 # On success, eliminate upper token (left only if necessary) and replace other token with result.
                 if result:
                     if left_parent is self:
                         right_token.collapseUp()
                         left_token.replaceMiddle(result)
                     else:
                         left_token.collapseUp()
                         right_token.replaceMiddle(result)
                     return True
     # Operations are done. Allow simplification of remaining constans, if possible.
     mid = self.getSingleChildMiddleNonToken()
     if mid and is_glsl_float(mid) and (not mid.isIntegrifyAllowed()):
         # No operators, left or right.
         left = self.findSiblingOperatorLeft()
         right = self.findSiblingOperatorRight()
         if not left and not right:
             mid.setAllowIntegrify(True)
             return True
         # Alone in vecN() directive.
         left = self.getSingleChildLeft()
         right = self.getSingleChildRight()
         if left and left.isTypeOpen() and right and (
                 right.getSingleChildMiddleNonToken() == ")"):
             mid.setAllowIntegrify(True)
             return True
         # If could not be integrified, at least ensure that float precision is not exceeded.
         if mid.getPrecision() > 6:
             mid.truncatePrecision(6)
             return True
     return False
Beispiel #13
0
 def getPrecedenceIfOperator(self):
     """Return precedence if middle element is a single child that is an operator."""
     mid = self.getSingleChildMiddleNonToken()
     if mid and is_glsl_operator(mid):
         return mid.getPrecedence()
     return None
Beispiel #14
0
def token_tree_build(lst):
    """Builds and balances a token tree from given list."""
    # Ensure all list elements are tokens.
    lst = token_list_create(lst)
    # Might be that everything is lost at this point.
    if not lst:
        return None
    # Start iteration over tokenized list.
    bracket_count = 0
    paren_count = 0
    first_bracket_index = -1
    first_paren_index = -1
    lowest_operator = None
    lowest_operator_index = -1
    for ii in range(len(lst)):
        vv = lst[ii].getSingleChild()
        # Count parens.
        if is_glsl_paren(vv):
            # Bracket case.
            if vv.isBracket():
                new_bracket_count = vv.updateBracket(bracket_count)
                if new_bracket_count == bracket_count:
                    raise RuntimeError("wut?")
                bracket_count = new_bracket_count
                # Split on brackets reaching 0.
                if 0 >= bracket_count:
                    if 0 > first_bracket_index:
                        raise RuntimeError("bracket inconsistency")
                    return token_tree_split_paren(lst, first_bracket_index, ii)
                elif (1 == bracket_count) and (0 > first_bracket_index):
                    first_bracket_index = ii
            # Paren case.
            elif vv.isParen():
                new_paren_count = vv.updateParen(paren_count)
                if new_paren_count == paren_count:
                    raise RuntimeError("wut?")
                paren_count = new_paren_count
                # Split on parens reaching 0.
                if 0 >= paren_count:
                    if 0 > first_paren_index:
                        raise RuntimeError("paren inconsistency")
                    return token_tree_split_paren(lst, first_paren_index, ii)
                elif (1 == paren_count) and (0 > first_paren_index):
                    first_paren_index = ii
            # Curly braces impossible.
            else:
                raise RuntimeError("unknown paren object '%s'" % (str(vv)))
        # If we're not within parens, consider operators.
        if is_glsl_operator(vv) and (0 >= bracket_count) and (0 >= paren_count):
            if (not lowest_operator) or (vv < lowest_operator):
                lowest_operator = vv
                lowest_operator_index = ii
    # Iteration done. Make a tiny subtree on the lowest operator position and continue.
    if lowest_operator:
        ret = GlslToken(lowest_operator)
        left_block = []
        right_block = []
        left = None
        right = None
        # Get extending list left and right.
        if lowest_operator_index >= 2:
            left_block = lst[:(lowest_operator_index - 1)]
        if lowest_operator_index <= len(lst) - 3:
            right_block = lst[(lowest_operator_index + 2):]
        # Check for left existing.
        if lowest_operator_index >= 1:
            left = lst[lowest_operator_index - 1]
            ret.addLeft(left)
        elif not (lowest_operator in ("-", "++", "--", "!")):
            raise RuntimeError("left component nonexistent for operator '%s'" % (str(lowest_operator)))
        # Check for right existing.
        if lowest_operator_index <= len(lst) - 2:
            right = lst[lowest_operator_index + 1]
            ret.addRight(right)
        elif not (lowest_operator in ("++", "--")):
            raise RuntimeError("right component nonexistent for operator '%s'" % (str(lowest_operator)))
        return token_tree_build(left_block + [ret] + right_block)
    # Only option at this point is that the list has no operators and no parens - return as itself.
    return GlslToken(lst)
Beispiel #15
0
 def simplify(self):
     """Perform any simple simplification and stop."""
     # Remove parens.
     if self.isSurroundedByParens():
         middle_lst = self.flattenMiddle()
         # Single expression.
         if len(middle_lst) == 1:
             if self.removeParens():
                 return True
         # Number or name with access.
         elif len(middle_lst) == 2:
             mid_lt = middle_lst[0]
             mid_rt = middle_lst[1]
             if (is_glsl_name(mid_lt) or is_glsl_number(mid_lt)) and is_glsl_access(mid_rt):
                 if self.removeParens():
                     return True
         # Single function call or indexing (with potential access).
         elif len(middle_lst) >= 3:
             mid_name = middle_lst[0]
             mid_opening = middle_lst[1]
             last_index = -1
             mid_ending = middle_lst[last_index]
             # If last part is access, try the element before that instead.
             if is_glsl_access(mid_ending) and (len(middle_lst) >= 4):
                 last_index = -2
                 mid_ending = middle_lst[last_index]
             # Check for function call or indexing format.
             if (is_glsl_name(mid_name) or is_glsl_type(mid_name)) and is_glsl_paren(mid_opening) and mid_opening.matches(mid_ending):
                 if is_single_call_or_access_list(middle_lst[2:last_index], mid_opening):
                     if self.removeParens():
                         return True
         # Only contains lower-priority operators compared to outside.
         paren_rt = self.__right[0].getSingleChild()
         elem_rt = self.findRightSiblingElementFromParentTree(paren_rt)
         prio = self.findHighestPrioOperatorMiddle()
         # Right element cannot be access or bracket.
         if (prio >= 0) and (not is_glsl_access(elem_rt)) and (elem_rt != "["):
             left = self.findSiblingOperatorLeft()
             right = self.findSiblingOperatorRight()
             if left:
                 if left.getPrecedence() > prio:
                     if right:
                         if right.getPrecedence() >= prio:
                             if self.removeParens():
                                 return True
                     else:
                         if self.removeParens():
                             return True
             elif right:
                 if right.getPrecedence() >= prio:
                     if self.removeParens():
                         return True
             else:
                 if self.removeParens():
                     return True
     # Recurse down.
     for ii in self.__left:
         if ii.simplify():
             return True
     for ii in self.__right:
         if ii.simplify():
             return True
     for ii in self.__middle:
         if is_glsl_token(ii):
             if ii.simplify():
                 return True
     # Perform operations only after removing any possible parens.
     if (len(self.__middle) == 1):
         oper = self.__middle[0]
         if is_glsl_operator(oper) and oper.isApplicable():
             # Try to remove trivial cases.
             if self.collapseIdentity():
                 return True
             (left_parent, left_token) = self.findEqualTokenLeft(self)
             (right_parent, right_token) = self.findEqualTokenRight(self)
             if left_parent and left_token and right_parent and right_token:
                 # Trivial case - leaf entry that can just be applied.
                 if left_parent is right_parent:
                     if not (left_parent is self):
                         raise RuntimeError("left and right operator resolve as '%s' not matching self '%s'" %
                                            (str(left_parent), str(self)))
                     result = self.applyOperator(oper, left_token, right_token)
                     if not (result is None):
                         # Remove sides from parent.
                         left_token.removeFromParent()
                         right_token.removeFromParent()
                         self.__middle = [result]
                         return True
                 # Nontrivial cases.
                 left_oper = left_parent.getSingleChildMiddleNonToken()
                 right_oper = right_parent.getSingleChildMiddleNonToken()
                 result = None
                 # Double divide -> multiply.
                 if (left_oper == "/") and (right_oper == "/") and left_token.isSingleChildRight():
                     result = self.applyOperator(interpret_operator("*"), left_token, right_token)
                 # Same operation -> can be just applied.
                 elif left_parent == right_parent:
                     result = self.applyOperator(left_oper, left_token, right_token)
                 # Substract addition: <something> - a + b => <something> + (b - a)
                 elif (left_oper == "-") and (oper == "+") and (oper is right_oper):
                     result = self.applyOperator(left_oper, right_token, left_token)
                     # If b - a is negative, replace it with its absolute value which is going to get subtracted.
                     if result.getFloat() < 0.0:
                         right_oper.setOperator("-")
                         if is_glsl_int(result):
                             result = interpret_int(str(abs(result.getInt())))
                         elif is_glsl_float(result):
                             number_string = str(abs(result.getFloat()))
                             (integer_part, decimal_part) = number_string.split(".")
                             result = interpret_float(integer_part, decimal_part)
                         else:
                             raise RuntimeError("unknown result object '%s'" % (str(result)))
                 # TODO: further cases.
                 # On success, eliminate upper token (left only if necessary) and replace other token with result.
                 if result:
                     if left_parent is self:
                         right_token.collapseUp()
                         left_token.replaceMiddle(result)
                     else:
                         left_token.collapseUp()
                         right_token.replaceMiddle(result)
                     return True
     # Operations are done. Allow simplification of remaining constans, if possible.
     mid = self.getSingleChildMiddleNonToken()
     if mid and is_glsl_float(mid) and (abs(mid.getFloat()) <= 2147483647.0) and (not mid.isIntegrifyAllowed()):
         # No operators, left or right.
         left = self.findSiblingOperatorLeft()
         right = self.findSiblingOperatorRight()
         if (not left) and (not right):
             mid.setAllowIntegrify(True)
             return True
         # Alone in vecN() directive.
         left = self.getSingleChildLeft()
         right = self.getSingleChildRight()
         if left and left.isTypeOpen() and right and (right.getSingleChildMiddleNonToken() == ")"):
             mid.setAllowIntegrify(True)
             return True
         # If could not be integrified, at least ensure that float precision is not exceeded.
         if mid.getPrecision() > 6:
             mid.truncatePrecision(6)
             return True
     return False
Beispiel #16
0
 def getPrecedenceIfOperator(self):
     """Return precedence if middle element is a single child that is an operator."""
     mid = self.getSingleChildMiddleNonToken()
     if mid and is_glsl_operator(mid):
         return mid.getPrecedence()
     return None