Ejemplo n.º 1
0
        /***
         *   Precondition: tokens.Current.Type == TokenType.IDENTIFIER || MAYBE_MACRO
         *   Postcondition: tokens.Current is fully reduced (i.e. not a macro, and not a definition)
         *   Returns: true iff tokens was actually expanded.
         */
        public bool ExpandIdentifier(MergeableGenerator <Token> tokens, ImmutableStack <Closure> scopes)
        {
            bool ret = false;

            //Macros and Definitions.
            if (tokens.Current.Type == TokenType.MAYBE_MACRO && Macros.ContainsName(tokens.Current.Content))
            {
                Token head = tokens.Current;
                tokens.MoveNext();
                IList <IList <Token> > parameters = ParseMacroParamList(tokens);
                if (Macros.HasMacro(head.Content, parameters.Count))
                {
                    tokens.PrependEnumerator(Macros.GetMacro(head.Content, parameters.Count).ApplyMacro(head, parameters, scopes).GetEnumerator());
                }
                else
                {
                    Error(head.Location, System.String.Format("No overload of {0} with {1} parameters.", head.Content, parameters.Count));
                }
                return(true);
            }
            else if (tokens.Current.Type == TokenType.MAYBE_MACRO)
            {
                Token head = tokens.Current;
                tokens.MoveNext();
                tokens.PutBack(new Token(TokenType.IDENTIFIER, head.Location, head.Content));
                return(true);
            }
            else if (Definitions.ContainsKey(tokens.Current.Content))
            {
                Token head = tokens.Current;
                tokens.MoveNext();
                tokens.PrependEnumerator(Definitions[head.Content].ApplyDefinition(head).GetEnumerator());
                return(true);
            }

            return(ret);
        }
Ejemplo n.º 2
0
        public Maybe <ILineNode> ParseLine(MergeableGenerator <Token> tokens, ImmutableStack <Closure> scopes)
        {
            if (IsIncluding)
            {
                if (tokens.Current.Type == TokenType.NEWLINE || tokens.Current.Type == TokenType.SEMICOLON)
                {
                    tokens.MoveNext();
                    return(new Nothing <ILineNode>());
                }
                head = tokens.Current;
                switch (head.Type)
                {
                case TokenType.IDENTIFIER:
                case TokenType.MAYBE_MACRO:
                    if (ExpandIdentifier(tokens, scopes))
                    {
                        return(ParseLine(tokens, scopes));
                    }
                    else
                    {
                        tokens.MoveNext();
                        if (tokens.Current.Type == TokenType.COLON)
                        {
                            tokens.MoveNext();
                            if (scopes.Head.HasLocalLabel(head.Content))
                            {
                                Warning(head.Location, "Label already in scope, ignoring: " + head.Content);    //replacing: " + head.Content);
                            }
                            else if (!IsValidLabelName(head.Content))
                            {
                                Error(head.Location, "Invalid label name " + head.Content + '.');
                            }
                            else
                            {
                                scopes.Head.AddLabel(head.Content, CurrentOffset);
                            }

                            return(new Nothing <ILineNode>());
                        }
                        else
                        {
                            tokens.PutBack(head);
                            return(ParseStatement(tokens, scopes));
                        }
                    }

                case TokenType.OPEN_BRACE:
                    return(new Just <ILineNode>(ParseBlock(tokens, new ImmutableStack <Closure>(new Closure(), scopes))));

                case TokenType.PREPROCESSOR_DIRECTIVE:
                    return(ParsePreprocessor(tokens, scopes));

                case TokenType.OPEN_BRACKET:
                    Error(head.Location, "Unexpected list literal.");
                    IgnoreRestOfLine(tokens);
                    break;

                case TokenType.NUMBER:
                case TokenType.OPEN_PAREN:
                    Error(head.Location, "Unexpected mathematical expression.");
                    IgnoreRestOfLine(tokens);
                    break;

                default:
                    tokens.MoveNext();
                    Error(head.Location, System.String.Format("Unexpected token: {0}: {1}", head.Type, head.Content));
                    IgnoreRestOfLine(tokens);
                    break;
                }
                return(new Nothing <ILineNode>());
            }
            else
            {
                bool hasNext = true;
                while (tokens.Current.Type != TokenType.PREPROCESSOR_DIRECTIVE && (hasNext = tokens.MoveNext()))
                {
                    ;
                }
                if (hasNext)
                {
                    return(ParsePreprocessor(tokens, scopes));
                }
                else
                {
                    Error(null, System.String.Format("Missing {0} endif(s).", Inclusion.Count));
                    return(new Nothing <ILineNode>());
                }
            }
        }