|
47 | 47 |
|
48 | 48 | import static com.igormaznitsa.prologparser.DefaultParserContext.of; |
49 | 49 | import static com.igormaznitsa.prologparser.ParserContext.*; |
| 50 | +import static com.igormaznitsa.prologparser.terms.TermType.__OPERATOR_CONTAINER__; |
50 | 51 | import static com.igormaznitsa.prologparser.tokenizer.Koi7CharOpMap.ofOps; |
51 | 52 |
|
52 | 53 | /** |
@@ -159,7 +160,7 @@ private boolean isEndOperator(final PrologTerm operator, final Koi7CharOpMap end |
159 | 160 | return false; |
160 | 161 | } |
161 | 162 |
|
162 | | - return operator.getTermType() == TermType.__OPERATOR_CONTAINER__ && endOperators.contains(operator.getTermText()); |
| 163 | + return operator.getTermType() == __OPERATOR_CONTAINER__ && endOperators.contains(operator.getTermText()); |
163 | 164 | } |
164 | 165 |
|
165 | 166 | public ParserContext getContext() { |
@@ -385,157 +386,152 @@ private PrologTerm readBlock(final Koi7CharOpMap endOperators) { |
385 | 386 | // same as the natural precedence) |
386 | 387 | int readAtomPrecedence = 0; // we make it as highest precedence |
387 | 388 |
|
388 | | - switch (readAtom.getTermType()) { |
389 | | - case __OPERATOR_CONTAINER__: { |
390 | | - // it is operator list |
391 | | - // try to get the single operator from the list if the list |
392 | | - // contains only one |
393 | | - final Op readOperator = ((OpContainer) readAtom).getIfSingle(); |
| 389 | + if (readAtom.getTermType() == __OPERATOR_CONTAINER__) { |
| 390 | + // it is operator list |
| 391 | + // try to get the single operator from the list if the list |
| 392 | + // contains only one |
| 393 | + final Op readOperator = ((OpContainer) readAtom).getIfSingle(); |
394 | 394 |
|
395 | | - // check that the operator is single |
396 | | - if (readOperator == null) { |
| 395 | + // check that the operator is single |
| 396 | + if (readOperator == null) { |
397 | 397 |
|
398 | | - // there are a few operators in the list so we need to |
399 | | - // select one |
400 | | - final OpContainer readOperators = (OpContainer) readAtom; |
| 398 | + // there are a few operators in the list so we need to |
| 399 | + // select one |
| 400 | + final OpContainer readOperators = (OpContainer) readAtom; |
401 | 401 |
|
402 | | - boolean leftPresented = false; |
| 402 | + boolean leftPresented = false; |
403 | 403 |
|
404 | | - if (currentTreeItem != null) { |
405 | | - if (currentTreeItem.getType() == TermType.OPERATOR) { |
406 | | - if (currentTreeItem.getRightBranch() != null) { |
407 | | - leftPresented = true; |
408 | | - } |
409 | | - } else { |
| 404 | + if (currentTreeItem != null) { |
| 405 | + if (currentTreeItem.getType() == TermType.OPERATOR) { |
| 406 | + if (currentTreeItem.getRightBranch() != null) { |
410 | 407 | leftPresented = true; |
411 | 408 | } |
| 409 | + } else { |
| 410 | + leftPresented = true; |
412 | 411 | } |
| 412 | + } |
413 | 413 |
|
414 | | - final TokenizerResult peekResult = this.tokenizer.peek(); |
415 | | - final boolean rightPresented = peekResult != null && !isEndOperator(peekResult.getResult(), endOperators); |
| 414 | + final TokenizerResult peekResult = this.tokenizer.peek(); |
| 415 | + final boolean rightPresented = peekResult != null && !isEndOperator(peekResult.getResult(), endOperators); |
416 | 416 |
|
417 | | - readAtom = readOperators.findSimilar(leftPresented, rightPresented); |
| 417 | + readAtom = readOperators.findSimilar(leftPresented, rightPresented); |
418 | 418 |
|
419 | | - if (readAtom == null) { |
420 | | - if (currentTreeItem == null && !(leftPresented || rightPresented)) { |
421 | | - // alone operator, it is an atom |
422 | | - return new PrologAtom(readOperators.getTermText(), PrologTerm.QuotingType.SINGLE_QUOTED, readOperators.getLine(), readOperators.getPos()); |
423 | | - } |
424 | | - // we didn't get any operator for our criteria, so throw |
425 | | - // an exception |
426 | | - throw new PrologParserException("Operator clash detected [" + readAtomContainer.getResult().getTermText() + ']', |
427 | | - readAtomContainer.getLine(), readAtomContainer.getPos()); |
| 419 | + if (readAtom == null) { |
| 420 | + if (currentTreeItem == null && !(leftPresented || rightPresented)) { |
| 421 | + // alone operator, it is an atom |
| 422 | + return new PrologAtom(readOperators.getTermText(), PrologTerm.QuotingType.SINGLE_QUOTED, readOperators.getLine(), readOperators.getPos()); |
428 | 423 | } |
429 | | - // we have found needed operator so get its precedence |
430 | | - readAtomPrecedence = readAtom.getPrecedence(); |
431 | | - } else { |
432 | | - readAtom = readOperator; |
433 | | - final String operatorText = readOperator.getTermText(); |
434 | | - |
435 | | - if (operatorText.length() == 1) { |
436 | | - switch (findFirstCharCode(operatorText)) { |
437 | | - case '[': { |
438 | | - // it's a list |
439 | | - readAtom = readList(readAtomContainer); |
440 | | - readAtom.setPos(readAtomContainer.getPos()); |
441 | | - readAtom.setLine(readAtomContainer.getLine()); |
442 | | - readAtomPrecedence = 0; |
| 424 | + // we didn't get any operator for our criteria, so throw |
| 425 | + // an exception |
| 426 | + throw new PrologParserException("Operator clash detected [" + readAtomContainer.getResult().getTermText() + ']', |
| 427 | + readAtomContainer.getLine(), readAtomContainer.getPos()); |
| 428 | + } |
| 429 | + // we have found needed operator so get its precedence |
| 430 | + readAtomPrecedence = readAtom.getPrecedence(); |
| 431 | + } else { |
| 432 | + readAtom = readOperator; |
| 433 | + final String operatorText = readOperator.getTermText(); |
| 434 | + |
| 435 | + if (operatorText.length() == 1) { |
| 436 | + switch (findFirstCharCode(operatorText)) { |
| 437 | + case '[': { |
| 438 | + // it's a list |
| 439 | + readAtom = readList(readAtomContainer); |
| 440 | + readAtom.setPos(readAtomContainer.getPos()); |
| 441 | + readAtom.setLine(readAtomContainer.getLine()); |
| 442 | + readAtomPrecedence = 0; |
| 443 | + } |
| 444 | + break; |
| 445 | + case '(': { |
| 446 | + // read sub-block |
| 447 | + readAtom = readBlock(OPERATORS_SUBBLOCK); |
| 448 | + |
| 449 | + if (readAtom == null) { |
| 450 | + throw new PrologParserException("Illegal start of term", |
| 451 | + readAtomContainer.getLine(), readAtomContainer.getPos()); |
443 | 452 | } |
444 | | - break; |
445 | | - case '(': { |
446 | | - // read sub-block |
447 | | - readAtom = readBlock(OPERATORS_SUBBLOCK); |
448 | | - |
449 | | - if (readAtom == null) { |
450 | | - throw new PrologParserException("Illegal start of term", |
451 | | - readAtomContainer.getLine(), readAtomContainer.getPos()); |
452 | | - } |
453 | 453 |
|
454 | | - readAtom.setLine(readAtomContainer.getLine()); |
455 | | - readAtom.setPos(readAtomContainer.getPos()); |
456 | | - readAtom = new PrologStruct(Op.VIRTUAL_OPERATOR_BLOCK, new PrologTerm[] {readAtom}, readAtomContainer.getLine(), readAtomContainer.getPos()); |
| 454 | + readAtom.setLine(readAtomContainer.getLine()); |
| 455 | + readAtom.setPos(readAtomContainer.getPos()); |
| 456 | + readAtom = new PrologStruct(Op.VIRTUAL_OPERATOR_BLOCK, new PrologTerm[] {readAtom}, readAtomContainer.getLine(), readAtomContainer.getPos()); |
457 | 457 |
|
458 | | - final TokenizerResult token = this.tokenizer.readNextToken(); |
| 458 | + final TokenizerResult token = this.tokenizer.readNextToken(); |
459 | 459 |
|
460 | | - final PrologTerm closingAtom; |
461 | | - if (token == null) { |
462 | | - closingAtom = null; |
463 | | - } else { |
464 | | - closingAtom = token.getResult(); |
465 | | - token.release(); |
466 | | - } |
467 | | - |
468 | | - if (closingAtom == null || !closingAtom.getTermText().equals(OPERATOR_RIGHTBRACKET.getTermText())) { |
469 | | - throw new PrologParserException("Non-closed brakes", this.tokenizer.getLine(), this.tokenizer.getPos()); |
470 | | - } |
| 460 | + final PrologTerm closingAtom; |
| 461 | + if (token == null) { |
| 462 | + closingAtom = null; |
| 463 | + } else { |
| 464 | + closingAtom = token.getResult(); |
| 465 | + token.release(); |
471 | 466 | } |
472 | | - break; |
473 | | - default: { |
474 | | - readAtomPrecedence = readOperator.getPrecedence(); |
| 467 | + |
| 468 | + if (closingAtom == null || !closingAtom.getTermText().equals(OPERATOR_RIGHTBRACKET.getTermText())) { |
| 469 | + throw new PrologParserException("Non-closed brakes", this.tokenizer.getLine(), this.tokenizer.getPos()); |
475 | 470 | } |
476 | | - break; |
477 | 471 | } |
478 | | - } else { |
479 | | - readAtomPrecedence = readOperator.getPrecedence(); |
| 472 | + break; |
| 473 | + default: { |
| 474 | + readAtomPrecedence = readOperator.getPrecedence(); |
| 475 | + } |
| 476 | + break; |
480 | 477 | } |
| 478 | + } else { |
| 479 | + readAtomPrecedence = readOperator.getPrecedence(); |
481 | 480 | } |
482 | 481 | } |
483 | | - break; |
484 | | - default: { |
485 | | - if (readAtom.getTermType() != TermType.VAR || (this.parserFlags & FLAG_VAR_AS_FUNCTOR) != 0) { |
486 | | - TokenizerResult nextToken = this.tokenizer.readNextToken(); |
| 482 | + } else { |
| 483 | + if (readAtom.getTermType() != TermType.VAR || (this.parserFlags & FLAG_VAR_AS_FUNCTOR) != 0) { |
| 484 | + TokenizerResult nextToken = this.tokenizer.readNextToken(); |
487 | 485 |
|
488 | | - if (nextToken == null) { |
489 | | - throw new PrologParserException("Non-closed clause", this.tokenizer.getLastTokenLine(), this.tokenizer.getLastTokenPos()); |
490 | | - } |
| 486 | + if (nextToken == null) { |
| 487 | + throw new PrologParserException("Non-closed clause", this.tokenizer.getLastTokenLine(), this.tokenizer.getLastTokenPos()); |
| 488 | + } |
491 | 489 |
|
492 | | - try { |
493 | | - if (nextToken.getResult().getTermText().equals(OPERATOR_LEFTBRACKET.getTermText())) { |
494 | | - final int nextTokenLineNumber = nextToken.getLine(); |
495 | | - final int nextTokenStrPosition = nextToken.getPos(); |
496 | | - |
497 | | - // it is a structure |
498 | | - if ( |
499 | | - readAtom.getTermType() == TermType.ATOM |
500 | | - || (readAtom.getTermType() == TermType.VAR |
501 | | - && (this.parserFlags & FLAG_VAR_AS_FUNCTOR) != 0) |
502 | | - ) { |
503 | | - |
504 | | - final PrologTerm prev = readAtom; |
505 | | - readAtom = readStruct(readAtom); |
506 | | - if (readAtom == null) { |
507 | | - // we have met the empty brackets |
508 | | - if ((this.parserFlags & FLAG_ALLOW_ZERO_STRUCT) == 0) { |
509 | | - throw new PrologParserException("Empty structure is not allowed", |
510 | | - nextTokenLineNumber, nextTokenStrPosition); |
| 490 | + try { |
| 491 | + if (nextToken.getResult().getTermText().equals(OPERATOR_LEFTBRACKET.getTermText())) { |
| 492 | + final int nextTokenLineNumber = nextToken.getLine(); |
| 493 | + final int nextTokenStrPosition = nextToken.getPos(); |
| 494 | + |
| 495 | + // it is a structure |
| 496 | + if ( |
| 497 | + readAtom.getTermType() == TermType.ATOM |
| 498 | + || (readAtom.getTermType() == TermType.VAR |
| 499 | + && (this.parserFlags & FLAG_VAR_AS_FUNCTOR) != 0) |
| 500 | + ) { |
| 501 | + |
| 502 | + final PrologTerm prev = readAtom; |
| 503 | + readAtom = readStruct(readAtom); |
| 504 | + if (readAtom == null) { |
| 505 | + // we have met the empty brackets |
| 506 | + if ((this.parserFlags & FLAG_ALLOW_ZERO_STRUCT) == 0) { |
| 507 | + throw new PrologParserException("Empty structure is not allowed", |
| 508 | + nextTokenLineNumber, nextTokenStrPosition); |
| 509 | + } else { |
| 510 | + final TokenizerResult pushed = this.tokenizer.pop(); |
| 511 | + if (pushed.getResult() == OPERATOR_RIGHTBRACKET) { |
| 512 | + readAtom = new PrologStruct(prev); |
511 | 513 | } else { |
512 | | - final TokenizerResult pushed = this.tokenizer.pop(); |
513 | | - if (pushed.getResult() == OPERATOR_RIGHTBRACKET) { |
514 | | - readAtom = new PrologStruct(prev); |
515 | | - } else { |
516 | | - throw new CriticalUnexpectedError(); |
517 | | - } |
| 514 | + throw new CriticalUnexpectedError(); |
518 | 515 | } |
519 | 516 | } |
520 | | - } else { |
521 | | - tokenizer.push(nextToken); |
522 | | - nextToken = null; |
523 | | - throw new PrologParserException("You must have an atom as the structure functor", |
524 | | - nextTokenLineNumber, nextTokenStrPosition); |
525 | 517 | } |
526 | 518 | } else { |
527 | | - // push back the next atom |
528 | 519 | tokenizer.push(nextToken); |
529 | 520 | nextToken = null; |
| 521 | + throw new PrologParserException("You must have an atom as the structure functor", |
| 522 | + nextTokenLineNumber, nextTokenStrPosition); |
530 | 523 | } |
531 | | - } finally { |
532 | | - if (nextToken != null) { |
533 | | - nextToken.release(); |
534 | | - } |
| 524 | + } else { |
| 525 | + // push back the next atom |
| 526 | + tokenizer.push(nextToken); |
| 527 | + nextToken = null; |
| 528 | + } |
| 529 | + } finally { |
| 530 | + if (nextToken != null) { |
| 531 | + nextToken.release(); |
535 | 532 | } |
536 | 533 | } |
537 | 534 | } |
538 | | - break; |
539 | 535 | } |
540 | 536 |
|
541 | 537 | final TreeItem readAtomTreeItem = this.treeItemPool.find().setData(readAtom, |
@@ -623,7 +619,17 @@ private PrologTerm readBlock(final Koi7CharOpMap endOperators) { |
623 | 619 |
|
624 | 620 | @Override |
625 | 621 | public Iterator<PrologTerm> iterator() { |
626 | | - return this; |
| 622 | + return new Iterator<PrologTerm>() { |
| 623 | + @Override |
| 624 | + public boolean hasNext() { |
| 625 | + return PrologParser.this.hasNext(); |
| 626 | + } |
| 627 | + |
| 628 | + @Override |
| 629 | + public PrologTerm next() { |
| 630 | + return PrologParser.this.next(); |
| 631 | + } |
| 632 | + }; |
627 | 633 | } |
628 | 634 |
|
629 | 635 | public Stream<PrologTerm> stream() { |
|
0 commit comments