コード例 #1
0
        public static bool TryParseNode(IParser parser, out FunctionTypeReference defNode, bool isPublic)
        {
            defNode = null;
            bool result = false;

            if (parser.PeekToken(TokenKind.FunctionKeyword))
            {
                result               = true;
                defNode              = new FunctionTypeReference();
                defNode.Arguments    = new Dictionary <string, TypeReference>();
                defNode.Returns      = new List <TypeReference>();
                defNode._orderedArgs = new List <string>();
                defNode._isPublic    = isPublic;
                parser.NextToken();
                defNode.StartIndex      = parser.Token.Span.Start;
                defNode._location       = parser.TokenLocation;
                defNode._typeNameString = defNode.Name;

                // TODO: not sure if a function name is allowable...
                if (parser.PeekToken(TokenKind.LeftParenthesis))
                {
                    parser.NextToken();
                    while (parser.PeekToken(TokenCategory.Keyword) || parser.PeekToken(TokenCategory.Identifier))
                    {
                        VariableDefinitionNode varDefNode = null;
                        if (VariableDefinitionNode.TryParseNode(parser, out varDefNode, null, false, false))
                        {
                            // There should only be one vardef since we're not allowing compact definition
                            foreach (var vardef in varDefNode.VariableDefinitions)
                            {
                                defNode.Arguments.Add(vardef.Name, vardef.Type);
                                defNode._orderedArgs.Add(vardef.Name);
                            }
                        }
                        else
                        {
                            parser.ReportSyntaxError("Failed getting argument type.");
                        }
                        if (parser.PeekToken(TokenKind.Comma))
                        {
                            parser.NextToken();
                        }
                    }

                    if (parser.PeekToken(TokenKind.RightParenthesis))
                    {
                        parser.NextToken();
                        ReturnsStatement returnsStatement;
                        if (ReturnsStatement.TryParseNode(parser, out returnsStatement))
                        {
                            foreach (var ret in returnsStatement.ReturnTypes)
                            {
                                defNode.Returns.Add(ret);
                            }
                        }
                    }
                    else
                    {
                        parser.ReportSyntaxError("Missing right paren in function type signature.");
                    }
                }
                else
                {
                    parser.ReportSyntaxError("A function name cannot exist in a function type specifier");
                }
            }

            return(result);
        }
コード例 #2
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;
            FunctionTypeReference    functionType;
            DictionaryDefinitionNode dictType;

            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 (parser.LanguageVersion >= GeneroLanguageVersion.V310 &&
                     FunctionTypeReference.TryParseNode(parser, out functionType, isPublic) && functionType != null)
            {
                result = true;
                //defNode = new TypeReference();
                //defNode.StartIndex = functionType.StartIndex;
                //defNode.EndIndex = functionType.EndIndex;
                defNode           = functionType;
                defNode._isPublic = isPublic;
                //defNode.Children.Add(functionType.StartIndex, functionType);
                defNode.IsComplete = true;
            }
            else if (parser.LanguageVersion >= GeneroLanguageVersion.V310 &&
                     DictionaryDefinitionNode.TryParseNode(parser, out dictType) && dictType != null)
            {
                result             = true;
                defNode            = new TypeReference();
                defNode.StartIndex = dictType.StartIndex;
                defNode.EndIndex   = dictType.EndIndex;
                defNode._isPublic  = isPublic;
                defNode.Children.Add(dictType.StartIndex, dictType);
                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);
        }