Пример #1
0
        private static Executable ParseStruct(TokenStream tokens, Executable owner)
        {
            Token structToken     = tokens.PopExpected("struct");
            Token structNameToken = tokens.Pop();

            Parser.VerifyIdentifier(structNameToken);

            tokens.PopExpected("{");

            List <Token>      fieldTokens     = new List <Token>();
            List <Annotation> typeAnnotations = new List <Annotation>();
            bool nextForbidden = false;

            while (!tokens.PopIfPresent("}"))
            {
                if (nextForbidden)
                {
                    tokens.PopExpected("}");                // crash
                }
                Annotation annotation = tokens.IsNext("@") ? AnnotationParser.ParseAnnotation(tokens) : null;

                Token fieldToken = tokens.Pop();
                Parser.VerifyIdentifier(fieldToken);
                nextForbidden = !tokens.PopIfPresent(",");
                fieldTokens.Add(fieldToken);
                typeAnnotations.Add(annotation);
            }

            return(new StructDefinition(structToken, structNameToken, fieldTokens, typeAnnotations, owner));
        }
Пример #2
0
        public static Expression Parse(TokenStream tokens, Executable owner)
        {
            Dictionary <string, Annotation> annotations = null;

            if (tokens.IsNext("@"))
            {
                annotations = new Dictionary <string, Annotation>();
                while (tokens.IsNext("@"))
                {
                    Annotation annotation = AnnotationParser.ParseAnnotation(tokens);
                    annotations[annotation.Type] = annotation;
                }
            }
            Expression output = ParseTernary(tokens, owner);

            output.Annotations = annotations;
            return(output);
        }
Пример #3
0
        private static Executable ParseFunction(Parser parser, TokenStream tokens, Executable nullableOwner)
        {
            bool isStatic =
                nullableOwner != null &&
                nullableOwner is ClassDefinition &&
                tokens.PopIfPresent("static");

            Token functionToken = tokens.PopExpected("function");

            List <Annotation> functionAnnotations = new List <Annotation>();

            while (tokens.IsNext("@"))
            {
                functionAnnotations.Add(AnnotationParser.ParseAnnotation(tokens));
            }

            Token functionNameToken = tokens.Pop();

            Parser.VerifyIdentifier(functionNameToken);

            FunctionDefinition fd = new FunctionDefinition(functionToken, nullableOwner, isStatic, functionNameToken, functionAnnotations, parser.CurrentNamespace);

            tokens.PopExpected("(");
            List <Token>      argNames       = new List <Token>();
            List <Expression> defaultValues  = new List <Expression>();
            List <Annotation> argAnnotations = new List <Annotation>();
            bool optionalArgFound            = false;

            while (!tokens.PopIfPresent(")"))
            {
                if (argNames.Count > 0)
                {
                    tokens.PopExpected(",");
                }

                Annotation annotation   = tokens.IsNext("@") ? AnnotationParser.ParseAnnotation(tokens) : null;
                Token      argName      = tokens.Pop();
                Expression defaultValue = null;
                Parser.VerifyIdentifier(argName);
                if (tokens.PopIfPresent("="))
                {
                    optionalArgFound = true;
                    defaultValue     = ExpressionParser.Parse(tokens, fd);
                }
                else if (optionalArgFound)
                {
                    throw new ParserException(argName, "All optional arguments must come at the end of the argument list.");
                }
                argAnnotations.Add(annotation);
                argNames.Add(argName);
                defaultValues.Add(defaultValue);
            }

            IList <Executable> code = Parser.ParseBlock(parser, tokens, true, fd);

            fd.ArgNames       = argNames.ToArray();
            fd.DefaultValues  = defaultValues.ToArray();
            fd.ArgAnnotations = argAnnotations.ToArray();
            fd.Code           = code.ToArray();

            return(fd);
        }
Пример #4
0
        private static Executable ParseClassDefinition(Parser parser, TokenStream tokens, Executable owner, Token staticToken, Token finalToken)
        {
            Token classToken     = tokens.PopExpected("class");
            Token classNameToken = tokens.Pop();

            Parser.VerifyIdentifier(classNameToken);
            List <Token>  baseClassTokens  = new List <Token>();
            List <string> baseClassStrings = new List <string>();

            if (tokens.PopIfPresent(":"))
            {
                if (baseClassTokens.Count > 0)
                {
                    tokens.PopExpected(",");
                }

                Token  baseClassToken = tokens.Pop();
                string baseClassName  = baseClassToken.Value;

                Parser.VerifyIdentifier(baseClassToken);
                while (tokens.PopIfPresent("."))
                {
                    Token baseClassTokenNext = tokens.Pop();
                    Parser.VerifyIdentifier(baseClassTokenNext);
                    baseClassName += "." + baseClassTokenNext.Value;
                }

                baseClassTokens.Add(baseClassToken);
                baseClassStrings.Add(baseClassName);
            }

            ClassDefinition cd = new ClassDefinition(
                classToken,
                classNameToken,
                baseClassTokens,
                baseClassStrings,
                parser.CurrentNamespace,
                owner,
                staticToken,
                finalToken);

            tokens.PopExpected("{");
            List <FunctionDefinition> methods              = new List <FunctionDefinition>();
            List <FieldDeclaration>   fields               = new List <FieldDeclaration>();
            ConstructorDefinition     constructorDef       = null;
            ConstructorDefinition     staticConstructorDef = null;

            while (!tokens.PopIfPresent("}"))
            {
                Dictionary <string, List <Annotation> > annotations = null;

                while (tokens.IsNext("@"))
                {
                    annotations = annotations ?? new Dictionary <string, List <Annotation> >();
                    Annotation annotation = AnnotationParser.ParseAnnotation(tokens);
                    if (!annotations.ContainsKey(annotation.Type))
                    {
                        annotations[annotation.Type] = new List <Annotation>();
                    }

                    annotations[annotation.Type].Add(annotation);
                }

                if (tokens.IsNext("function") || tokens.AreNext("static", "function"))
                {
                    methods.Add((FunctionDefinition)ExecutableParser.ParseFunction(parser, tokens, cd));
                }
                else if (tokens.IsNext("constructor"))
                {
                    if (constructorDef != null)
                    {
                        throw new ParserException(tokens.Pop(), "Multiple constructors are not allowed. Use optional arguments.");
                    }

                    constructorDef = (ConstructorDefinition)ExecutableParser.ParseConstructor(parser, tokens, cd);

                    if (annotations != null && annotations.ContainsKey("private"))
                    {
                        constructorDef.PrivateAnnotation = annotations["private"][0];
                        annotations["private"].RemoveAt(0);
                    }
                }
                else if (tokens.AreNext("static", "constructor"))
                {
                    tokens.Pop(); // static token
                    if (staticConstructorDef != null)
                    {
                        throw new ParserException(tokens.Pop(), "Multiple static constructors are not allowed.");
                    }

                    staticConstructorDef = (ConstructorDefinition)ExecutableParser.ParseConstructor(parser, tokens, cd);
                }
                else if (tokens.IsNext("field") || tokens.AreNext("static", "field"))
                {
                    fields.Add(ExecutableParser.ParseField(tokens, cd));
                }
                else
                {
                    tokens.PopExpected("}");
                }

                if (annotations != null)
                {
                    foreach (List <Annotation> annotationsOfType in annotations.Values)
                    {
                        if (annotationsOfType.Count > 0)
                        {
                            throw new ParserException(annotationsOfType[0].FirstToken, "Unused or extra annotation.");
                        }
                    }
                }
            }

            cd.Methods           = methods.ToArray();
            cd.Constructor       = constructorDef;
            cd.StaticConstructor = staticConstructorDef;
            cd.Fields            = fields.ToArray();

            return(cd);
        }