Java Reference
In-Depth Information
own source. Thus we repeatedly digest characters. If the current character is a
closing quote, we are done. If it is a newline, we have an unterminated charac-
ter or string constant. And if it is a backslash, we digest an extra character
without examining it.
Once we've written the skipping routine, writing
getNextOpenClose
is eas-
ier. The bulk of the logic is deferred to
processSlash
. If the current character is
a
/
, we read a second character to see whether we have a comment. If so, we
call
skipComment
; if not, we undo the second read. If we have a quote, we call
skipQuote
. If we have an opening or closing symbol, we can return. Other-
wise, we keep reading until we eventually run out of input or find an opening
or closing symbol. Both
getNextOpenClose
and
processSlash
are shown in
Figure 11.7.
The
getLineNumber
and
getErrorCount
methods are one-liners that return
the values of the corresponding data members and are shown in Figure 11.2.
We discuss the
getNextID
routine in Section 12.2.2 when it is needed.
In the
Balance
class, the balanced symbol algorithm requires that we place
opening symbols on a stack. In order to print diagnostics, we store a line num-
ber with each symbol, as shown previously in the
Symbol
nested class at lines
34 to 44 in Figure 11.3.
The
checkBalance
routine is implemented as shown in Figure 11.8. It fol-
lows the algorithm description almost verbatim. A stack that stores pending
opening symbols is declared at line 9. Opening symbols are pushed onto the
stack with the current line number. When a closing symbol is encountered and
the stack is empty, the closing symbol is extraneous; otherwise, we remove
the top item from the stack and verify that the opening symbol that was on the
stack matches the closing symbol just read. To do so we use the
checkMatch
routine, which is shown in Figure 11.9. Once the end of input is encountered,
any symbols on the stack are unmatched; they are repeatedly output in the
while
loop that begins at line 40. The total number of errors detected is then
returned.
The current implementation allows multiple calls to
checkBalance
. How-
ever, if the input stream is not reset externally, all that happens is that the end
of the file is immediately detected and we return immediately. We can add
functionality to the
Tokenizer
class, allowing it to change the stream source,
and then add functionality to the
Balance
class to change the input stream
(passing on the change to the
Tokenizer
class). We leave this task for you to do
as Exercise 11.9.
Figure 11.10 shows that we expect a
Balance
object to be created and then
checkBalance
to be invoked. In our example, if there are no command-line argu-
ments, the associated
Reader
is attached to
System.in
(via an
InputStreamReader
bridge); otherwise, we repeatedly use
Reader
s associated with the files given in
the command-line argument list.
The
checkBalance
routine does all the
algorithmic work.
Search WWH ::
Custom Search