@@ -187,58 +187,84 @@ public ParserContext getContext() {
187187 return context ;
188188 }
189189
190- public boolean hasNext () {
191- return this .tokenizer .peek () != null ;
190+ private PrologTermReadResult deferredReadTerm ;
191+ 192+ private static boolean isComment (final TokenizerResult tokenizerResult ) {
193+ return tokenizerResult != null
194+ && tokenizerResult .getResult ().getType () == TermType .ATOM
195+ && (tokenizerResult .getResult ().getQuotation () == Quotation .COMMENT_LINE
196+ || tokenizerResult .getResult ().getQuotation () == Quotation .COMMENT_BLOCK );
197+ }
198+ 199+ private void notifyCommentTokenListeners (final TokenizerResult commentToken ) {
200+ for (final TokenizedCommentListener listener : this .commentTokenListeners ) {
201+ listener .onCommentToken (this , commentToken );
202+ }
192203 }
193204
194- private TokenizerResult readNextTokenCommentAware () {
205+ private TokenizerResult extractNextTokenCommentAware () {
195206 TokenizerResult result ;
196- if (this .commentsAsAtoms ) {
197- while (true ) {
198- result = this .tokenizer .readNextToken ();
199- if (result != null
200- && (result .getResult ().getQuotation () == Quotation .COMMENT_BLOCK ||
201- result .getResult ().getQuotation () == Quotation .COMMENT_LINE )) {
202- for (final TokenizedCommentListener listener : this .commentTokenListeners ) {
203- listener .onCommentToken (this , result );
204- }
205- } else {
206- break ;
207- }
208- }
209- } else {
207+ while (true ) {
210208 result = this .tokenizer .readNextToken ();
209+ if (isComment (result )) {
210+ this .notifyCommentTokenListeners (result );
211+ } else {
212+ break ;
213+ }
211214 }
212215 return result ;
213216 }
214217
215- public PrologTerm next () {
216- final PrologTerm found = readBlock (OPERATORS_PHRASE );
217- if (found == null ) {
218- throw new NoSuchElementException ("No terms in source" );
219- } else {
220- final TokenizerResult endAtom = this .readNextTokenCommentAware ();
221- if (endAtom == null || !endAtom .getResult ().getText ().equals (OPERATOR_DOT .getText ())) {
222- throw new PrologParserException ("End operator is not found" ,
223- this .tokenizer .getLine (),
224- this .tokenizer .getPos ());
218+ private PrologTermReadResult extractNextBlockAndWrapError () {
219+ try {
220+ final PrologTerm found = this .readBlock (OPERATORS_PHRASE );
221+ if (found == null ) {
222+ throw new NoSuchElementException ("No terms in source" );
223+ } else {
224+ final TokenizerResult endAtom = this .extractNextTokenCommentAware ();
225+ if (endAtom == null || !endAtom .getResult ().getText ().equals (OPERATOR_DOT .getText ())) {
226+ throw new PrologParserException ("End operator is not found" ,
227+ this .tokenizer .getLine (),
228+ this .tokenizer .getPos ());
229+ }
225230 }
231+ return new PrologTermReadResult (found , null );
232+ } catch (RuntimeException ex ) {
233+ return new PrologTermReadResult (null , ex );
234+ }
235+ }
236+ 237+ public boolean hasNext () {
238+ if (this .deferredReadTerm == null ) {
239+ this .deferredReadTerm = this .extractNextBlockAndWrapError ();
226240 }
227- return found ;
241+ return this .deferredReadTerm .isPresented ();
242+ }
243+ 244+ public PrologTerm next () {
245+ if (this .deferredReadTerm == null ) {
246+ this .deferredReadTerm = this .extractNextBlockAndWrapError ();
247+ }
248+ final PrologTerm result ;
249+ try {
250+ result = this .deferredReadTerm .getResult ();
251+ } finally {
252+ this .deferredReadTerm = null ;
253+ }
254+ return result ;
228255 }
229256
230257 private PrologStruct readStruct (final PrologTerm functor ) {
231258 final List <PrologTerm > listOfAtoms = new ArrayList <>();
232259 PrologStruct result ;
233260 boolean active = true ;
234261 while (active ) {
235- final PrologTerm block = readBlock (OPERATORS_INSIDE_STRUCT );
236- 262+ final PrologTerm block = this .readBlock (OPERATORS_INSIDE_STRUCT );
237263 if (block == null ) {
238264 return null ;
239265 }
240266
241- final TokenizerResult nextAtom = this .readNextTokenCommentAware ();
267+ final TokenizerResult nextAtom = this .extractNextTokenCommentAware ();
242268 if (nextAtom == null ) {
243269 throw new PrologParserException ("Can't read next token in block" , this .tokenizer .getLine (),
244270 this .tokenizer .getPos ());
@@ -277,7 +303,7 @@ private PrologTerm readList(final TokenizerResult openingBracket) {
277303 while (continueReading ) {
278304 final PrologTerm block = readBlock (OPERATORS_INSIDE_LIST );
279305
280- final TokenizerResult nextAtom = this .readNextTokenCommentAware ();
306+ final TokenizerResult nextAtom = this .extractNextTokenCommentAware ();
281307 if (nextAtom == null ) {
282308 throw new PrologParserException ("Can't read next token in list" , this .tokenizer .getLine (),
283309 this .tokenizer .getPos ());
@@ -316,7 +342,7 @@ private PrologTerm readList(final TokenizerResult openingBracket) {
316342 tokenizer .getLastTokenPos (), null );
317343 }
318344
319- final TokenizerResult nextAtomTwo = this .readNextTokenCommentAware ();
345+ final TokenizerResult nextAtomTwo = this .extractNextTokenCommentAware ();
320346 if (nextAtomTwo == null ) {
321347 throw new PrologParserException ("Can't find expected token in list" ,
322348 this .tokenizer .getLine (), this .tokenizer .getPos ());
@@ -374,21 +400,14 @@ private PrologTerm readList(final TokenizerResult openingBracket) {
374400 return leftPartFirst ;
375401 }
376402
377- private void checkForNull (final Object obj , final String message ,
378- final TokenizerResult startTerm ) {
379- if (obj == null ) {
380- throw new PrologParserException (message , startTerm .getLine (), startTerm .getPos ());
381- }
382- }
383- 384403 private PrologTerm readBlock (final Koi7CharOpMap endOperators ) {
385404 // the variable will contain last processed tree item contains either
386405 // atom or operator
387406 AstItem currentTreeItem = null ;
388407
389408 while (true ) {
390409 // read next atom from tokenizer
391- TokenizerResult readAtomContainer = this .readNextTokenCommentAware ();
410+ TokenizerResult readAtomContainer = this .extractNextTokenCommentAware ();
392411
393412 if (readAtomContainer == null ) {
394413 if (currentTreeItem == null ) {
@@ -505,7 +524,7 @@ private PrologTerm readBlock(final Koi7CharOpMap endOperators) {
505524 readAtomContainer .getLine (), readAtomContainer .getPos ());
506525 }
507526
508- final TokenizerResult token = this .readNextTokenCommentAware ();
527+ final TokenizerResult token = this .extractNextTokenCommentAware ();
509528
510529 final PrologTerm closingAtom ;
511530 if (token == null ) {
@@ -534,7 +553,7 @@ private PrologTerm readBlock(final Koi7CharOpMap endOperators) {
534553 }
535554 } else {
536555 if (readAtom .getType () != TermType .VAR || (this .parserFlags & FLAG_VAR_AS_FUNCTOR ) != 0 ) {
537- TokenizerResult nextToken = this .readNextTokenCommentAware ();
556+ TokenizerResult nextToken = this .extractNextTokenCommentAware ();
538557
539558 if (nextToken == null ) {
540559 throw new PrologParserException ("Non-closed clause" , this .tokenizer .getLastTokenLine (),
@@ -666,6 +685,19 @@ private PrologTerm readBlock(final Koi7CharOpMap endOperators) {
666685 }
667686 }
668687
688+ private void checkForNull (final Object obj , final String message ,
689+ final TokenizerResult startTerm ) {
690+ if (obj == null ) {
691+ throw new PrologParserException (message , startTerm .getLine (), startTerm .getPos ());
692+ }
693+ }
694+ 695+ @ Override
696+ public void close () throws IOException {
697+ this .deferredReadTerm = null ;
698+ this .tokenizer .close (this .autoCloseReaderFlag );
699+ }
700+ 669701 @ Override
670702 public Iterator <PrologTerm > iterator () {
671703 return new Iterator <>() {
@@ -690,9 +722,26 @@ public Stream<PrologTerm> stream() {
690722 );
691723 }
692724
693- @ Override
694- public void close () throws IOException {
695- this .tokenizer .close (this .autoCloseReaderFlag );
725+ private static final class PrologTermReadResult {
726+ private final PrologTerm result ;
727+ private final RuntimeException exception ;
728+ 729+ private PrologTermReadResult (final PrologTerm result , final RuntimeException error ) {
730+ this .result = result ;
731+ this .exception = error ;
732+ }
733+ 734+ boolean isPresented () {
735+ return this .exception == null || !(this .exception instanceof NoSuchElementException );
736+ }
737+ 738+ PrologTerm getResult () {
739+ if (this .exception == null ) {
740+ return this .result ;
741+ } else {
742+ throw this .exception ;
743+ }
744+ }
696745 }
697746
698747}
0 commit comments