/*****************************************************************************
* Copyright (C) Codehaus.org *
* ------------------------------------------------------------------------- *
* 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 net.ion.rosetta;
/**
* Parses a list of pattern started with a delimiter, separated and optionally ended by the delimiter.
*
* @author Ben Yu
*/
class DelimitedParser<T, R> extends Parser<R> {
final Parser<T> parser;
private final Parser<?> delim;
DelimitedParser(Parser<T> p, Parser<?> delim) {
this.parser = p;
this.delim = delim;
}
@Override
boolean apply(final ParseContext ctxt) {
final R result = begin();
for (;;) {
final int step0 = ctxt.step;
final int at0 = ctxt.at;
boolean r = ParserInternals.greedyRun(delim, ctxt);
if (!r) {
if (!ParserInternals.stillThere(ctxt, at0, step0))
return false;
ctxt.result = result;
return true;
}
final int step1 = ctxt.step;
final int at1 = ctxt.at;
r = ParserInternals.greedyRun(parser, ctxt);
if (!r) {
if (!ParserInternals.stillThere(ctxt, at1, step1))
return false;
ctxt.result = result;
return true;
}
if (at0 == ctxt.at) { // infinite loop
ctxt.result = result;
return true;
}
element(ctxt, result);
}
}
R begin() {
return null;
}
void element(ParseContext ctxt, R result) {
}
@Override
public String toString() {
return "delimited";
}
}