/******************************************************************************* * Copyright (c) 2008 Scott Stanchfield. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Based on the ANTLR parser generator by Terence Parr, http://antlr.org * Ric Klaren <klaren@cs.utwente.nl> * Scott Stanchfield - Modifications for XML Parsing *******************************************************************************/ package com.javadude.antxr; import java.util.HashMap; import java.util.Map; import java.util.Stack; /** A token stream MUX (multiplexor) knows about n token streams * and can multiplex them onto the same channel for use by token * stream consumer like a parser. This is a way to have multiple * lexers break up the same input stream for a single parser. * Or, you can have multiple instances of the same lexer handle * multiple input streams; this works great for includes. */ public class TokenStreamSelector implements TokenStream { /** The set of inputs to the MUX */ protected Map<String, TokenStream> inputStreamNames; /** The currently-selected token stream input */ protected TokenStream input; /** Used to track stack of input streams */ protected Stack<TokenStream> streamStack = new Stack<TokenStream>(); public TokenStreamSelector() { super(); inputStreamNames = new HashMap<String, TokenStream>(); } public void addInputStream(TokenStream stream, String key) { inputStreamNames.put(key, stream); } /** Return the stream from tokens are being pulled at * the moment. */ public TokenStream getCurrentStream() { return input; } public TokenStream getStream(String sname) { TokenStream stream = inputStreamNames.get(sname); if (stream == null) { throw new IllegalArgumentException("TokenStream " + sname + " not found"); } return stream; } public Token nextToken() throws TokenStreamException { // return input.nextToken(); // keep looking for a token until you don't // get a retry exception. for (; ;) { try { return input.nextToken(); } catch (TokenStreamRetryException r) { // just retry "forever" } } } public TokenStream pop() { TokenStream stream = streamStack.pop(); select(stream); return stream; } public void push(TokenStream stream) { streamStack.push(input); // save current stream select(stream); } public void push(String sname) { streamStack.push(input); select(sname); } /** Abort recognition of current Token and try again. * A stream can push a new stream (for include files * for example, and then retry(), which will cause * the current stream to abort back to this.nextToken(). * this.nextToken() then asks for a token from the * current stream, which is the new "substream." */ public void retry() throws TokenStreamRetryException { throw new TokenStreamRetryException(); } /** Set the stream without pushing old stream */ public void select(TokenStream stream) { input = stream; } public void select(String sname) throws IllegalArgumentException { input = getStream(sname); } }