All Downloads are FREE. Search and download functionalities are using the official Maven repository.

eu.cqse.check.framework.util.tokens.SkipNestedPattern Maven / Gradle / Ivy

Go to download

The Teamscale Custom Check API allows users to extend Teamscale by writing custom analyses that create findings.

There is a newer version: 2024.7.2
Show newest version
/*
 * Copyright (c) CQSE GmbH
 *
 * 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 eu.cqse.check.framework.util.tokens;

/**
 * Matches a nested structure (e.g. nested parentheses).
 */
public class SkipNestedPattern extends TokenPatternBase {

	/** Matches the token that increases the nesting level. */
	private final TokenPatternBase openMatcher;

	/** Matches the token that decreases the nesting level. */
	private final TokenPatternBase closeMatcher;

	/**
	 * If this is true, this pattern matches, even if no nested structure is found at the
	 * current position. In this case, an empty match is returned.
	 */
	private final boolean optional;

	/** Constructor. */
	public SkipNestedPattern(TokenPatternBase openMatcher, TokenPatternBase closeMatcher, boolean optional) {
		this.openMatcher = openMatcher;
		this.closeMatcher = closeMatcher;
		this.optional = optional;
	}

	/** {@inheritDoc} */
	@Override
	protected TokenPatternMatch matchesLocally(TokenStream stream) {
		int beforeMatch = stream.getPosition();
		TokenPatternMatch parentMatch = createMatch(stream);

		TokenPatternMatch openMatch = openMatcher.matches(stream);
		if (openMatch == null) {
			if (optional) {
				stream.setPosition(beforeMatch);
				return createMatch(stream);
			}
			return null;
		}
		parentMatch.mergeFrom(openMatch);

		int level = 1;
		while (level > 0) {
			if (stream.isExhausted()) {
				if (optional) {
					stream.setPosition(beforeMatch);
					return createMatch(stream);
				}
				return null;
			}

			int beforeAlternative = stream.getPosition();
			TokenPatternMatch alternativeSubMatch = closeMatcher.matches(stream);
			if (alternativeSubMatch != null) {
				parentMatch.mergeFrom(alternativeSubMatch);
				level -= 1;
				continue;
			}
			stream.setPosition(beforeAlternative);

			alternativeSubMatch = openMatcher.matches(stream);
			if (alternativeSubMatch != null) {
				parentMatch.mergeFrom(alternativeSubMatch);
				level += 1;
				continue;
			}
			stream.setPosition(beforeAlternative);

			stream.next();
		}

		return parentMatch;
	}

	/** {@inheritDoc} */
	@Override
	public String toString() {
		return "SkipNested (OPEN: " + openMatcher.toString() + " CLOSE: " + closeMatcher.toString() + " optional: "
				+ optional + ")";
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy