lib/parser/statements/ExpressionStatement.js
function parseExpression(data, line) {
    data = data.trim();

    var lowerData = data.toLowerCase();
    var positions = util.findPositions(lowerData, [
        { 'start': '"', 'end': '"' },
        { 'start': '(', 'end': ')' }
    ]);

    // Try to find an operator in the root of the data
    for (var i = 0; i < operators.length; i++) {
        var operatorList = operators[i];
        var operatorNames = Object.keys(operatorList);

        // We go backwards so that the resulting object nesting goes from left to right
        // in the case of two operators with the same precedence are beside each other.
        // For example, with the expression '1 * 2 / 3' you would expect it to do the
        // '1 * 2' part first, so we have to go this way so that it parses as
        // DivisionOperator('1 * 2', '3') instead of MultiplicationOperator('1', '2 / 3')
        var found = util.findLastOutside(lowerData, operatorNames, lowerData.length, positions);

        // If there is an operator, parse the two sides and then return the operator
        if (found.index !== -1) {
            // If there is no number before and the character is '-' or '+', ignore
            var beforeText = data.substring(0, found.index).trim();
            if ((found.found === '-' || found.found === '+')) {
                var previousOperator = util.findLast(beforeText, allOperators);
                if (previousOperator.index !== -1) {
                    var middleContent = beforeText.substring(previousOperator.index + previousOperator.found.length).trim();
                    if (!middleContent.length) continue;
                }
            }

            var before = parseExpression(beforeText);
            var after = parseExpression(data.substring(found.index + found.found.length));

            var operatorConstructor = operatorList[found.found];
            if (!operatorConstructor) throw new SyntaxError('Unknown operator');
            return new operatorConstructor(before, after);
        }
    }

    // If none are found, its either a syntax error, function call, bracket, or singular expression
    var startBracketIndex = data.indexOf('(');
    if (startBracketIndex !== -1) {
        var endBracketIndex = data.lastIndexOf(')');
        if (endBracketIndex === -1) throw new SyntaxError('Expected end bracket in ' + data);
        var bracketContent = data.substring(startBracketIndex + 1, endBracketIndex).trim();

        // If there is something before the bracket, its a function call
        var beforeBracket = data.substring(0, startBracketIndex).trim();
        if (beforeBracket.length) return new statements.FunctionStatement(beforeBracket, bracketContent);

        // If there is something after the bracket, its a syntax error
        var afterBracket = data.substring(endBracketIndex + 1).trim();
        if (afterBracket.length) throw new SyntaxError("Unexpected expression");

        // If we've gotten to here, its just an expression in brackets
        return parseExpression(bracketContent);
    }

    // It must be a singular expression
    return parseSingularExpression(data);
}
function parseExpression(data, line) {
    data = data.trim();

    var lowerData = data.toLowerCase();
    var positions = util.findPositions(lowerData, [
        { 'start': '"', 'end': '"' },
        { 'start': '(', 'end': ')' }
    ]);

    // Try to find an operator in the root of the data
    for (var i = 0; i < operators.length; i++) {
        var operatorList = operators[i];
        var operatorNames = Object.keys(operatorList);

        // We go backwards so that the resulting object nesting goes from left to right
        // in the case of two operators with the same precedence are beside each other.
        // For example, with the expression '1 * 2 / 3' you would expect it to do the
        // '1 * 2' part first, so we have to go this way so that it parses as
        // DivisionOperator('1 * 2', '3') instead of MultiplicationOperator('1', '2 / 3')
        var found = util.findLastOutside(lowerData, operatorNames, lowerData.length, positions);

        // If there is an operator, parse the two sides and then return the operator
        if (found.index !== -1) {
            // If there is no number before and the character is '-' or '+', ignore
            var beforeText = data.substring(0, found.index).trim();
            if ((found.found === '-' || found.found === '+')) {
                var previousOperator = util.findLast(beforeText, allOperators);
                if (previousOperator.index !== -1) {
                    var middleContent = beforeText.substring(previousOperator.index + previousOperator.found.length).trim();
                    if (!middleContent.length) continue;
                }
            }

            var before = parseExpression(beforeText);
            var after = parseExpression(data.substring(found.index + found.found.length));

            var operatorConstructor = operatorList[found.found];
            if (!operatorConstructor) throw new SyntaxError('Unknown operator');
            return new operatorConstructor(before, after);
        }
    }

    // If none are found, its either a syntax error, function call, bracket, or singular expression
    var startBracketIndex = data.indexOf('(');
    if (startBracketIndex !== -1) {
        var endBracketIndex = data.lastIndexOf(')');
        if (endBracketIndex === -1) throw new SyntaxError('Expected end bracket in ' + data);
        var bracketContent = data.substring(startBracketIndex + 1, endBracketIndex).trim();

        // If there is something before the bracket, its a function call
        var beforeBracket = data.substring(0, startBracketIndex).trim();
        if (beforeBracket.length) return new statements.FunctionStatement(beforeBracket, bracketContent);

        // If there is something after the bracket, its a syntax error
        var afterBracket = data.substring(endBracketIndex + 1).trim();
        if (afterBracket.length) throw new SyntaxError("Unexpected expression");

        // If we've gotten to here, its just an expression in brackets
        return parseExpression(bracketContent);
    }

    // It must be a singular expression
    return parseSingularExpression(data);
}
function parseExpression ( data , line ) { data = data . trim ( ) ; var lowerData = data . toLowerCase ( ) ; var positions = util . findPositions ( lowerData , [ { 'start' : '"' , 'end' : '"' } , { 'start' : '(' , 'end' : ')' } ] ) ; // Try to find an operator in the root of the data for ( var i = 0 ; i < operators . length ; i ++ ) { var operatorList = operators [ i ] ; var operatorNames = Object . keys ( operatorList ) ; // We go backwards so that the resulting object nesting goes from left to right // in the case of two operators with the same precedence are beside each other. // For example, with the expression '1 * 2 / 3' you would expect it to do the // '1 * 2' part first, so we have to go this way so that it parses as // DivisionOperator('1 * 2', '3') instead of MultiplicationOperator('1', '2 / 3') var found = util . findLastOutside ( lowerData , operatorNames , lowerData . length , positions ) ; // If there is an operator, parse the two sides and then return the operator if ( found . index !== - 1 ) { // If there is no number before and the character is '-' or '+', ignore var beforeText = data . substring ( 0 , found . index ) . trim ( ) ; if ( ( found . found === '-' || found . found === '+' ) ) { var previousOperator = util . findLast ( beforeText , allOperators ) ; if ( previousOperator . index !== - 1 ) { var middleContent = beforeText . substring ( previousOperator . index + previousOperator . found . length ) . trim ( ) ; if ( ! middleContent . length ) continue ; } } var before = parseExpression ( beforeText ) ; var after = parseExpression ( data . substring ( found . index + found . found . length ) ) ; var operatorConstructor = operatorList [ found . found ] ; if ( ! operatorConstructor ) throw new SyntaxError ( 'Unknown operator' ) ; return new operatorConstructor ( before , after ) ; } } // If none are found, its either a syntax error, function call, bracket, or singular expression var startBracketIndex = data . indexOf ( '(' ) ; if ( startBracketIndex !== - 1 ) { var endBracketIndex = data . lastIndexOf ( ')' ) ; if ( endBracketIndex === - 1 ) throw new SyntaxError ( 'Expected end bracket in ' + data ) ; var bracketContent = data . substring ( startBracketIndex + 1 , endBracketIndex ) . trim ( ) ; // If there is something before the bracket, its a function call var beforeBracket = data . substring ( 0 , startBracketIndex ) . trim ( ) ; if ( beforeBracket . length ) return new statements . FunctionStatement ( beforeBracket , bracketContent ) ; // If there is something after the bracket, its a syntax error var afterBracket = data . substring ( endBracketIndex + 1 ) . trim ( ) ; if ( afterBracket . length ) throw new SyntaxError ( "Unexpected expression" ) ; // If we've gotten to here, its just an expression in brackets return parseExpression ( bracketContent ) ; } // It must be a singular expression return parseSingularExpression ( data ) ; }
Parses a given expression, following BOCMDAS
(Brackets, Comparators, Multiplication/Division, Addition/Subtraction/binary operators)
To configure the order @see operators/index.js

Two operators of the same precedence will execute left to right, just as expected

@param data
@param line
Parses a given expression following BOCMDAS ( Brackets Comparators Multiplication / Division Addition / Subtraction / binary operators ) To configure the order @see operators / index . js