//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gdata.util.parser;
/**
* The <code>Repeat</code> parser returns a successful match if its
* <code>subject</code> parser matches at least <code>min</code> times, but not
* more than <code>max</code> times. The <code>Repeat</code> parser is used to
* implement the <code>Parser.star()</code> and <code>Parser.plus()</code>
* methods by specifying appropriate values for <code>min</code> and
* <code>max</code>.
*
* The following matches a string of 1 to 3 letters:
*
* Parse p = Chset.ALPHA.repeat(1, 3);
* p.parse("") -> no match
* p.parse("a") -> matches "a"
* p.parse("aa") -> matches "aa"
* p.parse("aaa") -> matches "aaa"
* p.parse("aaaa") -> matches "aaa"
*
* @param <T>
*
*/
public class Repeat<T> extends Parser<T> {
private Parser<T> subject;
private int min;
private int max;
/**
* Class constructor that is used for creating a <code>Repeat</code> object
* that will match its <code>subject</code> <code>min</code> or more times.
*
* @param subject The <code>Parse</code> that this parser will repeatedly
* match.
*
* @param min The minimum number of times the <code>subject</code> parser
* must match.
*/
public Repeat(Parser<T> subject, int min) {
this(subject, min, -1);
}
/**
* Class constructor that is used for creating a <code>Repeat</code> object
* that will match its <code>subject</code> at least <code>min</code> times
* but not more than <code>max</code> times. Specifying <code>-1</code> for
* <code>max</code> causes the parser to match as many times as possible.
*
* @param subject The <code>Parse</code> that this parser will repeatedly
* match.
*
* @param min The minimum number of times the <code>subject</code> parser
* must match.
*
* @param max The maximum number of times the <code>subject</code> parser can
* match.
*/
public Repeat(Parser<T> subject, int min, int max) {
this.subject = subject;
this.min = min;
this.max = max;
}
/**
* Matches the <code>subject</code> parser against the prefix of the buffer
* (<code>buf[start,end)</code>) being parsed if the <code>subject</code>
* parser matches at least <code>min</code> times and not more than
* <code>max</code> times in sequence.
*
* @see Parser#parse
*/
@Override
public int parse(char[] buf, int start, int end, T data) {
int hit = 0;
for (int i = 0; i != max; i++) {
int next = subject.parse(buf, start + hit, end, data);
if (next == 0) {
break;
}
if (next == NO_MATCH) {
if (i < min) {
return NO_MATCH;
}
break;
}
hit += next;
}
return hit;
}
}