Exemple #1
0
        /*
         * Handles "|", "&", "!" and "^" tokens
         */
        private static void LogicalToken(IteratorGroup current, string token, string previousToken)
        {
            switch (token)
            {
            case "|":

                // OR logical boolean algebraic operator
                current.AddLogical(new Logical(Logical.LogicalType.Or));
                break;

            case "&":

                // AND logical boolean algebraic operator
                current.AddLogical(new Logical(Logical.LogicalType.And));
                break;

            case "!":

                // NOT logical boolean algebraic operator
                current.AddLogical(new Logical(Logical.LogicalType.Not));
                break;

            case "^":

                // XOR logical boolean algebraic operator
                current.AddLogical(new Logical(Logical.LogicalType.Xor));
                break;
            }
        }
Exemple #2
0
        /*
         * Tokenizes and initializes expression object
         */
        IteratorGroup BuildExpression(
            ApplicationContext context,
            Node evaluatedNode,
            Node exNode)
        {
            // Setting up a return value
            var retVal = new IteratorGroup();

            // Checking to see if we should run formatting logic on expression before parsing iterators
            var expression = FormatExpression(context, exNode);

            string previousToken = null;   // Needed to keep track of previous token
            var    current       = retVal; // Used as index iterator during tokenizing process

            // Tokenizer uses StringReader to tokenize, making sure tokenizer is disposed when finished
            using (var tokenizer = new Tokenizer(expression)) {
                // Looping through every token in espression, building up our Iterator tree hierarchy
                foreach (var idxToken in tokenizer.Tokens)
                {
                    if (previousToken == "?")
                    {
                        // Last token, initializing type of expression and conversion type, if given
                        InitializeType(idxToken);
                        break; // finished
                    }

                    if (previousToken == null && idxToken != "/" && idxToken != "?" && idxToken != "(")
                    {
                        // Missing '/' before iterator
                        throw new ExpressionException(Value, "Syntax error in expression, missing iterator declaration, after evaluation expression yields; " + expression);
                    }

                    if (idxToken != "?")
                    {
                        // '?' token is handled in next iteration
                        current = AppendToken(context, current, idxToken, previousToken);
                    }
                    else if (previousToken == "/")
                    {
                        // Checking for '/' at end of token, before type declaration, which means we have an empty name iterator
                        current.AddIterator(new IteratorNamed(""));
                    }

                    // Storing previous token, since some iterators are dependent upon knowing it
                    previousToken = idxToken;
                }
            }
            // Checking to see if we have open groups, which is an error
            if (current.ParentGroup != null)
            {
                throw new ExpressionException(Value, "Group in expression was not closed. Probably missing ')' token, after evaluation expression yields; " + expression);
            }

            // Returning IteratorGroup to caller, but first making sure it has the right Root Group Iterator
            retVal.GroupRootNode = evaluatedNode;
            return(retVal);
        }
Exemple #3
0
        /*
         * Creates a modulo token
         */
        private void ModuloToken(IteratorGroup current, string token)
        {
            // Removing "%" character
            token = token.Substring(1);

            // Making sure we're given a number
            if (!Utilities.IsNumber(token))
            {
                throw new ExpressionException(
                          Value,
                          string.Format("Syntax error in modulo token '{0}', expected integer value, found string", token));
            }
            current.AddIterator(new IteratorModulo(int.Parse(token)));
        }
Exemple #4
0
        /*
         * Creates a valued token
         */
        private void ValueToken(ApplicationContext context, IteratorGroup current, string token)
        {
            token = token.Substring(1); // Removing equal sign (=)
            string type = null;         // Defaulting to "no type", meaning "string" type basically

            // Might contain a type declaration, checking here
            if (token.StartsWith(":"))
            {
                // Yup, we've got a type declaration for our token ...
                type  = token.Substring(1, token.IndexOf(":", 1, StringComparison.Ordinal) - 1);
                token = token.Substring(type.Length + 2);
            }
            current.AddIterator(new IteratorValued(token, type));
        }
Exemple #5
0
        /*
         * Creates a sibling token
         */
        private void SiblingToken(IteratorGroup current, string token)
        {
            var intValue = token.Substring(1);
            var oper     = token[0];
            var value    = 1;

            if (intValue.Length > 0 && !Utilities.IsNumber(intValue))
            {
                throw new ExpressionException(
                          Value,
                          string.Format("Syntax error in sibling token '{0}', expected integer value, found string", token));
            }
            if (intValue.Length > 0)
            {
                value = int.Parse(intValue);
            }
            current.AddIterator(new IteratorSibling(value * (oper == '+' ? 1 : -1)));
        }
Exemple #6
0
        /*
         * Creates an elder relative token
         */
        private void ElderRelativeToken(IteratorGroup current, string token)
        {
            var name = token.Substring(1);

            current.AddIterator(new IteratorNamedElderRelative(name));
        }
Exemple #7
0
        /*
         * Creates a range token [x,y]
         */
        private void RangeToken(IteratorGroup current, string token)
        {
            // Verifying token ends with "]"
            token = token.TrimEnd();
            if (token [token.Length - 1] != ']')
            {
                throw new ExpressionException(
                          Value,
                          string.Format("Syntax error in range token '{0}', no ']' at end of token", token));
            }

            token = token.Substring(1, token.Length - 2);  // Removing [] square brackets

            if (token.IndexOf(',') == -1)
            {
                throw new ExpressionException(
                          Value,
                          string.Format("Syntax error in range token '{0}', range token must have at the very least a ',' character.", token));
            }

            var values = token.Split(',');

            // Verifyies token has only two integer values, separated by ","
            if (values.Length != 2)
            {
                throw new ExpressionException(
                          Value,
                          string.Format("Syntax error in range token '[{0}]', ranged iterator takes two integer values, separated by ','", token));
            }
            var start    = -1;
            var end      = -1;
            var startStr = values [0].Trim();
            var endStr   = values [1].Trim();

            if (startStr.Length > 0)   // start index was explicitly given
            {
                if (!Utilities.IsNumber(startStr))
                {
                    throw new ExpressionException(
                              Value,
                              string.Format("Syntax error in range token '[{0}]', expected number, found string", token));
                }
                start = int.Parse(startStr, CultureInfo.InvariantCulture);
            }
            if (endStr.Length > 0)   // end index was explicitly given
            {
                if (!Utilities.IsNumber(endStr))
                {
                    throw new ExpressionException(
                              Value,
                              string.Format("Syntax error in range token '[{0}]', expected number, found string", token));
                }
                end = int.Parse(endStr, CultureInfo.InvariantCulture);
                if (end <= start)
                {
                    throw new ExpressionException(
                              Value,
                              string.Format("Syntax error in range token '[{0}]', end must be larger than start", token));
                }
            }
            current.AddIterator(new IteratorRange(start, end));
        }
Exemple #8
0
        /*
         * Handles an expression iterator token
         */
        private IteratorGroup AppendToken(
            ApplicationContext context,
            IteratorGroup current,
            string token,
            string previousToken)
        {
            switch (token)
            {
            case "(":

                // Opening new group, checking for empty name iterator first
                if (previousToken == "/")
                {
                    current.AddIterator(new IteratorNamed(""));
                }
                return(new IteratorGroup(current));

            case ")":

                // Closing group, checking for empty name iterator first and missing group opening first
                if (current.ParentGroup == null)     // making sure there's actually an open group first
                {
                    throw new ExpressionException(
                              Value,
                              "Closing parenthesis ')' has no matching '(' in expression.");
                }
                if (previousToken == "/")
                {
                    current.AddIterator(new IteratorNamed(""));
                }
                return(current.ParentGroup);

            case "/":

                // New token iterator
                if (previousToken == "/")
                {
                    // Two slashes "//" preceding each other, hence we're looking for a named value,
                    // where its name is ""
                    current.AddIterator(new IteratorNamed(""));
                }     // Else, ignoring token, since it's simply declaring the beginning (or the end) of another token
                break;

            case "|":
            case "&":
            case "^":
            case "!":

                // Boolean algebraic operator, opening up a new sibling-expression, checking for empty name iterator first
                if (previousToken == "/")
                {
                    current.AddIterator(new IteratorNamed(""));
                }
                LogicalToken(current, token, previousToken);
                break;

            case "..":

                // Sanity check!
                if (previousToken != "/")
                {
                    throw new ExpressionException(Value, "Missing '/' before possible iterator");
                }

                // Root node token
                current.AddIterator(new IteratorRoot());
                break;

            case "*":

                // Sanity check!
                if (previousToken != "/")
                {
                    throw new ExpressionException(Value, "Missing '/' before possible iterator");
                }

                // All children token
                current.AddIterator(new IteratorChildren());
                break;

            case "**":

                // Sanity check!
                if (previousToken != "/")
                {
                    throw new ExpressionException(Value, "Missing '/' before possible iterator");
                }

                // Flatten descendants token
                current.AddIterator(new IteratorDescendants());
                break;

            case ".":

                // Sanity check!
                if (previousToken != "/")
                {
                    throw new ExpressionException(Value, "Missing '/' before possible iterator");
                }

                // Parent node token
                current.AddIterator(new IteratorParent());
                break;

            case "#":

                // Sanity check!
                if (previousToken != "/")
                {
                    throw new ExpressionException(Value, "Missing '/' before possible iterator");
                }

                // Reference node token
                current.AddIterator(new IteratorReference());
                break;

            case "<":

                // Sanity check!
                if (previousToken != "/")
                {
                    throw new ExpressionException(Value, "Missing '/' before possible iterator");
                }

                // Left shift token
                current.AddIterator(new IteratorShiftLeft());
                break;

            case ">":

                // Sanity check!
                if (previousToken != "/")
                {
                    throw new ExpressionException(Value, "Missing '/' before possible iterator");
                }

                // Right shift token
                current.AddIterator(new IteratorShiftRight());
                break;

            case "=$":

                // Sanity check!
                if (previousToken != "/")
                {
                    throw new ExpressionException(Value, "Missing '/' before possible iterator");
                }

                // Right shift token
                current.AddIterator(new IteratorDistinctValue());
                break;

            case "$":

                // Sanity check!
                if (previousToken != "/")
                {
                    throw new ExpressionException(Value, "Missing '/' before possible iterator");
                }

                // Right shift token
                current.AddIterator(new IteratorDistinctName());
                break;

            case "++":

                // Sanity check!
                if (previousToken != "/")
                {
                    throw new ExpressionException(Value, "Missing '/' before possible iterator");
                }

                // Right shift token
                current.AddIterator(new IteratorSiblingsOlder());
                break;

            case "--":

                // Sanity check!
                if (previousToken != "/")
                {
                    throw new ExpressionException(Value, "Missing '/' before possible iterator");
                }

                // Right shift token
                current.AddIterator(new IteratorSiblingsYounger());
                break;

            default:

                // Sanity check!
                if (previousToken != "/")
                {
                    throw new ExpressionException(Value, "Missing '/' before possible iterator");
                }

                // Handles everything else
                if (token.StartsWith("="))
                {
                    // Some type of value token, either normal value, or regex value
                    ValueToken(context, current, token);
                }
                else if (token.StartsWith("["))
                {
                    // Range iterator token
                    RangeToken(current, token);
                }
                else if (token.StartsWith("..") && token.Length > 2)
                {
                    // Named ancestor token
                    current.AddIterator(new IteratorNamedAncestor(token.Substring(2)));
                }
                else if (token.StartsWith("%"))
                {
                    // Modulo token
                    ModuloToken(current, token);
                }
                else if (token.StartsWith("-") || token.StartsWith("+"))
                {
                    // Sibling offset
                    SiblingToken(current, token);
                }
                else if (token.StartsWith("@"))
                {
                    // Sibling offset
                    ElderRelativeToken(current, token);
                }
                else
                {
                    if (Utilities.IsNumber(token))
                    {
                        // Numbered child token
                        current.AddIterator(new IteratorNumberedChild(int.Parse(token)));
                    }
                    else
                    {
                        // Defaulting to "named iterator"
                        current.AddIterator(new IteratorNamed(token));
                    }
                }
                break;
            }

            // Defaulting to returning what we came in with
            return(current);
        }