@@ -525,6 +525,15 @@ private static void propertywiseAlikeLine(
525525 }
526526 }
527527
528+ private static String stringAt (UnicodeSet set , int i ) {
529+ final int codePointsSize = set .size () - set .strings ().size ();
530+ if (i < codePointsSize ) {
531+ return Character .toString (set .charAt (i ));
532+ } else {
533+ return set .strings ().stream ().skip (i - codePointsSize ).findFirst ().get ();
534+ }
535+ }
536+
528537 private static void propertywiseCorrespondenceLine (
529538 Set <String > ignoredProperties ,
530539 UnicodeSet firstSet ,
@@ -538,13 +547,13 @@ private static void propertywiseCorrespondenceLine(
538547 final List <UnicodeSet > sets = new ArrayList <>();
539548 sets .add (firstSet );
540549 expectToken (":" , pp , source );
550+
551+ // Index of the first set of multi-character strings (and of the first multi-character
552+ // reference string).
553+ // This is `m` in the documentation in UnicodeInvariantTest.txt.
554+ int firstMultiCharacterIndex = -1 ;
541555 do {
542556 final var set = parseUnicodeSet (source , pp );
543- if (set .hasStrings ()) {
544- throw new BackwardParseException (
545- "Set should contain only single code points for property comparison" ,
546- pp .getIndex ());
547- }
548557 if (set .size () != firstSet .size ()) {
549558 throw new BackwardParseException (
550559 "Sets should have the same size for property correspondence (got "
@@ -554,18 +563,41 @@ private static void propertywiseCorrespondenceLine(
554563 + ")" ,
555564 pp .getIndex ());
556565 }
566+ if (set .hasStrings () && set .strings ().size () != set .size ()) {
567+ throw new BackwardParseException (
568+ "Sets should be all strings or all code points for property correspondence" ,
569+ pp .getIndex ());
570+ }
571+ if (firstMultiCharacterIndex == -1 ) {
572+ if (set .hasStrings ()) {
573+ firstMultiCharacterIndex = sets .size ();
574+ }
575+ } else if (!set .hasStrings ()) {
576+ throw new BackwardParseException (
577+ "Code points should come before strings in property correspondence" ,
578+ pp .getIndex ());
579+ }
557580 sets .add (set );
558581 } while (Lookahead .oneToken (pp , source ).accept (":" ));
559- final List <Integer > referenceCodePoints = new ArrayList <>();
582+ if (firstMultiCharacterIndex == -1 ) {
583+ firstMultiCharacterIndex = sets .size ();
584+ }
585+ final List <String > referenceCodePoints = new ArrayList <>();
560586 expectToken ("CorrespondTo" , pp , source );
561587 do {
562588 final var referenceSet = parseUnicodeSet (source , pp );
563- if (referenceSet .hasStrings () || referenceSet .size () != 1 ) {
589+ if (referenceSet .size () != 1 ) {
590+ throw new BackwardParseException (
591+ "reference should be a single code point or string for property correspondence" ,
592+ pp .getIndex ());
593+ }
594+ if (referenceSet .hasStrings ()
595+ != (referenceCodePoints .size () >= firstMultiCharacterIndex )) {
564596 throw new BackwardParseException (
565- "reference should be a single code point for property correspondence" ,
597+ "Strings should correspond to strings for property correspondence" ,
566598 pp .getIndex ());
567599 }
568- referenceCodePoints .add (referenceSet .charAt ( 0 ));
600+ referenceCodePoints .add (referenceSet .iterator (). next ( ));
569601 } while (Lookahead .oneToken (pp , source ).accept (":" ));
570602 if (referenceCodePoints .size () != sets .size ()) {
571603 throw new BackwardParseException (
@@ -608,8 +640,8 @@ public ExpectedPropertyDifference(String actualValueAlias, String referenceValue
608640 expectedDifference = expectedPropertyDifferences .get (alias );
609641 }
610642 if (expectedDifference != null ) {
611- for (int k = 0 ; k < sets . size () ; ++k ) {
612- final int rk = referenceCodePoints .get (k );
643+ for (int k = 0 ; k < firstMultiCharacterIndex ; ++k ) {
644+ final int rk = referenceCodePoints .get (k ). codePointAt ( 0 ) ;
613645 final String pRk = property .getValue (rk );
614646 if (!Objects .equals (pRk , expectedDifference .referenceValueAlias )) {
615647 errorMessageLines .add (
@@ -638,9 +670,9 @@ public ExpectedPropertyDifference(String actualValueAlias, String referenceValue
638670 }
639671 }
640672 } else {
641- for (int k = 0 ; k < sets . size () ; ++k ) {
673+ for (int k = 0 ; k < firstMultiCharacterIndex ; ++k ) {
642674 final UnicodeSet set = sets .get (k );
643- final int rk = referenceCodePoints .get (k );
675+ final int rk = referenceCodePoints .get (k ). codePointAt ( 0 ) ;
644676 final String pRk = property .getValue (rk );
645677 loop_over_set :
646678 for (int i = 0 ; i < set .size (); ++i ) {
@@ -652,10 +684,9 @@ public ExpectedPropertyDifference(String actualValueAlias, String referenceValue
652684 Integer lMatchingForReference = null ;
653685 for (int l = 0 ; l < sets .size (); ++l ) {
654686 final boolean pCkEqualsCl =
655- Objects .equals (pCk , Character . toString (sets .get (l ). charAt ( i ) ));
687+ Objects .equals (pCk , stringAt (sets .get (l ), i ));
656688 final boolean pRkEqualsRl =
657- Objects .equals (
658- pRk , Character .toString (referenceCodePoints .get (l )));
689+ Objects .equals (pRk , referenceCodePoints .get (l ));
659690 if (pRkEqualsRl ) {
660691 lMatchingForReference = l ;
661692 if (pCkEqualsCl ) {
@@ -685,8 +716,7 @@ public ExpectedPropertyDifference(String actualValueAlias, String referenceValue
685716 + ")\t =\t "
686717 + pCk
687718 + "\t ≠\t "
688- + Character .toString (
689- sets .get (lMatchingForReference ).charAt (i ))
719+ + stringAt (sets .get (lMatchingForReference ), i )
690720 + "\t whereas\t "
691721 + property .getName ()
692722 + "("
0 commit comments