Example #1
0
def convertToRPN(tokens):
    """
	Convert infix notation into Reverse Polish Notation for building the AST
	@param tokens: the list of tokens in infix notation order
	@post: this implementation uses the Shunting-yard algorithm
	"""
    outputQueue = []
    operatorStack = []
    for token in tokens:
        if token == UC_Common.BRACKET_OPEN: operatorStack.append(token)
        elif token == UC_Common.BRACKET_SHUT:
            while operatorStack and operatorStack[-1] != UC_Common.BRACKET_OPEN:
                outputQueue.append(operatorStack.pop())
            if operatorStack.pop() != UC_Common.BRACKET_OPEN:
                raise UC_CommonUnitError(
                    f"Detected mismatched parentheses: '{UC_Common.BRACKET_SHUT}'"
                )
        elif UC_Utils.isOperator(token):
            while (operatorStack
                   and operatorStack[-1] != UC_Common.BRACKET_OPEN
                   and UC_Utils.hasHigherPrecedence(operatorStack[-1], token)):
                outputQueue.append(operatorStack.pop())
            operatorStack.append(token)
        else:
            outputQueue.append(token)

    while operatorStack:
        if operatorStack[-1] == UC_Common.BRACKET_OPEN:
            raise UC_CommonUnitError(
                f"Detected mismatched parentheses: '{UC_Common.BRACKET_OPEN}'")
        outputQueue.append(operatorStack.pop())

    return outputQueue
Example #2
0
def aggregateQuantities(tokens):
    """
	Combine tokens which constitute a quantity
	@param tokens: a list of tokens
	"""
    aggregatedTokens = []
    needsValue = True

    while tokens:
        if UC_Utils.isOperator(tokens[0]):
            if needsValue:
                raise UC_Common.UnitError(
                    f"Expected float; received '{tokens[0]}'")
            aggregatedTokens.append(tokens.pop(0))
            needsValue = True
        elif UC_Utils.isSpecialChar(tokens[0]):
            aggregatedTokens.append(tokens.pop(0))
        else:
            needsValue = False

            # Get value
            quantity = '1'
            try:
                float(tokens[0])
                quantity = tokens.pop(0)
            except:
                # Inject multiplication where needed
                if aggregatedTokens and aggregatedTokens[
                        -1] == UC_Common.BRACKET_SHUT:
                    aggregatedTokens.append(UC_Common.OPERATOR_MUL)

            # Get unit
            unit = []
            if tokens and isinstance(tokens[0], list):
                unit = tokens.pop(0)

            aggregatedTokens.append((quantity, unit))
    if needsValue and aggregatedTokens:
        raise UC_Common.UnitError(f"Expected float; no tokens received")

    return aggregatedTokens
Example #3
0
def aggregateUnits(tokens):
    """
	Combine tokens which constitute compound units
	@param tokens: a list of tokens
	"""
    aggregatedTokens = []
    unitTokens = []
    parsingExp = 0

    def appendUnitTokens(aggregatedTokens, unitTokens, token=None):
        # Append unit tokens to list of aggregated tokens
        if unitTokens:
            if unitTokens[-1] == UC_Common.OPERATOR_MUL or unitTokens[
                    -1] == UC_Common.OPERATOR_DIV:
                operator = unitTokens.pop()
                aggregatedTokens.append(unitTokens)
                aggregatedTokens.append(operator)
            else:
                aggregatedTokens.append(unitTokens)
        if token is not None:
            # Inject multiplication if needed
            if ((aggregatedTokens)
                    and (not UC_Utils.isSpecialChar(aggregatedTokens[-1]))
                    and (token == UC_Common.BRACKET_OPEN)):
                aggregatedTokens.append(UC_Common.OPERATOR_MUL)
            aggregatedTokens.append(token)
        return []

    def handleParseExpDecrement(tokens, unitTokens, parsingExp):
        # Check if multiplication needs to be injected between adjacent units
        if parsingExp != 1: return parsingExp
        if tokens:
            if tokens[0] == UC_Common.OPERATOR_MUL or tokens[
                    0] == UC_Common.OPERATOR_DIV:
                unitTokens.append(tokens.pop(0))
            elif UC_Utils.isValidSymbol(tokens[0]):
                unitTokens.append(UC_Common.OPERATOR_MUL)
        return 0

    def handleAppendUnitSymbol(tokens, unitTokens, parsingExp):
        if tokens:
            token = tokens[0]
            if token == UC_Common.OPERATOR_EXP:
                unitTokens.append(tokens.pop(0))
                return 1
            elif token == UC_Common.OPERATOR_MUL or token == UC_Common.OPERATOR_DIV:
                unitTokens.append(tokens.pop(0))
            elif UC_Utils.isValidSymbol(token):
                unitTokens.append(UC_Common.OPERATOR_MUL)
        return parsingExp

    while tokens:
        token = UC_Utils.getNextToken(tokens)
        if token == UC_Common.BRACKET_OPEN:
            if parsingExp:
                unitTokens.append(token)
                parsingExp += 1
            else:
                unitTokens = appendUnitTokens(aggregatedTokens, unitTokens,
                                              token)
        elif token == UC_Common.BRACKET_SHUT:
            if parsingExp:
                unitTokens.append(token)
                parsingExp = handleParseExpDecrement(tokens, unitTokens,
                                                     parsingExp - 1)
            else:
                unitTokens = appendUnitTokens(aggregatedTokens, unitTokens,
                                              token)
        elif UC_Utils.isFloat(token):
            if parsingExp:
                if not UC_Utils.isInt(token):
                    raise UC_Common.UnitError(
                        f"Expected int; received '{token}'")
                unitTokens.append(token)
                parsingExp = handleParseExpDecrement(tokens, unitTokens,
                                                     parsingExp)
            else:
                unitTokens = appendUnitTokens(aggregatedTokens, unitTokens,
                                              token)
        elif UC_Utils.isValidSymbol(token):
            if parsingExp:
                raise UC_Common.UnitError(f"Expected int; received '{token}'")
            unitTokens.append(token)
            parsingExp = handleAppendUnitSymbol(tokens, unitTokens, parsingExp)
        elif UC_Utils.isOperator(token):
            if parsingExp:
                raise UC_Common.UnitError(f"Expected int; received '{token}'")
            else:
                unitTokens = appendUnitTokens(aggregatedTokens, unitTokens,
                                              token)
        else:
            raise UC_Common.UnitError(f"Unknown token; received '{token}'")

    appendUnitTokens(aggregatedTokens, unitTokens)
    return aggregatedTokens