org.eclipse.titan.common.parsers.IntervalDetector.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.titan.common.parsers.IntervalDetector.java

Source

/******************************************************************************
 * Copyright (c) 2000-2016 Ericsson Telecom AB
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 ******************************************************************************/
package org.eclipse.titan.common.parsers;

import java.util.List;

import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.Token;
import org.eclipse.titan.common.parsers.Interval.interval_type;
import org.eclipse.titan.common.parsers.cfg.CfgParseTreePrinter;

/**
 * @author Kristof Szabados
 * @author Arpad Lovassy
 */
public class IntervalDetector {
    /** the root interval of the interval hierarchy tree. */
    protected Interval rootInterval = null;
    /** the actual interval, that can be modified directly. */
    protected Interval actualInterval = null;

    private int maxLength;

    /**
     * Creates and initializes the root interval, and sets it as the actual interval.
     *
     * @param length the length of the root interval
     * */
    public void initRootInterval(final int length) {
        actualInterval = new Interval(null, interval_type.NORMAL);
        rootInterval = actualInterval;
        actualInterval.setStartOffset(0);
        actualInterval.setStartLine(0);
        actualInterval.setEndOffset(length);
        maxLength = length;
    }

    /**
     * @return the pre-set maximum length any interval can reach.
     * */
    protected int getMaxLength() {
        return maxLength;
    }

    /**
     * Sets the maximum length an interval can reach.
     * Used to correct the last intervals, if needed.
     *
     * @param maxLength the length of the processed document.
     * */
    protected void setMaxLength(final int maxLength) {
        this.maxLength = maxLength;
    }

    /**
     * Creates and pushes a new interval onto the stack of intervals. This new interval becomes the actual one.
     * <p>
     * The ending offset of this interval is not yet set. @see #popInterval(int)
     *
     * @param offset the offset at which the new interval should start
     * @param line the line at which the new interval should start
     * @param type the type of the interval
     */
    public final void pushInterval(final int offset, final int line, final interval_type type) {
        actualInterval = new Interval(actualInterval, type);
        if (rootInterval == null) {
            rootInterval = actualInterval;
        }
        actualInterval.setStartOffset(offset);
        actualInterval.setStartLine(line);
    }

    /**
     * Creates and pushes a new interval onto the stack of intervals. This new interval becomes the actual one.
     * <p>
     * The ending offset of this interval is not yet set. @see #popInterval(int)
     *
     * @param aToken the first token of the interval
     * @param aType the type of the interval
     */
    public final void pushInterval(final Token aToken, final interval_type aType) {
        pushInterval(aToken.getCharPositionInLine(), aToken.getLine(), aType);
    }

    /**
     * Pops the actual interval off of the stack, making its parent the actual interval. The ending offset of the popped off interval is set here.
     * <p>
     * If the actual interval is the root interval, than it is not popped off the stack. This situation can only happen in case of a syntactically
     * invalid file.
     *
     * @param offset the offset value to be set as the ending offset of the actual interval
     * @param line the line to be set as the ending line of the actual interval
     * */
    public final void popInterval(final int offset, final int line) {
        if (actualInterval != null) {
            actualInterval.setEndOffset(offset);
            actualInterval.setEndLine(line);
            if (rootInterval.equals(actualInterval)) {
                actualInterval.setErroneous();
            } else {
                actualInterval = actualInterval.getParent();
            }
        }
    }

    /**
     * Pops the actual interval off of the stack, making its parent the actual interval. The ending offset of the popped off interval is set here.
     * <p>
     * If the actual interval is the root interval, than it is not popped off the stack. This situation can only happen in case of a syntactically
     * invalid file.
     *
     * @param aToken the last token of the interval
     */
    public final void popInterval(final Token aToken) {
        popInterval(aToken.getCharPositionInLine(), aToken.getLine());
    }

    /**
     * Pops the actual interval off of the stack, making its parent the actual interval. The ending offset of the popped off interval is set here.
     * <p>
     * If the actual interval is the root interval, than it is not popped off the stack. This situation can only happen in case of a syntactically
     * invalid file.
     * <p>
     * The last non-hidden token will be the end of the interval.
     *
     * @param aTokenStream token stream to get the list of tokens for searching hidden tokens
     */
    public final void popInterval(final CommonTokenStream aTokenStream) {
        final int nonHiddenIndex = getNonHiddenTokensBefore(aTokenStream.index() - 1, aTokenStream.getTokens());
        final Token t = aTokenStream.get(nonHiddenIndex);
        popInterval(t);
    }

    /**
     * @param aIndex the token index, where the search is started
     * @param aTokens token list from token stream
     * @return the index of the first non-hidden token to the left
     */
    private final int getNonHiddenTokensBefore(final int aIndex, final List<Token> aTokens) {
        // 1st non hidden token to the left
        int nonHiddenIndex = aIndex;
        while (CfgParseTreePrinter.isHiddenToken(nonHiddenIndex, aTokens)) {
            nonHiddenIndex--;
        }
        return nonHiddenIndex;
    }

    /**
     * @return the root interval of this interval hierarchy tree.
     * */
    public final Interval getRootInterval() {
        return rootInterval;
    }

    /**
     * This function shall be called after the reading of the source of the intervals has finished. If the actual interval is not the root interval,
     * or if its ending offset is not set, this indicates syntax errors in the file. To make the built interval hierarchy is usable, the ending offset of
     * the actual interval and all of its parents is set to one less than the root intervals ending offset.
     * */
    public void handleFinalCorrection() {
        if (rootInterval == null) {
            return;
        }

        while (actualInterval != null && !actualInterval.equals(rootInterval)) {
            actualInterval.setErroneous();

            // TODO the ending line should be set correctly.
            popInterval(maxLength - 1, -1);
        }
    }
}