001: package antlr;
002:
003: /* ANTLR Translator Generator
004: * Project led by Terence Parr at http://www.cs.usfca.edu
005: * Software rights: http://www.antlr.org/license.html
006: */
007:
008: import antlr.collections.impl.BitSet;
009:
010: /**This object filters a token stream coming from a lexer
011: * or another TokenStream so that only certain token channels
012: * get transmitted to the parser.
013: *
014: * Any of the channels can be filtered off as "hidden" channels whose
015: * tokens can be accessed from the parser.
016: */
017: public class TokenStreamHiddenTokenFilter extends
018: TokenStreamBasicFilter implements TokenStream {
019: // protected BitSet discardMask;
020: protected BitSet hideMask;
021:
022: protected CommonHiddenStreamToken nextMonitoredToken;
023:
024: /** track tail of hidden list emanating from previous
025: * monitored token
026: */
027: protected CommonHiddenStreamToken lastHiddenToken;
028:
029: protected CommonHiddenStreamToken firstHidden = null;
030:
031: public TokenStreamHiddenTokenFilter(TokenStream input) {
032: super (input);
033: hideMask = new BitSet();
034: }
035:
036: protected void consume() throws TokenStreamException {
037: nextMonitoredToken = (CommonHiddenStreamToken) input
038: .nextToken();
039: }
040:
041: private void consumeFirst() throws TokenStreamException {
042: consume(); // get first token of input stream
043:
044: // Handle situation where hidden or discarded tokens
045: // appear first in input stream
046: CommonHiddenStreamToken p = null;
047: // while hidden or discarded scarf tokens
048: while (hideMask.member(LA(1).getType())
049: || discardMask.member(LA(1).getType())) {
050: if (hideMask.member(LA(1).getType())) {
051: if (p == null) {
052: p = LA(1);
053: } else {
054: p.setHiddenAfter(LA(1));
055: LA(1).setHiddenBefore(p); // double-link
056: p = LA(1);
057: }
058: lastHiddenToken = p;
059: if (firstHidden == null) {
060: firstHidden = p; // record hidden token if first
061: }
062: }
063: consume();
064: }
065: }
066:
067: public BitSet getDiscardMask() {
068: return discardMask;
069: }
070:
071: /** Return a ptr to the hidden token appearing immediately after
072: * token t in the input stream.
073: */
074: public CommonHiddenStreamToken getHiddenAfter(
075: CommonHiddenStreamToken t) {
076: return t.getHiddenAfter();
077: }
078:
079: /** Return a ptr to the hidden token appearing immediately before
080: * token t in the input stream.
081: */
082: public CommonHiddenStreamToken getHiddenBefore(
083: CommonHiddenStreamToken t) {
084: return t.getHiddenBefore();
085: }
086:
087: public BitSet getHideMask() {
088: return hideMask;
089: }
090:
091: /** Return the first hidden token if one appears
092: * before any monitored token.
093: */
094: public CommonHiddenStreamToken getInitialHiddenToken() {
095: return firstHidden;
096: }
097:
098: public void hide(int m) {
099: hideMask.add(m);
100: }
101:
102: public void hide(BitSet mask) {
103: hideMask = mask;
104: }
105:
106: protected CommonHiddenStreamToken LA(int i) {
107: return nextMonitoredToken;
108: }
109:
110: /** Return the next monitored token.
111: * Test the token following the monitored token.
112: * If following is another monitored token, save it
113: * for the next invocation of nextToken (like a single
114: * lookahead token) and return it then.
115: * If following is unmonitored, nondiscarded (hidden)
116: * channel token, add it to the monitored token.
117: *
118: * Note: EOF must be a monitored Token.
119: */
120: public Token nextToken() throws TokenStreamException {
121: // handle an initial condition; don't want to get lookahead
122: // token of this splitter until first call to nextToken
123: if (LA(1) == null) {
124: consumeFirst();
125: }
126:
127: // we always consume hidden tokens after monitored, thus,
128: // upon entry LA(1) is a monitored token.
129: CommonHiddenStreamToken monitored = LA(1);
130: // point to hidden tokens found during last invocation
131: monitored.setHiddenBefore(lastHiddenToken);
132: lastHiddenToken = null;
133:
134: // Look for hidden tokens, hook them into list emanating
135: // from the monitored tokens.
136: consume();
137: CommonHiddenStreamToken p = monitored;
138: // while hidden or discarded scarf tokens
139: while (hideMask.member(LA(1).getType())
140: || discardMask.member(LA(1).getType())) {
141: if (hideMask.member(LA(1).getType())) {
142: // attach the hidden token to the monitored in a chain
143: // link forwards
144: p.setHiddenAfter(LA(1));
145: // link backwards
146: if (p != monitored) { //hidden cannot point to monitored tokens
147: LA(1).setHiddenBefore(p);
148: }
149: p = lastHiddenToken = LA(1);
150: }
151: consume();
152: }
153: return monitored;
154: }
155: }
|