1 /* 2 * Copyright (c) 2012-2018 The ANTLR Project. All rights reserved. 3 * Use of this file is governed by the BSD 3-clause license that 4 * can be found in the LICENSE.txt file in the project root. 5 */ 6 7 module antlr.v4.runtime.CommonTokenStream; 8 9 import std.conv; 10 import std.stdio; 11 import antlr.v4.runtime.BufferedTokenStream; 12 import antlr.v4.runtime.Token; 13 import antlr.v4.runtime.TokenConstantDefinition; 14 import antlr.v4.runtime.TokenSource; 15 16 // Class CommonTokenStream 17 /** 18 * This class extends {@link BufferedTokenStream} with functionality to filter 19 * token streams to tokens on a particular channel (tokens where 20 * {@link Token#getChannel} returns a particular value). 21 * <p> 22 * This token stream provides access to all tokens by index or when calling 23 * methods like {@link #getText}. The channel filtering is only used for code 24 * accessing tokens via the lookahead methods {@link #LA}, {@link #LT}, and 25 * {@link #LB}.</p> 26 * 27 * <p> 28 * By default, tokens are placed on the default channel 29 * ({@link Token#DEFAULT_CHANNEL}), but may be reassigned by using the 30 * {@code ->channel(HIDDEN)} lexer command, or by using an embedded action to 31 * call {@link Lexer#setChannel}. 32 * </p> 33 * 34 * <p> 35 * Note: lexer rules which use the {@code ->skip} lexer command or call 36 * {@link Lexer#skip} do not produce tokens at all, so input text matched by 37 * such a rule will not be available as part of the token stream, regardless of 38 * channel.</p> 39 */ 40 class CommonTokenStream : BufferedTokenStream 41 { 42 43 /** 44 * Specifies the channel to use for filtering tokens. 45 * 46 * <p> 47 * The default value is {@link Token#DEFAULT_CHANNEL}, which matches the 48 * default channel assigned to tokens created by the lexer.</p> 49 */ 50 protected int channel = TokenConstantDefinition.DEFAULT_CHANNEL; 51 52 /** 53 * Constructs a new {@link CommonTokenStream} using the specified token 54 * source and the default token channel ({@link Token#DEFAULT_CHANNEL}). 55 * 56 * @param tokenSource The token source. 57 */ 58 public this(TokenSource tokenSource) 59 { 60 super(tokenSource); 61 } 62 63 /** 64 * Constructs a new {@link CommonTokenStream} using the specified token 65 * source and filtering tokens to the specified channel. Only tokens whose 66 * {@link Token#getChannel} matches {@code channel} or have the 67 * {@link Token#getType} equal to {@link Token#EOF} will be returned by the 68 * token stream lookahead methods. 69 * 70 * @param tokenSource The token source. 71 * @param channel The channel to use for filtering tokens. 72 */ 73 public this(TokenSource tokenSource, int channel) 74 { 75 this(tokenSource); 76 this.channel = channel; 77 } 78 79 /** 80 * @uml 81 * @override 82 */ 83 protected override int adjustSeekIndex(int i) 84 { 85 return nextTokenOnChannel(i, channel); 86 } 87 88 /** 89 * @uml 90 * @override 91 */ 92 protected override Token LB(int k) 93 { 94 if (k == 0 || (index - k) < 0 ) return null; 95 96 int i = index; 97 int n = 1; 98 // find k good tokens looking backwards 99 while (n <= k && i > 0) { 100 // skip off-channel tokens 101 i = previousTokenOnChannel(i - 1, channel); 102 n++; 103 } 104 if (i < 0) return null; 105 return tokens[i]; 106 } 107 108 /** 109 * @uml 110 * @override 111 */ 112 public override Token LT(int k) 113 { 114 debug 115 writefln("enter LT(%s) on channel = %s, p = %s", k, channel, index); 116 lazyInit(); 117 if (k == 0 ) return null; 118 if (k < 0) return LB(-k); 119 int i = index; 120 int n = 1; // we know tokens[p] is a good one 121 // find k good tokens 122 while (n < k) { 123 // skip off-channel tokens, but make sure to not look past EOF 124 if (sync(i + 1)) { 125 i = nextTokenOnChannel(i + 1, channel); 126 } 127 n++; 128 } 129 // if ( i>range ) range = i; 130 debug 131 writefln("enter end LT(%s): %s", i, tokens[i]); 132 return tokens[i]; 133 } 134 135 /** 136 * Count EOF just once. 137 */ 138 public int getNumberOfOnChannelTokens() 139 { 140 int n = 0; 141 fill(); 142 foreach (t; tokens) { 143 if (t.getChannel == channel) 144 n++; 145 if (t.getType == TokenConstantDefinition.EOF) 146 break; 147 } 148 return n; 149 } 150 151 }