override public Token token() { for (;;) { /* Deal with lexed tokens first. */ if (arg != null) { if (arg.hasNext()) { Token tok2 = arg.next(); /* XXX PASTE -> INVALID. */ Debug.Assert(tok2.getType() != Token.M_PASTE, "Unexpected paste token"); return(tok2); } arg = null; } if (!tokens.hasNext()) { return(new Token(Token.EOF, -1, -1, "")); /* End of macro. */ } Token tok = tokens.next(); int idx; switch (tok.getType()) { case Token.M_STRING: /* Use the nonexpanded arg. */ idx = (int)tok.getValue(); return(stringify(tok, args.get(idx))); case Token.M_ARG: /* Expand the arg. */ idx = (int)tok.getValue(); // System.out.println("Pushing arg " + args.get(idx)); arg = args.get(idx).expansion(); break; case Token.M_PASTE: paste(tok); break; default: return(tok); } } /* for */ }
/* At this point, we have consumed the first M_PASTE. * @see Macro#addPaste(Token) */ private void paste(Token ptok) { StringBuilder buf = new StringBuilder(); Token err = null; /* We know here that arg is null or expired, * since we cannot paste an expanded arg. */ int count = 2; for (int i = 0; i < count; i++) { if (!tokens.hasNext()) { /* XXX This one really should throw. */ error(ptok.getLine(), ptok.getColumn(), "Paste at end of expansion"); buf.append(' ').append(ptok.getText()); break; } Token tok = tokens.next(); // System.out.println("Paste " + tok); switch (tok.getType()) { case Token.M_PASTE: /* One extra to paste, plus one because the * paste token didn't count. */ count += 2; ptok = tok; break; case Token.M_ARG: int idx = (int)tok.getValue(); concat(buf, args.get(idx)); break; /* XXX Test this. */ case Token.CCOMMENT: case Token.CPPCOMMENT: break; default: buf.append(tok.getText()); break; } } /* Push and re-lex. */ /* * StringBuilder src = new StringBuilder(); * escape(src, buf); * StringLexerSource sl = new StringLexerSource(src.toString()); */ StringLexerSource sl = new StringLexerSource(buf.toString()); /* XXX Check that concatenation produces a valid token. */ arg = new SourceIterator(sl); }