Пример #1
0
        /* processes a #define directive */
        private Token define()
        {
            Token	tok = source_token_nonwhite();
            if (tok.getType() != Token.IDENTIFIER) {
            error(tok, "Expected Token.IDENTIFIER");
            return source_skipline(false);
            }
            /* if predefined */

            String			name = tok.getText();
            if ("defined" == name) {
            error(tok, "Cannot redefine name 'defined'");
            return source_skipline(false);
            }

            Macro			m = new Macro(getSource(), name);
            List<String>	args;

            tok = source_token();
            if (tok.getType() == '(') {
            tok = source_token_nonwhite();
            if (tok.getType() != ')') {
                args = new List<String>();
                for (;;) {
                    switch (tok.getType()) {
                        case Token.IDENTIFIER:
                            if(m.isVariadic()) {
                                throw new Exception();
                            }
                            args.Add(tok.getText());
                            break;
                        case Token.ELLIPSIS:
                            m.setVariadic(true);
                            args.Add("__VA_ARGS__");
                            break;
                        case Token.NL:
                        case Token.EOF:
                            error(tok,
                                "Unterminated macro parameter list");
                            return tok;
                        default:
                            error(tok,
                                "error in macro parameters: " +
                                tok.getText());
                            return source_skipline(false);
                    }
                    tok = source_token_nonwhite();
                    switch (tok.getType()) {
                        case ',':
                            break;
                        case Token.ELLIPSIS:
                            tok = source_token_nonwhite();
                            if (tok.getType() != ')')
                                error(tok,
                                    "ellipsis must be on last argument");
                            m.setVariadic(true);
                            goto BREAK_ARGS;
                        case ')':
                            goto BREAK_ARGS;

                        case Token.NL:
                        case Token.EOF:
                            /* Do not skip line. */
                            error(tok,
                                "Unterminated macro parameters");
                            return tok;
                        default:
                            error(tok,
                                "Bad token in macro parameters: " +
                                tok.getText());
                            return source_skipline(false);
                    }
                    tok = source_token_nonwhite();
                }
            BREAK_ARGS:;
            }
            else {
                System.Diagnostics.Debug.Assert(tok.getType() == ')', "Expected ')'");
                args = new List<string>();
            }

            m.setArgs(args);
            }
            else {
            /* For searching. */
            args = new List<string>();
            source_untoken(tok);
            }

            /* Get an expansion for the macro, using IndexOf. */
            bool	space = false;
            bool	paste = false;
            int		idx;

            /* Ensure no space at start. */
            tok = source_token_nonwhite();
            for (;;) {
            switch (tok.getType()) {
                case Token.EOF:
                    goto BREAK_EXPANSION;
                case Token.NL:
                    goto BREAK_EXPANSION;

                case Token.CCOMMENT:
                case Token.CPPCOMMENT:
                    /* XXX This is where we implement GNU's cpp -CC. */
                    // break;
                case Token.WHITESPACE:
                    if (!paste)
                        space = true;
                    break;

                /* Paste. */
                case Token.PASTE:
                    space = false;
                    paste = true;
                    m.addPaste(new Token(Token.M_PASTE,
                            tok.getLine(), tok.getColumn(),
                            "#" + "#", null));
                    break;

                /* Stringify. */
                case '#':
                    if (space)
                        m.addToken(Token.space);
                    space = false;
                    Token	la = source_token_nonwhite();
                    if(la.getType() == Token.IDENTIFIER &&
                        ((idx = args.IndexOf(la.getText())) != -1)) {
                            m.addToken(new Token(Token.M_STRING,
                                la.getLine(), la.getColumn(),
                                "#" + la.getText(),
                                idx));
                    }
                    else {
                        m.addToken(tok);
                        /* Allow for special processing. */
                        source_untoken(la);
                    }
                    break;

                case Token.IDENTIFIER:
                    if (space)
                        m.addToken(Token.space);
                    space = false;
                    paste = false;
                    idx = args.IndexOf(tok.getText());
                    if (idx == -1)
                        m.addToken(tok);
                    else
                        m.addToken(new Token(Token.M_ARG,
                                tok.getLine(), tok.getColumn(),
                                tok.getText(),
                                idx));
                    break;

                default:
                    if (space)
                        m.addToken(Token.space);
                    space = false;
                    paste = false;
                    m.addToken(tok);
                    break;
            }
            tok = source_token();
            }
            BREAK_EXPANSION:

            if (getFeature(Feature.DEBUG))
            System.Console.Error.WriteLine("Defined macro " + m);
            addMacro(m);

            return tok;	/* Token.NL or Token.EOF. */
        }
Пример #2
0
 /**
  * Defines the given name as a macro.
  *
  * The String value is lexed into a token stream, which is
  * used as the macro expansion.
  */
 public void addMacro(String name, String value)
 {
     try {
     Macro				m = new Macro(name);
     StringLexerSource	s = new StringLexerSource(value);
     for (;;) {
         Token	tok = s.token();
         if(tok.getType() == Token.EOF)
             break;
         m.addToken(tok);
     }
     addMacro(m);
     }
     catch (IOException e) {
     throw new LexerException(e);
     }
 }