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