system/src/sc/parser/OrderedChoice.java
public Object parseExtendedErrors(Parser parser, Parselet exitParselet) {
      if (trace)
         System.out.println("*** tracing extended errors for ordered choice");
      if (skipOnErrorParselet == null)
         return null;

      int startIndex = parser.currentIndex;
      int lastMatchStart;
      ParentParseNode value = null;
      boolean matched;
      ParseError bestError;
      int bestErrorSlotIx = -1;

      boolean emptyMatch = false;

      do {
         matched = false;
         lastMatchStart = parser.currentIndex;

         // Since we've parsed on from this point, need to clear out the last error
         bestError = null;

         List<Parselet> matchingParselets = getMatchingParselets(parser);

         int numMatches = matchingParselets.size();
         for (int i = 0; i < numMatches; i++) {
            Parselet matchedParselet = matchingParselets.get(i);
            Object nestedValue = parser.parseNext(matchedParselet);
            emptyMatch = nestedValue == null;
            if (!(nestedValue instanceof ParseError)) {
               if (value == null)
                  value = newParseNode(lastMatchStart);

               if (nestedValue != null || parser.peekInputChar(0) != '\0') {
                  int slotIx = getSlotIndex(matchingParselets, i);
                  value.add(nestedValue, matchedParselet, -1, slotIx, false, parser);

                  matched = true;
                  break;
               }
            }
            else {
               ParseError error = (ParseError) nestedValue;
               if (bestError == null || bestError.endIndex < error.endIndex) {
                  bestError = error;
                  bestErrorSlotIx = matchingParselets instanceof MatchResult ? ((MatchResult) matchingParselets).slotIndexes[i] : i;
               }
            }
         }

         if (!matched || emptyMatch) {
            // Keep applying the skipOnErrorParselet until we hit the exit parselet
            if (!exitParselet.peek(parser)) {
               int errorStart = parser.currentIndex;
               // This will consume whatever it is that we can't parse until we get to the next statement.  We have to be careful with the
               // design of the skipOnErrorParselet so that it leaves us in the state for the next match on this choice.  It should not breakup
               // an identifier for example.
               Object errorRes = parser.parseNext(skipOnErrorParselet);
               if (errorRes instanceof ParseError) {
                  // We never found the exitParselet - i.e. the } so the parent sequence will fail just like it did before.
                  // When this method returns null, we go with the result we produced in the normal parseRepeatingChoice method.
                  parser.changeCurrentIndex(startIndex);
                  return null;
               }

               boolean useError = true;
               if (errorRes instanceof IParseNode) {
                  IParseNode errorNode = (IParseNode) errorRes;
                  // If one of the partial value errors is longer (or as long) we can start the skip parse from that error preserving more of the model
                  if (bestError != null && errorNode.length() <= bestError.endIndex - bestError.startIndex && bestError.partialValue != null) {
                     value = value == null ? (ParentParseNode) newParseNode(bestError.startIndex) : value;
                     value.add(bestError.partialValue, bestError.parselet, -1, bestErrorSlotIx, false, parser);
                     errorStart = bestError.endIndex;
                     parser.changeCurrentIndex(bestError.endIndex);

                     // It turns out the partial value error will match better than the skipOnError parselet.  We need to insert an error representing the
                     // fact that it's not a complete statement.
                     if (exitParselet.peek(parser)) {
                        value.add(new ErrorParseNode(new ParseError(bestError.parselet, bestError.errorCode, bestError.errorArgs, bestError.endIndex, bestError.endIndex), ""), bestError.parselet, -1, -1, true, parser);
                        return value;
                     }

                     errorRes = parser.parseNext(skipOnErrorParselet);
                     if (errorRes instanceof ParseError)
                        return value;
                  }
               }

               if (useError) {
                  if (value == null)
                     value = (ParentParseNode) newParseNode(lastMatchStart);
                  value.add(new ErrorParseNode(new ParseError(skipOnErrorParselet, "Expected {0}", new Object[]{this}, errorStart, parser.currentIndex), errorRes.toString()), skipOnErrorParselet, -1, -1, true, parser);
                  matched = true;
                  emptyMatch = false;
               }
            }
         }

      } while (matched && !emptyMatch);

      if (value == null) {
         if (optional) {
            if (parser.enablePartialValues && bestError != null && bestError.partialValue != null/* && bestError.eof */) {
               return parsePartialErrorValue(parser, bestError, lastMatchStart, bestErrorSlotIx);
            }
            parser.changeCurrentIndex(startIndex);

            // If we are a repeat optional choice with mappings of '' and we match no elements, we should return an empty string, not null.
            if (!lookahead && repeat && isStringParameterMapping() && parser.peekInputChar(0) != '\0') {
               return parseResult(parser, "", false);
            }
            return null;
         }
         if (bestError != null) {
            if (parser.enablePartialValues && bestError.partialValue != null) {
               return parsePartialErrorValue(parser, bestError, lastMatchStart, bestErrorSlotIx);
            }
            // NOTE: In this case, we are possibly returning the error from a scalar parselet for a repeating one.  It won't matter unless we have partial values enabled and partialValue
            return bestError;
         }
         return parseError(parser, "Expecting one or more of: {0}", this);
      }
      else {
         // If we are doing the partial values case, we might have partially matched one more statement.  if so, this is part of the partial results
         if (parser.enablePartialValues && bestError != null && /*bestError.eof && */ bestError.partialValue != null && bestError.startIndex == lastMatchStart) {
            value.add(bestError.partialValue, bestError.parselet, -1, bestErrorSlotIx, false, parser);

            return parsePartialError(parser, value, bestError, bestError.parselet, bestError.errorCode, bestError.errorArgs);
         }
         if (lookahead)
            parser.changeCurrentIndex(startIndex);

         else
            parser.changeCurrentIndex(lastMatchStart);
         return parseResult(parser, value, false);
      }
   }
/** Code copied alert!  This is a lot like parseRepeatingChoice but skipping and stopping on exitParselet. */
Code copied alert.  This is a lot like parseRepeatingChoice but skipping and stopping on exitParselet.
Code copied alert . This is a lot like parseRepeatingChoice but skipping and stopping on exitParselet .
public Object parseExtendedErrors(Parser parser, Parselet exitParselet) {
      if (trace)
         System.out.println("*** tracing extended errors for ordered choice");
      if (skipOnErrorParselet == null)
         return null;
      int startIndex = parser.currentIndex;
      int lastMatchStart;
      ParentParseNode value = null;
      boolean matched;
      ParseError bestError;
      int bestErrorSlotIx = -1;
      boolean emptyMatch = false;
      do {
         matched = false;
         lastMatchStart = parser.currentIndex;
         bestError = null;
         List<Parselet> matchingParselets = getMatchingParselets(parser);
         int numMatches = matchingParselets.size();
         for (int i = 0; i < numMatches; i++) {
            Parselet matchedParselet = matchingParselets.get(i);
            Object nestedValue = parser.parseNext(matchedParselet);
            emptyMatch = nestedValue == null;
            if (!(nestedValue instanceof ParseError)) {
               if (value == null)
                  value = newParseNode(lastMatchStart);
               if (nestedValue != null || parser.peekInputChar(0) != '\0') {
                  int slotIx = getSlotIndex(matchingParselets, i);
                  value.add(nestedValue, matchedParselet, -1, slotIx, false, parser);
                  matched = true;
                  break;
               }
            }
            else {
               ParseError error = (ParseError) nestedValue;
               if (bestError == null || bestError.endIndex < error.endIndex) {
                  bestError = error;
                  bestErrorSlotIx = matchingParselets instanceof MatchResult ? ((MatchResult) matchingParselets).slotIndexes[i] : i;
               }
            }
         }
         if (!matched || emptyMatch) {
            if (!exitParselet.peek(parser)) {
               int errorStart = parser.currentIndex;
               Object errorRes = parser.parseNext(skipOnErrorParselet);
               if (errorRes instanceof ParseError) {
                  parser.changeCurrentIndex(startIndex);
                  return null;
               }
               boolean useError = true;
               if (errorRes instanceof IParseNode) {
                  IParseNode errorNode = (IParseNode) errorRes;
                  if (bestError != null && errorNode.length() <= bestError.endIndex - bestError.startIndex && bestError.partialValue != null) {
                     value = value == null ? (ParentParseNode) newParseNode(bestError.startIndex) : value;
                     value.add(bestError.partialValue, bestError.parselet, -1, bestErrorSlotIx, false, parser);
                     errorStart = bestError.endIndex;
                     parser.changeCurrentIndex(bestError.endIndex);
                     if (exitParselet.peek(parser)) {
                        value.add(new ErrorParseNode(new ParseError(bestError.parselet, bestError.errorCode, bestError.errorArgs, bestError.endIndex, bestError.endIndex), ""), bestError.parselet, -1, -1, true, parser);
                        return value;
                     }
                     errorRes = parser.parseNext(skipOnErrorParselet);
                     if (errorRes instanceof ParseError)
                        return value;
                  }
               }
               if (useError) {
                  if (value == null)
                     value = (ParentParseNode) newParseNode(lastMatchStart);
                  value.add(new ErrorParseNode(new ParseError(skipOnErrorParselet, "Expected {0}", new Object[]{this}, errorStart, parser.currentIndex), errorRes.toString()), skipOnErrorParselet, -1, -1, true, parser);
                  matched = true;
                  emptyMatch = false;
               }
            }
         }
      } while (matched && !emptyMatch);
      if (value == null) {
         if (optional) {
            if (parser.enablePartialValues && bestError != null && bestError.partialValue != null/* && bestError.eof */) {
               return parsePartialErrorValue(parser, bestError, lastMatchStart, bestErrorSlotIx);
            }
            parser.changeCurrentIndex(startIndex);
            if (!lookahead && repeat && isStringParameterMapping() && parser.peekInputChar(0) != '\0') {
               return parseResult(parser, "", false);
            }
            return null;
         }
         if (bestError != null) {
            if (parser.enablePartialValues && bestError.partialValue != null) {
               return parsePartialErrorValue(parser, bestError, lastMatchStart, bestErrorSlotIx);
            }
            return bestError;
         }
         return parseError(parser, "Expecting one or more of: {0}", this);
      }
      else {
         if (parser.enablePartialValues && bestError != null && /*bestError.eof && */ bestError.partialValue != null && bestError.startIndex == lastMatchStart) {
            value.add(bestError.partialValue, bestError.parselet, -1, bestErrorSlotIx, false, parser);
            return parsePartialError(parser, value, bestError, bestError.parselet, bestError.errorCode, bestError.errorArgs);
         }
         if (lookahead)
            parser.changeCurrentIndex(startIndex);
         else
            parser.changeCurrentIndex(lastMatchStart);
         return parseResult(parser, value, false);
      }
   }
public Object parseExtendedErrors ( Parser parser , Parselet exitParselet ) { if ( trace ) System . out . println ( "*** tracing extended errors for ordered choice" ) ; if ( skipOnErrorParselet == null ) return null ; int startIndex = parser . currentIndex ; int lastMatchStart ; ParentParseNode value = null ; boolean matched ; ParseError bestError ; int bestErrorSlotIx = - 1 ; boolean emptyMatch = false ; do { matched = false ; lastMatchStart = parser . currentIndex ; bestError = null ; List < Parselet > matchingParselets = getMatchingParselets ( parser ) ; int numMatches = matchingParselets . size ( ) ; for ( int i = 0 ; i < numMatches ; i ++ ) { Parselet matchedParselet = matchingParselets . get ( i ) ; Object nestedValue = parser . parseNext ( matchedParselet ) ; emptyMatch = nestedValue == null ; if ( ! ( nestedValue instanceof ParseError ) ) { if ( value == null ) value = newParseNode ( lastMatchStart ) ; if ( nestedValue != null || parser . peekInputChar ( 0 ) != '\0' ) { int slotIx = getSlotIndex ( matchingParselets , i ) ; value . add ( nestedValue , matchedParselet , - 1 , slotIx , false , parser ) ; matched = true ; break ; } } else { ParseError error = ( ParseError ) nestedValue ; if ( bestError == null || bestError . endIndex < error . endIndex ) { bestError = error ; bestErrorSlotIx = matchingParselets instanceof MatchResult ? ( ( MatchResult ) matchingParselets ) . slotIndexes [ i ] : i ; } } } if ( ! matched || emptyMatch ) { if ( ! exitParselet . peek ( parser ) ) { int errorStart = parser . currentIndex ; Object errorRes = parser . parseNext ( skipOnErrorParselet ) ; if ( errorRes instanceof ParseError ) { parser . changeCurrentIndex ( startIndex ) ; return null ; } boolean useError = true ; if ( errorRes instanceof IParseNode ) { IParseNode errorNode = ( IParseNode ) errorRes ; if ( bestError != null && errorNode . length ( ) <= bestError . endIndex - bestError . startIndex && bestError . partialValue != null ) { value = value == null ? ( ParentParseNode ) newParseNode ( bestError . startIndex ) : value ; value . add ( bestError . partialValue , bestError . parselet , - 1 , bestErrorSlotIx , false , parser ) ; errorStart = bestError . endIndex ; parser . changeCurrentIndex ( bestError . endIndex ) ; if ( exitParselet . peek ( parser ) ) { value . add ( new ErrorParseNode ( new ParseError ( bestError . parselet , bestError . errorCode , bestError . errorArgs , bestError . endIndex , bestError . endIndex ) , "" ) , bestError . parselet , - 1 , - 1 , true , parser ) ; return value ; } errorRes = parser . parseNext ( skipOnErrorParselet ) ; if ( errorRes instanceof ParseError ) return value ; } } if ( useError ) { if ( value == null ) value = ( ParentParseNode ) newParseNode ( lastMatchStart ) ; value . add ( new ErrorParseNode ( new ParseError ( skipOnErrorParselet , "Expected {0}" , new Object [ ] { this } , errorStart , parser . currentIndex ) , errorRes . toString ( ) ) , skipOnErrorParselet , - 1 , - 1 , true , parser ) ; matched = true ; emptyMatch = false ; } } } } while ( matched && ! emptyMatch ) ; if ( value == null ) { if ( optional ) { if ( parser . enablePartialValues && bestError != null && bestError . partialValue != null /* && bestError.eof */ ) { return parsePartialErrorValue ( parser , bestError , lastMatchStart , bestErrorSlotIx ) ; } parser . changeCurrentIndex ( startIndex ) ; if ( ! lookahead && repeat && isStringParameterMapping ( ) && parser . peekInputChar ( 0 ) != '\0' ) { return parseResult ( parser , "" , false ) ; } return null ; } if ( bestError != null ) { if ( parser . enablePartialValues && bestError . partialValue != null ) { return parsePartialErrorValue ( parser , bestError , lastMatchStart , bestErrorSlotIx ) ; } return bestError ; } return parseError ( parser , "Expecting one or more of: {0}" , this ) ; } else { if ( parser . enablePartialValues && bestError != null && /*bestError.eof && */ bestError . partialValue != null && bestError . startIndex == lastMatchStart ) { value . add ( bestError . partialValue , bestError . parselet , - 1 , bestErrorSlotIx , false , parser ) ; return parsePartialError ( parser , value , bestError , bestError . parselet , bestError . errorCode , bestError . errorArgs ) ; } if ( lookahead ) parser . changeCurrentIndex ( startIndex ) ; else parser . changeCurrentIndex ( lastMatchStart ) ; return parseResult ( parser , value , false ) ; } }
Code copied alert!
Code copied alert!
// Since we've parsed on from this point, need to clear out the last error // Keep applying the skipOnErrorParselet until we hit the exit parselet // This will consume whatever it is that we can't parse until we get to the next statement.  We have to be careful with the // design of the skipOnErrorParselet so that it leaves us in the state for the next match on this choice.  It should not breakup // an identifier for example. // We never found the exitParselet - i.e. the } so the parent sequence will fail just like it did before. // When this method returns null, we go with the result we produced in the normal parseRepeatingChoice method. // If one of the partial value errors is longer (or as long) we can start the skip parse from that error preserving more of the model // It turns out the partial value error will match better than the skipOnError parselet.  We need to insert an error representing the // fact that it's not a complete statement. // If we are a repeat optional choice with mappings of '' and we match no elements, we should return an empty string, not null. // NOTE: In this case, we are possibly returning the error from a scalar parselet for a repeating one.  It won't matter unless we have partial values enabled and partialValue // If we are doing the partial values case, we might have partially matched one more statement.  if so, this is part of the partial results