Package com.dci.intellij.dbn.language.common.element.parser

Source Code of com.dci.intellij.dbn.language.common.element.parser.NestedRangeMonitor

package com.dci.intellij.dbn.language.common.element.parser;

import com.dci.intellij.dbn.language.common.DBLanguageDialect;
import com.dci.intellij.dbn.language.common.SharedTokenTypeBundle;
import com.dci.intellij.dbn.language.common.SimpleTokenType;
import com.dci.intellij.dbn.language.common.TokenType;
import com.dci.intellij.dbn.language.common.element.impl.NestedRangeElementType;
import com.dci.intellij.dbn.language.common.element.path.ParsePathNode;
import com.intellij.lang.PsiBuilder;
import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NotNull;

public class NestedRangeMonitor {
    private int depth = 0;
    private Stack<NestedRangeStartMarker> markers = new Stack<NestedRangeStartMarker>();
    private DBLanguageDialect languageDialect;
    private PsiBuilder builder;

    private SimpleTokenType leftParenthesis;
    private SimpleTokenType rightParenthesis;


    public NestedRangeMonitor(PsiBuilder builder, DBLanguageDialect languageDialect) {
        this.builder = builder;
        this.languageDialect = languageDialect;

        SharedTokenTypeBundle sharedTokenTypes = languageDialect.getParserTokenTypes().getSharedTokenTypes();
        leftParenthesis = sharedTokenTypes.getLeftParenthesis();
        rightParenthesis = sharedTokenTypes.getRightParenthesis();
    }

    /**
     * cleanup all markers registered after the builder offset (remained dirty after a marker rollback)
     */
    public void reset() {
        int builderOffset = builder.getCurrentOffset();
        while (markers.size() > 0) {
            NestedRangeStartMarker lastMarker = markers.peek();
            if (lastMarker.getOffset() >= builderOffset) {
                markers.pop();
                if (depth > 0) depth--;
            } else {
                break;
            }
        }
    }

    public void compute(@NotNull ParsePathNode node, boolean mark) {
        TokenType tokenType = (TokenType) builder.getTokenType();
        if (tokenType == leftParenthesis) {
            depth++;
            int builderOffset =  builder.getCurrentOffset();
            NestedRangeStartMarker marker = new NestedRangeStartMarker(node, builderOffset);
            markers.push(marker);
        } else if (tokenType == rightParenthesis) {
            if (depth > 0) depth--;
            if (markers.size() > 0) {
                NestedRangeStartMarker marker = markers.peek();
                ParsePathNode markerNode = marker.getParentNode();
                if (markerNode == node || markerNode.isSiblingOf(node)) {
                    // nesting is closed in the same element or in parent element (as a result of advanced parser due to error)
                    // => nesting should be settled here
                    settle();
                } else if (node.isSiblingOf(markerNode)) {
                    // parent nesting is closing (prematurely) in child element
                    // => parent is settling the nesting after it is processed
                    // => parsing in ALL child elements must be interrupted
                    while (node != markerNode) {
                        node.setExitParsing(true);
                        node = node.getParent();
                    }
                }
            }
        }
    }

    /**
     * close nested range markers (i.e. create nested range elements)
     */
    public void settle() {
        while(markers.size() > depth) {
            markers.pop();
        }
    }

    private NestedRangeElementType getNestedRangeElementType() {
        return languageDialect.getParserDefinition().getParser().getElementTypes().getNestedRangeElementType();
    }
}
TOP

Related Classes of com.dci.intellij.dbn.language.common.element.parser.NestedRangeMonitor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.