001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.wicket.util.parse.metapattern.parsers;
018:
019: import java.util.regex.Matcher;
020:
021: import org.apache.wicket.util.parse.metapattern.MetaPattern;
022:
023: /**
024: * Base class for various MetaPattern based parsers.
025: *
026: * @author Jonathan Locke
027: */
028: public abstract class MetaPatternParser {
029: /** The input to parse */
030: private final CharSequence input;
031:
032: /** The length of the input; no. of characters */
033: private final int length;
034:
035: /**
036: * The position (index) behind the last pattern group matched while
037: * advancing from one pattern group to the next one.
038: */
039: private int pos;
040:
041: /** The object maintaining all the regex match details */
042: private Matcher matcher;
043:
044: /**
045: * Construct the parser. You must call
046: *
047: * @see #advance(MetaPattern) to initialize the matcher with the pattern.
048: * @param input
049: * to parse
050: */
051: public MetaPatternParser(final CharSequence input) {
052: this .input = input;
053: this .length = input.length();
054: }
055:
056: /**
057: * Construct the parser and initialize the matcher with the pattern given.
058: *
059: * @param pattern
060: * Meta pattern
061: * @param input
062: * Input to parse
063: */
064: public MetaPatternParser(final MetaPattern pattern,
065: final CharSequence input) {
066: this (input);
067: setPattern(pattern);
068: }
069:
070: /**
071: * @param pattern
072: * Pattern
073: */
074: public void setPattern(final MetaPattern pattern) {
075: this .matcher = pattern.matcher(input);
076: }
077:
078: /**
079: * Advance parsing to the next element. The internal cursor will be moved to
080: * end of the string matched.
081: *
082: * @param pattern
083: * Meta pattern
084: * @return True if found, false otherwise
085: */
086: protected final boolean advance(final MetaPattern pattern) {
087: // get the remaining part of the input
088: final CharSequence s = input.subSequence(pos, length);
089:
090: // does the pattern match?
091: this .matcher = pattern.matcher(s);
092: if (matcher.lookingAt()) {
093: // Yes, it does. Move the cursor to the end of the
094: // char sequence matched.
095: pos += matcher.end();
096:
097: // Found the pattern
098: return true;
099: }
100:
101: // Did not find the pattern.
102: return false;
103: }
104:
105: /**
106: * Whether the matcher matches the pattern.
107: *
108: * @return whether the matcher matches
109: */
110: public boolean matches() {
111: return matcher.matches();
112: }
113:
114: /**
115: * Gets the matcher.
116: *
117: * @return the matcher
118: */
119: public final Matcher matcher() {
120: return matcher;
121: }
122:
123: /**
124: * Whether the internal cursor has advanced to the end of the input.
125: *
126: * @return whether the input is parsed
127: */
128: public final boolean atEnd() {
129: return pos == length;
130: }
131: }
|