// // 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>Rule</code> parser has a very simple reason for existence: in * order to construct recursive grammars, a parser needs to reference * itself. But the normal parser construction routines don't allow that to be * done. An alternative to this design would be to allow the modification of * the sub-parsers of <code>Alternative</code>, <code>Sequence</code>, * etc. after the objects have been constructed. * * The following matches a sequence of letters and digits that end in a * digit. This could be more easily accomplished, but it demonstrates how a * recursive parser can be constructed: * * Rule r = new Rule(); * r.set(Parser.alternative(Chset.DIGIT, Parser.sequence(Chset.ALPHA, r))); * r.parse("a0") -> matches "a0" * r.parse("a0b1") -> matches "a0b1" * r.parse("a") -> no match * * @param <T> * @see Parser * */ public class Rule<T> extends Parser<T> { private Parser<T> subject; /** * Class constructor for a <code>null</code> <code>subject</code>. */ public Rule() { this(null); } /** * Class constructor. * * @param subject The <code>Parser</code> that this parser delegates parsing * responsibilities to. */ public Rule(Parser<T> subject) { this.subject = subject; } /** * Delegates parsing responsibilties to <code>subject</code> if it is * non-null, and returns <code>NO_MATCH</code> otherwise. * * @see Parser#parse */ @Override public int parse(char[] buf, int start, int end, T data) { if (subject != null) { return subject.parse(buf, start, end, data); } else { return NO_MATCH; } } /** * Sets the <code>subject</code> member. * * @param subject The<code>Parser</code> that this parser delegates * parsing responsibilities to. */ public void set(Parser<T> subject) { this.subject = subject; } }