private static string FormsOf(string text, FormsOfType type)
        {
            if (IsComplexExpression(text))
            {
                return(text);
            }

            if (text[text.Length - 2] == '*')
            {
                return(text);
            }

            switch (type)
            {
            case FormsOfType.None:
                return(text);

            case FormsOfType.Inflectional:
                return($"FORMSOF(INFLECTIONAL, {text})");

            case FormsOfType.Thesaurus:
                return($"FORMSOF(THESAURUS, {text})");

            case FormsOfType.Both:
                return($"(FORMSOF(INFLECTIONAL, {text}) OR FORMSOF(THESAURUS, {text}))");

            default:
                throw new ParsingException("Unknown FormsOfType.", ErrorKind.UnknownFormsOfType);
            }
        }
        private static void ProcessOr(Stack <string> stack, FormsOfType type)
        {
            var o2     = stack.Pop();
            var o1     = stack.Pop();
            var result = $"({FormsOf(o1, type)} OR {FormsOf(o2, type)})";

            stack.Push(result);
        }
예제 #3
0
        /// <summary>
        /// Compiles a given postfix notation expression into a CONTAINSTABLE search condition.
        /// </summary>
        /// <param name="searchExpression">The input search expression.</param>
        /// <param name="type">The FORMSOF type to generate.</param>
        /// <returns>The CONTAINSTABLE search condition.</returns>
        public static string Translate(string searchExpression, FormsOfType type = FormsOfType.Both)
        {
            if (searchExpression == null)
            {
                throw new ArgumentNullException(nameof(searchExpression), "String cannot be null.");
            }

            var lexemes = Lexer.Tokenize(searchExpression);

            if (lexemes.Length == 0)
            {
                throw new ParsingException("The tokenized search expression contains no lexical elements.", ErrorKind.InvalidEmptyExpression);
            }

            lexemes = FixAndKeywordCommonIssuesForUserFriendliness(lexemes);

            var postfixNotation = Parser.GetPostfixNotation(lexemes);

            postfixNotation = FixApostrophesForUserFriendliness(postfixNotation);

            var translation = CodeGenerator.Generate(postfixNotation, type);

            return(translation);
        }
        /// <summary>
        /// Generates CONTAINSTABLE search condition code for a given postfix notation expression.
        /// </summary>
        /// <param name="postfixNotation">The input postfix notation.</param>
        /// <param name="type">The FORMSOF type to generate.</param>
        /// <returns>The CONTAINSTABLE search condition.</returns>
        public static string Generate(LexicalElement[] postfixNotation, FormsOfType type = FormsOfType.Both)
        {
            if (postfixNotation == null)
            {
                throw new ArgumentNullException(nameof(postfixNotation), "Postfix notation array cannot be null.");
            }

            if (postfixNotation.Length == 0)
            {
                throw new ParsingException("Invalid empty expression.", ErrorKind.InvalidEmptyExpression);
            }

            var stack = new Stack <string>(postfixNotation.Length);

            foreach (var currentElement in postfixNotation)
            {
                if (currentElement.Type.IsOperator())
                {
                    var operandCount = currentElement.Type.GetOperandCount();

                    if (stack.Count < operandCount)
                    {
                        throw new ParsingException(
                                  $"Missing operand for operator. Expected {operandCount} operands, found {stack.Count} potential operands",
                                  currentElement, ErrorKind.MissingOperand);
                    }

                    switch (currentElement.Type)
                    {
                    case LexicalElementType.And:
                        ProcessAnd(stack, type);
                        break;

                    case LexicalElementType.Not:
                        ProcessNot(stack, type);
                        break;

                    case LexicalElementType.Or:
                        ProcessOr(stack, type);
                        break;

                    case LexicalElementType.Near:
                        ProcessNear(stack, currentElement, false);
                        break;

                    case LexicalElementType.OrderedNear:
                        ProcessNear(stack, currentElement, true);
                        break;
                    }
                }
                else
                {
                    if (currentElement.Type != LexicalElementType.Term)
                    {
                        throw new ParsingException("Expected \"Term\" token type. Found unexpected token",
                                                   currentElement, ErrorKind.UnexpectedTokenType);
                    }

                    stack.Push(Quote(currentElement.Text));
                }
            }

            if (stack.Count != 1)
            {
                throw new ParsingException($"Evaluation failed. The stack contains {stack.Count} items.",
                                           ErrorKind.StackHasMoreOrLessThanOneItem);
            }

            var result = stack.Pop();

            result = FormsOf(result, type);

            return(result);
        }