| LookaheadScanner.java |
1 // Copyright 2012- Bill Campbell, Swami Iyer and Bahar Akbal-Delibas
2
3 package jminusminus;
4
5 import java.io.FileNotFoundException;
6 import java.util.Stack;
7 import java.util.Vector;
8
9 /**
10 * A lexical analyzer for j-- that interfaces with the hand-written parser (Parser). It
11 * provides a backtracking mechanism, and makes use of the underlying hand-written scanner
12 * (Scanner).
13 */
14 class LookaheadScanner {
15 // The underlying hand-written scanner.
16 private Scanner scanner;
17
18 // Backtracking queue.
19 private Vector<TokenInfo> backtrackingQueue;
20
21 // Token queue.
22 private Vector<TokenInfo> nextQueue;
23
24 // Stack of token queues for nested lookahead.
25 private Stack<Vector<TokenInfo>> queueStack;
26
27 // Whether we are looking ahead.
28 public boolean isLookingAhead;
29
30 // Previous token.
31 private TokenInfo previousToken;
32
33 // Current token.
34 private TokenInfo token;
35
36 /**
37 * Constructs a LookaheadScanner.
38 *
39 * @param fileName the name of the file containing the source.
40 * @throws FileNotFoundException when the named file cannot be found.
41 */
42 public LookaheadScanner(String fileName) throws FileNotFoundException {
43 scanner = new Scanner(fileName);
44 backtrackingQueue = new Vector<TokenInfo>();
45 nextQueue = new Vector<TokenInfo>();
46 queueStack = new Stack<Vector<TokenInfo>>();
47 isLookingAhead = false;
48 }
49
50 /**
51 * Scans to the next token in the input.
52 */
53 public void next() {
54 previousToken = token;
55 if (backtrackingQueue.size() == 0) {
56 token = scanner.getNextToken();
57 } else {
58 token = backtrackingQueue.remove(0);
59 }
60 if (isLookingAhead) {
61 nextQueue.add(token);
62 }
63 }
64
65 /**
66 * Records the current position in the input, so that we can start looking ahead in the input
67 * (and later return to this position) --- the current and subsequent tokens are queued until
68 * returnToPosition() is invoked.
69 */
70 public void recordPosition() {
71 isLookingAhead = true;
72 queueStack.push(nextQueue);
73 nextQueue = new Vector<TokenInfo>();
74 nextQueue.add(previousToken);
75 nextQueue.add(token);
76 }
77
78 /**
79 * Returns to the previously recorded position in the input stream of tokens.
80 */
81 public void returnToPosition() {
82 while (backtrackingQueue.size() > 0) {
83 nextQueue.add(backtrackingQueue.remove(0));
84 }
85 backtrackingQueue = nextQueue;
86 nextQueue = queueStack.pop();
87 isLookingAhead = !(queueStack.empty());
88
89 // Restore previous and current tokens
90 previousToken = backtrackingQueue.remove(0);
91 token = backtrackingQueue.remove(0);
92 }
93
94 /**
95 * Returns the current token.
96 *
97 * @return the current token.
98 */
99 public TokenInfo token() {
100 return token;
101 }
102
103 /**
104 * Returns the previous token.
105 *
106 * @return the previous token.
107 */
108 public TokenInfo previousToken() {
109 return previousToken;
110 }
111
112 /**
113 * Returns true if an error has occurred, and false otherwise.
114 *
115 * @return true if an error has occurred, and false otherwise.
116 */
117 public boolean errorHasOccured() {
118 return scanner.errorHasOccurred();
119 }
120
121 /**
122 * Returns the name of the source file.
123 *
124 * @return the name of the source file.
125 */
126 public String fileName() {
127 return scanner.fileName();
128 }
129 }
130