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);
        }
Beispiel #2
0
        public static bool TryParseNode(IParser parser, out ConstantDefNode defNode, out bool matchedBreakSequence, List <List <TokenKind> > breakSequences = null)
        {
            defNode = null;
            bool result = false;

            matchedBreakSequence = false;
            AccessModifier?accMod      = null;
            string         accModToken = null;

            if (parser.PeekToken(TokenKind.PublicKeyword))
            {
                accMod      = AccessModifier.Public;
                accModToken = parser.PeekToken().Value.ToString();
            }
            else if (parser.PeekToken(TokenKind.PrivateKeyword))
            {
                accMod      = AccessModifier.Private;
                accModToken = parser.PeekToken().Value.ToString();
            }

            uint lookAheadBy = (uint)(accMod.HasValue ? 2 : 1);

            if (parser.PeekToken(TokenKind.ConstantKeyword, lookAheadBy))
            {
                result  = true;
                defNode = new ConstantDefNode();
                if (accMod.HasValue)
                {
                    parser.NextToken();
                    defNode.AccessModifier = accMod.Value;
                }
                else
                {
                    defNode.AccessModifier = AccessModifier.Public;
                }

                parser.NextToken(); // move past the Constant keyword
                defNode.StartIndex = parser.Token.Span.Start;

                ConstantDefinitionNode constDef;
                while (true)
                {
                    if (ConstantDefinitionNode.TryParseNode(parser, out constDef, defNode.AccessModifier == AccessModifier.Public) && constDef != null)
                    {
                        defNode.Children.Add(constDef.StartIndex, constDef);
                    }
                    else
                    {
                        break;
                    }

                    if (parser.PeekToken(TokenKind.Comma))
                    {
                        parser.NextToken();
                    }

                    if (breakSequences != null)
                    {
                        bool matchedBreak = false;
                        foreach (var seq in breakSequences)
                        {
                            bool bsMatch        = true;
                            uint peekaheadCount = 1;
                            foreach (var kind in seq)
                            {
                                if (parser.PeekToken(kind, peekaheadCount))
                                {
                                    peekaheadCount++;
                                }
                                else
                                {
                                    bsMatch = false;
                                    break;
                                }
                            }
                            if (bsMatch)
                            {
                                matchedBreak = true;
                                break;
                            }
                        }

                        if (matchedBreak)
                        {
                            matchedBreakSequence = true;
                            break;
                        }
                    }
                }

                if (defNode.Children.Count > 0 &&
                    defNode.Children.All(x => x.Value.IsComplete))
                {
                    defNode.IsComplete = true;
                }
            }
            return(result);
        }