Beispiel #1
0
        protected override FunctionDefinition MaybeParseFunctionDefinition(
            TokenStream tokens,
            Node owner,
            FileScope fileScope,
            AnnotationCollection annotations,
            ModifierCollection modifiers)
        {
            TokenStream.StreamState tss = tokens.RecordState();
            AType returnType            = this.parser.TypeParser.TryParse(tokens);

            if (returnType == null)
            {
                return(null);
            }
            Token functionName = tokens.PopIfWord();

            if (functionName == null)
            {
                tokens.RestoreState(tss);
                return(null);
            }

            if (tokens.IsNext("("))
            {
                tokens.RestoreState(tss);
                return(this.ParseFunction(tokens, owner as TopLevelEntity, fileScope, modifiers, annotations));
            }

            tokens.RestoreState(tss);
            return(null);
        }
        protected override AType MaybeParseCastPrefix(TokenStream tokens)
        {
            TokenStream.StreamState tss = tokens.RecordState();
            if (tokens.PopIfPresent("("))
            {
                AType output = this.parser.TypeParser.TryParse(tokens);
                if (output != null)
                {
                    if (tokens.PopIfPresent(")"))
                    {
                        if (!tokens.HasMore)
                        {
                            return(output);                 // let the next thing throw an error
                        }
                        if (output.Generics.Length > 0)
                        {
                            return(output);
                        }
                        switch (output.RootType)
                        {
                        case "int":
                        case "bool":
                        case "float":
                        case "string":
                        case "object":
                            return(output);
                        }
                        Token nextToken = tokens.Peek();
                        switch (nextToken.Type)
                        {
                        case TokenType.NUMBER:
                        case TokenType.STRING:
                        case TokenType.WORD:
                            return(output);

                        case TokenType.KEYWORD:
                            switch (nextToken.Value)
                            {
                            case "this":
                            case "base":
                                return(output);
                            }
                            break;

                        case TokenType.PUNCTUATION:
                            if (tokens.IsNext("("))
                            {
                                return(output);
                            }
                            break;
                        }
                    }
                }
            }
            tokens.RestoreState(tss);
            return(null);
        }
Beispiel #3
0
 public override AType TryParse(TokenStream tokens)
 {
     TokenStream.StreamState startIndex = tokens.RecordState();
     bool useMultichar = tokens.IsMultiCharTokensEnabled;
     tokens.IsMultiCharTokensEnabled = false;
     AType type = this.ParseImpl(tokens);
     tokens.IsMultiCharTokensEnabled = useMultichar;
     if (type == null)
     {
         tokens.RestoreState(startIndex);
     }
     return type;
 }
Beispiel #4
0
        private AType ParseImplRoot(TokenStream tokens)
        {
            switch (tokens.PeekValue())
            {
            // Don't even try to parse generics or namespaces on primitive types.
            case "int":
            case "bool":
            case "double":
            case "string":
                SIMPLE_TOKEN_LIST[0] = tokens.Pop();
                return(new AType(SIMPLE_TOKEN_LIST, EMPTY_TYPE_LIST));
            }

            Token firstToken = tokens.PopIfWord();

            if (firstToken != null)
            {
                List <Token> rootType = new List <Token>()
                {
                    firstToken
                };
                while (tokens.PopIfPresent("."))
                {
                    TokenStream.StreamState tss = tokens.RecordState();
                    Token next = tokens.PopIfWord();
                    if (next == null)
                    {
                        tokens.RestoreState(tss);
                        break;
                    }
                    else
                    {
                        rootType.Add(next);
                    }
                }
                IList <AType> generics = EMPTY_TYPE_LIST;
                if (tokens.IsNext("<"))
                {
                    TokenStream.StreamState tss = tokens.RecordState();
                    generics = this.ParseGenerics(tokens);
                    if (generics.Count == 0)
                    {
                        tokens.RestoreState(tss);
                    }
                }
                return(new AType(rootType, generics));
            }
            return(null);
        }
Beispiel #5
0
 protected override bool IsForEachLoopParenthesisContents(TokenStream tokens)
 {
     TokenStream.StreamState tss = tokens.RecordState();
     try
     {
         if (tokens.PopIfWord() == null)
         {
             return(false);
         }
         return(tokens.IsNext(":"));
     }
     finally
     {
         tokens.RestoreState(tss);
     }
 }
        protected override Assignment MaybeParseTypedVariableDeclaration(TokenStream tokens, Node owner)
        {
            TokenStream.StreamState tss        = tokens.RecordState();
            AType possiblyAVariableDeclaration = this.parser.TypeParser.TryParse(tokens);

            if (possiblyAVariableDeclaration != null)
            {
                AType variableDeclarationType = possiblyAVariableDeclaration;
                Token variableToken           = tokens.PopIfWord();
                if (variableToken != null)
                {
                    // This is a variable declaration.
                    Expression assignmentValue   = null;
                    Token      assignmentOpToken = tokens.Peek();
                    if (tokens.PopIfPresent("="))
                    {
                        assignmentValue = this.parser.ExpressionParser.Parse(tokens, owner);
                    }
                    else if (tokens.IsNext(";"))
                    {
                        return(new Assignment(
                                   new Variable(variableToken, variableToken.Value, owner),
                                   variableDeclarationType,
                                   assignmentOpToken,
                                   Ops.EQUALS,
                                   null,
                                   owner));
                    }

                    if (assignmentValue != null)
                    {
                        return(new Assignment(
                                   new Variable(variableToken, variableToken.Value, owner),
                                   variableDeclarationType,
                                   assignmentOpToken,
                                   assignmentValue,
                                   owner));
                    }
                }
            }

            tokens.RestoreState(tss);
            return(null);
        }
Beispiel #7
0
        protected override void ParseClassMember(
            TokenStream tokens,
            FileScope fileScope,
            ClassDefinition classDef,
            IList <FunctionDefinition> methodsOut,
            IList <FieldDefinition> fieldsOut,
            IList <PropertyDefinition> propertiesOut)
        {
            AnnotationCollection annotations = this.parser.AnnotationParser.ParseAnnotations(tokens);
            ModifierCollection   modifiers   = ModifierCollection.Parse(tokens);

            if (tokens.IsNext(this.parser.Keywords.CONSTRUCTOR))
            {
                if (modifiers.HasStatic)
                {
                    if (classDef.StaticConstructor != null)
                    {
                        throw new ParserException(tokens.Pop(), "Multiple static constructors are not allowed.");
                    }
                    classDef.StaticConstructor = this.ParseConstructor(tokens, classDef, modifiers, annotations);
                }
                else
                {
                    if (classDef.Constructor != null)
                    {
                        throw this.parser.GenerateParseError(
                                  ErrorMessages.CLASS_CANNOT_HAVE_MULTIPLE_CONSTRUCTORS,
                                  tokens.Pop());
                    }
                    classDef.Constructor = this.ParseConstructor(tokens, classDef, modifiers, annotations);
                }
            }
            else if (tokens.IsNext(this.parser.Keywords.CLASS))
            {
                throw new ParserException(tokens.Pop(), "Nested classes are not currently supported.");
            }
            else
            {
                // Parsing the type and then throwing it away is a little wasteful, but feels less weird than parsing
                // the type here and passing it into ParseFunction()/ParseField(). ParseX() should ParseX from the start.
                TokenStream.StreamState fieldOrFunctionStart = tokens.RecordState();
                AType fieldOrFunctionType = this.parser.TypeParser.TryParse(tokens);
                Token tokenAfterName      = fieldOrFunctionType != null?tokens.PeekAhead(1) : null;

                tokens.RestoreState(fieldOrFunctionStart);

                if (tokenAfterName == null)
                {
                    tokens.PopExpected("}");                         // intentionally induce error
                }
                switch (tokenAfterName.Value)
                {
                case "=":
                case ";":
                    fieldsOut.Add(this.ParseField(tokens, classDef, modifiers, annotations));
                    break;

                case "(":
                    methodsOut.Add(this.ParseFunction(tokens, classDef, fileScope, modifiers, annotations));
                    break;

                case "{":
                    // TODO(acrylic): properties should be implemented in Acrylic, just not yet.
                    tokens.PopExpected("}");     // intentionally induce error
                    break;

                default:
                    tokens.PopExpected("}");     // intentionally induce error
                    break;
                }
            }

            // TODO: check for annotations that aren't used.
            // https://github.com/blakeohare/crayon/issues/305
        }