Esempio n. 1
0
        private bool ParseDeclaration(ref ASTNode node)
        {
            AttributeNode             attrNode   = null;
            LightList <AttributeNode> attributes = LightList <AttributeNode> .Get();

            while (ParseAttribute(ref attrNode))
            {
                attributes.Add(attrNode);
                if (tokenStream.Current != ExpressionTokenType.ArrayAccessOpen)
                {
                    break;
                }
            }

            if (attributes.size == 0)
            {
                LightList <AttributeNode> .Release(ref attributes);
            }

            if (tokenStream.Current != ExpressionTokenType.Identifier)
            {
                return(false);
            }

            // modifiers? -> returnType -> name -> signature -> openBrace * closeBrace

            tokenStream.Save();

            bool isStatic = false;

            if (tokenStream.Current == "static")
            {
                isStatic = true;
                tokenStream.Advance();
            }

            ExpressionParser            parser    = new ExpressionParser(tokenStream);
            StructList <LambdaArgument> signature = null;
            TypeLookup typeLookup = default;

            if (!parser.ParseTypePath(ref typeLookup))
            {
                goto fail;
            }

            tokenStream.Set(parser.GetTokenPosition());
            parser.Release(false);

            if (tokenStream.Current != ExpressionTokenType.Identifier)
            {
                goto fail;
            }

            string name = tokenStream.Current.value;

            tokenStream.Advance();

            // if semi colon then we have a field!
            if (tokenStream.Current == ExpressionTokenType.SemiColon)
            {
                tokenStream.Advance();
                node = new FieldNode()
                {
                    name       = name,
                    isStatic   = isStatic,
                    attributes = attributes,
                    typeLookup = typeLookup
                };
                return(true);
            }

            if (tokenStream.Current != ExpressionTokenType.ParenOpen)
            {
                goto fail;
            }

            signature = StructList <LambdaArgument> .Get();

            if (tokenStream.NextTokenIs(ExpressionTokenType.ParenClose))
            {
                tokenStream.Advance(2);
            }
            else
            {
                int matchingIndex = tokenStream.FindMatchingIndex(ExpressionTokenType.ParenOpen, ExpressionTokenType.ParenClose);

                if (matchingIndex == -1)
                {
                    goto fail;
                }

                TokenStream subStream = tokenStream.AdvanceAndReturnSubStream(matchingIndex);
                subStream.Advance();
                tokenStream.Advance();
                if (!ExpressionParser.ParseSignature(subStream, signature))
                {
                    goto fail;
                }

                for (int i = 0; i < signature.size; i++)
                {
                    if (signature.array[i].type == null)
                    {
                        throw new ParseException($"When defining a method you must specify a type for all arguments. Found identifier {signature.array[i].identifier} but no type was given.");
                    }
                }
            }

            if (tokenStream.Current != ExpressionTokenType.ExpressionOpen)
            {
                goto fail;
            }

            BlockNode block = ParseBlock();

            node = new MethodNode()
            {
                body             = block,
                returnTypeLookup = typeLookup,
                attributes       = attributes,
                name             = name,
                isStatic         = isStatic,
                signatureList    = signature != null?signature.ToArray() : s_EmptySignature
            };

            StructList <LambdaArgument> .Release(ref signature);

            parser.Release(false);

            return(true);

fail:
            {
                tokenStream.Restore();
                parser.Release(false);
                typeLookup.Release();
                signature?.Release();
                return(false);
            }
        }
Esempio n. 2
0
        private bool ParseLocalVariableDeclaration(ref ASTNode node)
        {
            ExpressionParser parser     = default;
            TypeLookup       typeLookup = default;

            if (tokenStream.Current == ExpressionTokenType.Var)
            {
                if (!tokenStream.NextTokenIs(ExpressionTokenType.Identifier))
                {
                    return(false);
                }

                tokenStream.Advance();
            }
            else if (tokenStream.Current == ExpressionTokenType.Identifier)
            {
                tokenStream.Save();
                parser = new ExpressionParser(tokenStream);
                if (!parser.ParseTypePath(ref typeLookup))
                {
                    goto fail;
                }

                tokenStream.Set(parser.GetTokenPosition());
                parser.Release(false);
            }
            else
            {
                goto fail;
            }

            if (tokenStream.Current != ExpressionTokenType.Identifier)
            {
                goto fail;
            }

            string name = tokenStream.Current.value;

            tokenStream.Advance();

            if (tokenStream.Current == ExpressionTokenType.SemiColon)
            {
                tokenStream.Advance();
                node = new LocalVariableNode()
                {
                    name       = name,
                    typeLookup = typeLookup // will be default for var
                };
                return(true);
            }

            if (tokenStream.Current == ExpressionTokenType.Assign)
            {
                // todo -- would fail on this: var x = new F(() => { return x; });

                tokenStream.Advance();

                ASTNode expression = null;
                if (!ParseTerminatedExpression(ref expression))
                {
                    goto fail;
                }

                node = new LocalVariableNode()
                {
                    name       = name,
                    value      = expression,
                    typeLookup = typeLookup // will be default for var
                };

                return(true);
            }

fail:
            {
                parser.Release(false);
                typeLookup.Release();
                tokenStream.Restore();
                return(false);
            }
        }