Exemple #1
0
        public static bool TryParseNode(IParser parser, out TypeReference defNode, bool mimickingRecord = false, bool isPublic = false)
        {
            defNode = null;
            bool result = false;

            ArrayTypeReference   arrayType;
            RecordDefinitionNode recordDef;

            if (ArrayTypeReference.TryParseNode(parser, out arrayType) && arrayType != null)
            {
                result             = true;
                defNode            = new TypeReference();
                defNode.StartIndex = arrayType.StartIndex;
                defNode.EndIndex   = arrayType.EndIndex;
                defNode._isPublic  = isPublic;
                defNode.Children.Add(arrayType.StartIndex, arrayType);
                defNode.IsComplete = true;
            }
            else if (RecordDefinitionNode.TryParseNode(parser, out recordDef, isPublic) && recordDef != null)
            {
                result             = true;
                defNode            = new TypeReference();
                defNode.StartIndex = recordDef.StartIndex;
                defNode.EndIndex   = recordDef.EndIndex;
                defNode._isPublic  = isPublic;
                defNode.Children.Add(recordDef.StartIndex, recordDef);
                defNode.IsComplete = true;
            }
            else if (parser.PeekToken(TokenKind.LikeKeyword))
            {
                result = true;
                parser.NextToken();
                defNode            = new TypeReference();
                defNode.StartIndex = parser.Token.Span.Start;
                defNode._isPublic  = isPublic;

                // get db info
                if (!parser.PeekToken(TokenCategory.Identifier) && parser.PeekToken(TokenKind.Colon, 2))
                {
                    parser.NextToken(); // advance to the database name
                    defNode.DatabaseName = parser.Token.Token.Value.ToString();
                    parser.NextToken(); // advance to the colon
                }
                if (!parser.PeekToken(TokenCategory.Identifier))
                {
                    parser.ReportSyntaxError("Database table name expected.");
                }
                else if (!parser.PeekToken(TokenKind.Dot, 2) && !parser.PeekToken(TokenCategory.Identifier))
                {
                    parser.ReportSyntaxError("A mimicking type must reference a table as follows: \"[tablename].[recordname]\".");
                }
                else
                {
                    parser.NextToken(); // advance to the table name
                    defNode.TableName = parser.Token.Token.Value.ToString();
                    parser.NextToken(); // advance to the dot
                    if (parser.Token.Token.Kind == TokenKind.Dot)
                    {
                        if (parser.PeekToken(TokenKind.Multiply) ||
                            parser.PeekToken(TokenCategory.Identifier) ||
                            parser.PeekToken(TokenCategory.Keyword))
                        {
                            parser.NextToken(); // advance to the column name
                            defNode.ColumnName = parser.Token.Token.Value.ToString();
                            if (!mimickingRecord && defNode.ColumnName == "*")
                            {
                                parser.ReportSyntaxError("A variable cannot mimic an entire table without being a record. The variable must be defined as a mimicking record.");
                            }
                            defNode.IsComplete = true;
                            defNode.EndIndex   = parser.Token.Span.End;
                        }
                        else
                        {
                            if (mimickingRecord)
                            {
                                parser.ReportSyntaxError("A mimicking variable must use the format \"like table.*\"");
                            }
                            else
                            {
                                parser.ReportSyntaxError("A mimicking variable must use the format \"like table.column\"");
                            }
                        }
                    }
                    else
                    {
                        if (mimickingRecord)
                        {
                            parser.ReportSyntaxError("A mimicking variable must use the format \"like table.*\"");
                        }
                        else
                        {
                            parser.ReportSyntaxError("A mimicking variable must use the format \"like table.column\"");
                        }
                    }
                }
            }
            else
            {
                var tok = parser.PeekToken();
                var cat = Tokenizer.GetTokenInfo(tok).Category;
                if (cat == TokenCategory.Keyword || cat == TokenCategory.Identifier)
                {
                    StringBuilder sb = new StringBuilder();
                    result = true;
                    parser.NextToken();
                    defNode            = new TypeReference();
                    defNode.StartIndex = parser.Token.Span.Start;
                    sb.Append(parser.Token.Token.Value.ToString());

                    // determine if there are any constraints on the type keyword
                    string typeString;
                    if (TypeConstraints.VerifyValidConstraint(parser, out typeString))
                    {
                        defNode._typeNameString    = typeString;
                        defNode._isConstrainedType = true;
                    }
                    else
                    {
                        // see if we're referencing an extension type (dotted name)
                        while (parser.PeekToken(TokenKind.Dot))
                        {
                            sb.Append(parser.NextToken().Value.ToString());
                            if (parser.PeekToken(TokenCategory.Keyword) || parser.PeekToken(TokenCategory.Identifier))
                            {
                                sb.Append(parser.NextToken().Value.ToString());
                            }
                            else
                            {
                                parser.ReportSyntaxError("Unexpected token in type reference.");
                            }
                        }
                        defNode._typeNameString = sb.ToString();
                    }

                    AttributeSpecifier attribSpec;
                    if (AttributeSpecifier.TryParseNode(parser, out attribSpec))
                    {
                        defNode.Attribute = attribSpec;
                    }

                    defNode.EndIndex   = parser.Token.Span.End;
                    defNode.IsComplete = true;
                }
                else if (cat == TokenCategory.EndOfStream)
                {
                    parser.ReportSyntaxError("Unexpected end of type definition");
                    result = false;
                }
            }

            return(result);
        }
        public static bool TryParseNode(IParser parser, out ConstantDefinitionNode defNode, bool isPublic = false)
        {
            defNode = null;
            bool result = false;

            // parse constant definition
            if (parser.PeekToken(TokenCategory.Identifier) || parser.PeekToken(TokenCategory.Keyword))
            {
                defNode = new ConstantDefinitionNode();
                result  = true;
                parser.NextToken();
                defNode.StartIndex = parser.Token.Span.Start;
                defNode._location  = parser.TokenLocation;
                defNode._isPublic  = isPublic;
                defNode.Identifier = parser.Token.Token.Value.ToString();

                if (parser.PeekToken(TokenCategory.Identifier) || parser.PeekToken(TokenCategory.Keyword))
                {
                    parser.NextToken();
                    defNode.Typename = parser.Token.Token.Value.ToString();

                    string typeStr;
                    // This gets things like char(50), etc.
                    if (TypeConstraints.VerifyValidConstraint(parser, out typeStr))
                    {
                        defNode.Typename = typeStr;
                    }
                }

                if (!parser.PeekToken(TokenKind.Equals) && !(parser.PeekToken(2) is ConstantValueToken))
                {
                    parser.ReportSyntaxError("A constant must be defined with a value.");
                }
                else
                {
                    parser.NextToken(); // advance to equals

                    if (parser.PeekToken(TokenCategory.StringLiteral))
                    {
                        parser.NextToken();
                        defNode.Literal  = string.Format("\"{0}\"", parser.Token.Token.Value.ToString());
                        defNode.Typename = "string";
                    }
                    else if (parser.PeekToken(TokenCategory.CharacterLiteral))
                    {
                        parser.NextToken();
                        defNode.Literal  = string.Format("\'{0}\'", parser.Token.Token.Value.ToString());
                        defNode.Typename = "string";
                    }
                    else if (parser.PeekToken(TokenKind.Subtract))
                    {
                        parser.NextToken();
                        if (parser.PeekToken(TokenCategory.NumericLiteral))
                        {
                            parser.NextToken();
                            defNode.Literal = string.Format("-{0}", parser.Token.Token.Value.ToString());
                        }
                    }
                    else if (parser.PeekToken(TokenCategory.NumericLiteral))
                    {
                        parser.NextToken();
                        defNode.Literal = parser.Token.Token.Value.ToString();
                    }
                    else if (parser.PeekToken(TokenCategory.IncompleteMultiLineStringLiteral))
                    {
                        StringBuilder sb = new StringBuilder(parser.NextToken().Value.ToString());
                        while (parser.PeekToken(TokenCategory.IncompleteMultiLineStringLiteral))
                        {
                            parser.NextToken();
                            sb.Append(parser.Token.Token.Value.ToString());
                        }
                        defNode.Literal    = sb.ToString();
                        defNode.IsComplete = true;
                        defNode.Typename   = "string";
                    }
                    else if (parser.PeekToken(TokenKind.MdyKeyword))
                    {
                        StringBuilder sb = new StringBuilder(parser.NextToken().Value.ToString());
                        if (parser.PeekToken(TokenKind.LeftParenthesis))
                        {
                            parser.NextToken();
                            sb.Append("(");
                            while (!parser.PeekToken(TokenKind.Comma))
                            {
                                if (parser.PeekToken(TokenCategory.Keyword) || parser.PeekToken(TokenCategory.Identifier))
                                {
                                    parser.ReportSyntaxError("Invalid token found in MDY specification.");
                                    return(result);
                                }
                                sb.Append(parser.NextToken().Value.ToString());
                            }
                            sb.Append(", ");
                            parser.NextToken();
                            while (!parser.PeekToken(TokenKind.Comma))
                            {
                                if (parser.PeekToken(TokenCategory.Keyword) || parser.PeekToken(TokenCategory.Identifier))
                                {
                                    parser.ReportSyntaxError("Invalid token found in MDY specification.");
                                    return(result);
                                }
                                sb.Append(parser.NextToken().Value.ToString());
                            }
                            sb.Append(", ");
                            parser.NextToken();
                            while (!parser.PeekToken(TokenKind.RightParenthesis))
                            {
                                if (parser.PeekToken(TokenCategory.Keyword) || parser.PeekToken(TokenCategory.Identifier))
                                {
                                    parser.ReportSyntaxError("Invalid token found in MDY specification.");
                                    return(result);
                                }
                                sb.Append(parser.NextToken().Value.ToString());
                            }
                            sb.Append(")");
                            parser.NextToken();
                            defNode.Literal    = sb.ToString();
                            defNode.IsComplete = true;
                            defNode.Typename   = "date";
                        }
                        else
                        {
                            parser.ReportSyntaxError("Date constant found with an invalid MDY expression.");
                        }
                    }
                    else if (parser.PeekToken(TokenKind.DatetimeKeyword))
                    {
                        StringBuilder sb = new StringBuilder(parser.NextToken().Value.ToString());
                        if (parser.PeekToken(TokenKind.LeftParenthesis))
                        {
                            parser.NextToken();
                            sb.Append("(");
                            while (!parser.PeekToken(TokenKind.RightParenthesis))
                            {
                                if (parser.PeekToken(TokenCategory.Keyword) || parser.PeekToken(TokenCategory.Identifier))
                                {
                                    parser.ReportSyntaxError("Invalid token found in MDY specification.");
                                    return(result);
                                }
                                sb.Append(parser.NextToken().Value.ToString());
                            }
                            sb.Append(") ");
                            parser.NextToken();

                            string constraintStr;
                            if (TypeConstraints.VerifyValidConstraint(parser, out constraintStr, TokenKind.DatetimeKeyword))
                            {
                                sb.Append(constraintStr);
                                defNode.Literal    = sb.ToString();
                                defNode.IsComplete = true;
                                defNode.Typename   = "datetime";
                            }
                            else
                            {
                                parser.ReportSyntaxError("Datetime constant has an invalid constraint.");
                            }
                        }
                        else
                        {
                            parser.ReportSyntaxError("Datetime constant found with an invalid expression.");
                        }
                    }
                    else if (parser.PeekToken(TokenKind.IntervalKeyword))
                    {
                        StringBuilder sb = new StringBuilder(parser.NextToken().Value.ToString());
                        if (parser.PeekToken(TokenKind.LeftParenthesis))
                        {
                            parser.NextToken();
                            sb.Append("(");
                            while (!parser.PeekToken(TokenKind.RightParenthesis))
                            {
                                if (parser.PeekToken(TokenCategory.Keyword) || parser.PeekToken(TokenCategory.Identifier))
                                {
                                    parser.ReportSyntaxError("Invalid token found in MDY specification.");
                                    return(result);
                                }
                                sb.Append(parser.NextToken().Value.ToString());
                            }
                            sb.Append(") ");
                            parser.NextToken();

                            string constraintStr;
                            if (TypeConstraints.VerifyValidConstraint(parser, out constraintStr, TokenKind.IntervalKeyword))
                            {
                                sb.Append(constraintStr);
                                defNode.Literal    = sb.ToString();
                                defNode.IsComplete = true;
                                defNode.Typename   = "interval";
                            }
                            else
                            {
                                parser.ReportSyntaxError("Interval constant has an invalid constraint.");
                            }
                        }
                        else
                        {
                            parser.ReportSyntaxError("Interval constant found with an invalid expression.");
                        }
                    }
                    else
                    {
                        // look for the constant in the system constants
                        var             tok = parser.PeekToken();
                        IAnalysisResult sysConst;
                        if (Genero4glAst.SystemConstants.TryGetValue(tok.Value.ToString(), out sysConst))
                        {
                            parser.NextToken();
                            defNode.Literal  = sysConst.Name;
                            defNode.Typename = sysConst.Typename;
                        }
                    }
                }
            }
            return(result);
        }
Exemple #3
0
        public static bool TryGetExpressionNode(IParser parser, out ExpressionNode node, List <TokenKind> breakTokens = null, ExpressionParsingOptions options = null)
        {
            if (options == null)
            {
                options = new ExpressionParsingOptions();
            }
            node = null;
            bool result            = false;
            bool start             = true;
            bool requireExpression = false;

            TokenExpressionNode startingToken = null;

            while (true)
            {
                // First check for allowed pre-expression tokens
                if (_preExpressionTokens.Contains(parser.PeekToken().Kind))
                {
                    parser.NextToken();
                    if (node == null)
                    {
                        node = new TokenExpressionNode(parser.Token);
                    }
                    else
                    {
                        node.AppendExpression(new TokenExpressionNode(parser.Token));
                    }
                    requireExpression = true;
                }

                if (parser.PeekToken(TokenKind.LeftParenthesis))
                {
                    ParenWrappedExpressionNode parenExpr;
                    if (ParenWrappedExpressionNode.TryParseExpression(parser, out parenExpr, options))
                    {
                        if (node == null)
                        {
                            node = parenExpr;
                        }
                        else
                        {
                            node.AppendExpression(parenExpr);
                        }
                        result = true;
                    }
                    else
                    {
                        parser.ReportSyntaxError("Paren-nested expression expected.");
                    }
                }
                else if (parser.PeekToken(TokenKind.LeftBracket))
                {
                    BracketWrappedExpressionNode brackNode;
                    if (BracketWrappedExpressionNode.TryParseNode(parser, out brackNode))
                    {
                        if (node == null)
                        {
                            node = brackNode;
                        }
                        else
                        {
                            node.AppendExpression(brackNode);
                        }
                        result = true;
                    }
                    else
                    {
                        parser.ReportSyntaxError("Bracket-nested expression expected.");
                    }
                }
                else if (parser.PeekToken(TokenCategory.StringLiteral) ||
                         parser.PeekToken(TokenCategory.CharacterLiteral) ||
                         parser.PeekToken(TokenCategory.IncompleteMultiLineStringLiteral))
                {
                    result = true;
                    parser.NextToken();
                    if (node == null)
                    {
                        node = new StringExpressionNode(parser.Token);
                    }
                    else
                    {
                        node.AppendExpression(new StringExpressionNode(parser.Token));
                    }
                }
                else if (parser.PeekToken(TokenCategory.NumericLiteral))
                {
                    result = true;
                    parser.NextToken();
                    if (node == null)
                    {
                        node = new TokenExpressionNode(parser.Token);
                    }
                    else
                    {
                        node.AppendExpression(new TokenExpressionNode(parser.Token));
                    }
                }
                else if (parser.PeekToken(TokenKind.CurrentKeyword))
                {
                    result = true;
                    parser.NextToken();
                    int    currentExprStart = parser.Token.Span.Start;
                    string currentTypeConstraint;
                    if (TypeConstraints.VerifyValidConstraint(parser, out currentTypeConstraint, TokenKind.CurrentKeyword, true))
                    {
                        result = true;
                        StringExpressionNode strExpr = new StringExpressionNode(string.Format("current {0}", currentTypeConstraint));
                        strExpr.StartIndex = currentExprStart;
                        strExpr.EndIndex   = parser.Token.Span.End;
                        if (node == null)
                        {
                            node = strExpr;
                        }
                        else
                        {
                            node.AppendExpression(strExpr);
                        }
                    }
                    else
                    {
                        if (node == null)
                        {
                            node = new TokenExpressionNode(parser.Token);
                        }
                        else
                        {
                            node.AppendExpression(new TokenExpressionNode(parser.Token));
                        }
                    }
                }
                else if (parser.PeekToken(TokenKind.IntervalKeyword))
                {
                    parser.NextToken();
                    TokenExpressionNode intervalNode = new TokenExpressionNode(parser.Token);
                    if (node == null)
                    {
                        node = intervalNode;
                    }
                    else
                    {
                        node.AppendExpression(intervalNode);
                    }
                    if (parser.PeekToken(TokenKind.LeftParenthesis))
                    {
                        parser.NextToken();
                        node.AppendExpression(new TokenExpressionNode(parser.Token));
                        while (!parser.PeekToken(TokenKind.EndOfFile))
                        {
                            parser.NextToken();
                            node.AppendExpression(new TokenExpressionNode(parser.Token));
                            if (parser.Token.Token.Kind == TokenKind.RightParenthesis)
                            {
                                break;
                            }
                        }
                        string intervalString;
                        if (TypeConstraints.VerifyValidConstraint(parser, out intervalString, TokenKind.IntervalKeyword, true))
                        {
                            result = true;
                            node.AppendExpression(new StringExpressionNode(intervalString));
                        }
                        else
                        {
                            parser.ReportSyntaxError("Invalid interval expression found.");
                        }
                    }
                }
                else if (parser.PeekToken(TokenKind.SelectKeyword) && options.AllowNestedSelectStatement)
                {
                    FglStatement selStmt;
                    bool         dummy;
                    if (SqlStatementFactory.TryParseSqlStatement(parser, out selStmt, out dummy))
                    {
                        result = true;
                        if (node == null)
                        {
                            node = new FglStatementExpression(selStmt);
                        }
                        else
                        {
                            node.AppendExpression(new FglStatementExpression(selStmt));
                        }
                    }
                    else
                    {
                        parser.ReportSyntaxError("Invalid select statement found in expression.");
                    }
                }
                else if (parser.PeekToken(TokenCategory.Identifier) ||
                         parser.PeekToken(TokenCategory.Keyword))
                {
                    bool isCustomExpression = false;
                    if (options != null &&
                        options.AdditionalExpressionParsers != null)
                    {
                        ExpressionNode parsedExpr;
                        foreach (var exprParser in options.AdditionalExpressionParsers)
                        {
                            if ((parsedExpr = exprParser(parser)) != null)
                            {
                                result = true;
                                if (node == null)
                                {
                                    node = parsedExpr;
                                }
                                else
                                {
                                    node.AppendExpression(parsedExpr);
                                }
                                isCustomExpression = true;
                            }
                        }
                    }
                    if (!isCustomExpression)
                    {
                        FunctionCallExpressionNode funcCall;
                        FglNameExpression          nonFuncCallName;
                        if (FunctionCallExpressionNode.TryParseExpression(parser, out funcCall, out nonFuncCallName, false, options))
                        {
                            result = true;
                            if (node == null)
                            {
                                node = funcCall;
                            }
                            else
                            {
                                node.AppendExpression(funcCall);
                            }
                        }
                        else if (nonFuncCallName != null)
                        {
                            bool isDatetime = false;
                            var  dtToken    = Tokens.GetToken(nonFuncCallName.Name);
                            if (dtToken != null)
                            {
                                if (TypeConstraints.DateTimeQualifiers.Contains(dtToken.Kind))
                                {
                                    string dtString;
                                    isDatetime = true;
                                    if (TypeConstraints.VerifyValidConstraint(parser, out dtString, TokenKind.DatetimeKeyword, true, dtToken.Kind))
                                    {
                                        result = true;
                                        var strExpr = new StringExpressionNode(dtString);
                                        if (node == null)
                                        {
                                            node = strExpr;
                                        }
                                        else
                                        {
                                            node.AppendExpression(strExpr);
                                        }
                                    }
                                    else
                                    {
                                        isDatetime = false;
                                    }
                                }
                            }

                            if (!isDatetime)
                            {
                                // it's a name expression
                                result = true;
                                if (node == null)
                                {
                                    node = nonFuncCallName;
                                }
                                else
                                {
                                    node.AppendExpression(nonFuncCallName);
                                }
                            }
                        }
                        else
                        {
                            result = true;
                            parser.NextToken();
                            if (node == null)
                            {
                                node = new TokenExpressionNode(parser.Token);
                            }
                            else
                            {
                                node.AppendExpression(new TokenExpressionNode(parser.Token));
                            }
                        }
                    }
                }
                else if (parser.PeekToken(TokenKind.Multiply) && options.AllowStarParam)
                {
                    result = true;
                    parser.NextToken();
                    if (node == null)
                    {
                        node = new TokenExpressionNode(parser.Token);
                    }
                    else
                    {
                        node.AppendExpression(new TokenExpressionNode(parser.Token));
                    }
                }
                else if (parser.PeekToken(TokenKind.QuestionMark) && options.AllowQuestionMark)
                {
                    parser.NextToken();
                    if (node == null)
                    {
                        parser.ReportSyntaxError("Invalid token '?' found in expression.");
                    }
                    else
                    {
                        node.AppendExpression(new TokenExpressionNode(parser.Token));
                    }
                }
                else
                {
                    if (requireExpression)
                    {
                        var tok = parser.PeekToken();
                        if (breakTokens != null && !breakTokens.Contains(tok.Kind))
                        {
                            parser.ReportSyntaxError("Invalid token type found in expression.");
                        }
                        else
                        {
                            parser.ReportSyntaxError("Expression required.");
                        }
                    }
                    break;
                }
                requireExpression = false;

                Token nextTok    = parser.PeekToken();
                bool  isOperator = true;
                while (isOperator && !requireExpression)
                {
                    if ((breakTokens == null ||
                         (breakTokens != null && !breakTokens.Contains(nextTok.Kind))) &&
                        nextTok.Kind >= TokenKind.FirstOperator &&
                        nextTok.Kind <= TokenKind.LastOperator)
                    {
                        parser.NextToken();
                        // TODO: not sure if we want to do more analysis on what operators can start an expression
                        if (node == null)
                        {
                            node = new TokenExpressionNode(parser.Token);
                        }
                        else
                        {
                            node.AppendExpression(new TokenExpressionNode(parser.Token));
                        }

                        switch (parser.Token.Token.Kind)
                        {
                        case TokenKind.LessThan:
                            // check for '<=' or '<>'
                            if (parser.PeekToken(TokenKind.Equals) ||
                                parser.PeekToken(TokenKind.GreaterThan))
                            {
                                parser.NextToken();
                                node.AppendExpression(new TokenExpressionNode(parser.Token));
                            }
                            break;

                        case TokenKind.GreaterThan:
                            // check for '>='
                            if (parser.PeekToken(TokenKind.Equals))
                            {
                                parser.NextToken();
                                node.AppendExpression(new TokenExpressionNode(parser.Token));
                            }
                            break;

                        case TokenKind.Exclamation:
                            // check for '!='
                            if (parser.PeekToken(TokenKind.Equals))
                            {
                                parser.NextToken();
                                node.AppendExpression(new TokenExpressionNode(parser.Token));
                            }
                            else
                            {
                                parser.ReportSyntaxError("Invalid token '!' found in expression.");
                            }
                            break;

                        case TokenKind.Equals:
                            // check for '=='
                            if (parser.PeekToken(TokenKind.Equals))
                            {
                                parser.NextToken();
                                node.AppendExpression(new TokenExpressionNode(parser.Token));
                            }
                            break;

                        case TokenKind.SingleBar:
                            //  check for '||'
                            if (parser.PeekToken(TokenKind.SingleBar))
                            {
                                parser.NextToken();
                                node.AppendExpression(new TokenExpressionNode(parser.Token));
                            }
                            else
                            {
                                parser.ReportSyntaxError("Invalid token '|' found in expression.");
                            }
                            break;
                        }
                        requireExpression = true;
                    }
                    else
                    {
                        // check for non-symbol operators
                        switch (nextTok.Kind)
                        {
                        case TokenKind.DoubleBar:
                        case TokenKind.AsKeyword:
                        case TokenKind.AndKeyword:
                        case TokenKind.OrKeyword:
                        case TokenKind.ModKeyword:
                        case TokenKind.UsingKeyword:
                        case TokenKind.InstanceOfKeyword:
                        case TokenKind.UnitsKeyword:
                        case TokenKind.LikeKeyword:
                        case TokenKind.MatchesKeyword:
                        case TokenKind.ThroughKeyword:
                        case TokenKind.ThruKeyword:
                        case TokenKind.BetweenKeyword:
                        {
                            // require another expression
                            requireExpression = true;
                            parser.NextToken();
                            node.AppendExpression(new TokenExpressionNode(parser.Token));
                        }
                        break;

                        case TokenKind.ClippedKeyword:
                        case TokenKind.SpacesKeyword:
                        {
                            parser.NextToken();
                            node.AppendExpression(new TokenExpressionNode(parser.Token));
                        }
                        break;

                        case TokenKind.IsKeyword:
                        {
                            parser.NextToken();
                            node.AppendExpression(new TokenExpressionNode(parser.Token));
                            if (parser.PeekToken(TokenKind.NotKeyword))
                            {
                                parser.NextToken();
                                node.AppendExpression(new TokenExpressionNode(parser.Token));
                            }
                            if (parser.PeekToken(TokenKind.NullKeyword))
                            {
                                parser.NextToken();
                                node.AppendExpression(new TokenExpressionNode(parser.Token));
                            }
                            else
                            {
                                parser.ReportSyntaxError("NULL keyword required in expression.");
                            }
                        }
                        break;

                        case TokenKind.NotKeyword:
                        {
                            parser.NextToken();
                            node.AppendExpression(new TokenExpressionNode(parser.Token));
                            if (parser.PeekToken(TokenKind.LikeKeyword) ||
                                parser.PeekToken(TokenKind.MatchesKeyword) ||
                                parser.PeekToken(TokenKind.InKeyword))
                            {
                                // require another expression
                                requireExpression = true;
                                parser.NextToken();
                                node.AppendExpression(new TokenExpressionNode(parser.Token));
                            }
                            else
                            {
                                parser.ReportSyntaxError("LIKE or MATCHES keyword required in expression.");
                            }
                        }
                        break;

                        default:
                        {
                            isOperator = false;
                            break;
                        }
                        }
                        if (!isOperator)
                        {
                            break;
                        }
                        else
                        {
                            nextTok = parser.PeekToken();
                            if (nextTok.Kind == TokenKind.EndOfFile)
                            {
                                break;
                            }
                        }
                    }
                }
                if (!requireExpression)
                {
                    break;
                }
            }

            if (result && node != null)
            {
                node.EndIndex = parser.Token.Span.End;
            }

            return(result);
        }