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

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

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

import com.dci.intellij.dbn.language.common.ParseException;
import com.dci.intellij.dbn.language.common.SharedTokenTypeBundle;
import com.dci.intellij.dbn.language.common.TokenType;
import com.dci.intellij.dbn.language.common.element.IdentifierElementType;
import com.dci.intellij.dbn.language.common.element.LeafElementType;
import com.dci.intellij.dbn.language.common.element.QualifiedIdentifierElementType;
import com.dci.intellij.dbn.language.common.element.TokenElementType;
import com.dci.intellij.dbn.language.common.element.impl.QualifiedIdentifierVariant;
import com.dci.intellij.dbn.language.common.element.lookup.ElementTypeLookupCache;
import com.dci.intellij.dbn.language.common.element.parser.AbstractElementTypeParser;
import com.dci.intellij.dbn.language.common.element.parser.ParseResult;
import com.dci.intellij.dbn.language.common.element.parser.ParseResultType;
import com.dci.intellij.dbn.language.common.element.parser.ParserBuilder;
import com.dci.intellij.dbn.language.common.element.parser.ParserContext;
import com.dci.intellij.dbn.language.common.element.path.ParsePathNode;
import com.dci.intellij.dbn.language.common.element.path.PathNode;
import com.dci.intellij.dbn.language.common.element.util.ParseBuilderErrorHandler;
import com.intellij.lang.PsiBuilder;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class QualifiedIdentifierElementTypeParser extends AbstractElementTypeParser<QualifiedIdentifierElementType> {
    public QualifiedIdentifierElementTypeParser(QualifiedIdentifierElementType elementType) {
        super(elementType);
    }

    public ParseResult parse(@NotNull ParsePathNode parentNode, boolean optional, int depth, ParserContext context) throws ParseException {
        ParserBuilder builder = context.getBuilder();
        logBegin(builder, optional, depth);
        ParsePathNode node = createParseNode(parentNode, builder.getCurrentOffset());

        TokenElementType separatorToken = getElementType().getSeparatorToken();

        PsiBuilder.Marker marker = builder.mark(node);
        int matchedTokens = 0;

        QualifiedIdentifierVariant variant = getMostProbableParseVariant(builder, node);
        if (variant != null) {
            LeafElementType[] elementTypes = variant.getLeafs();

            int currentSiblingPosition = 0;
            for (LeafElementType elementType : elementTypes) {
                ParseResult result = elementType.getParser().parse(node, true, depth + 1, context);
                if (result.isNoMatch()) breakelse matchedTokens = matchedTokens + result.getMatchedTokens();

                if (elementType != elementTypes[elementTypes.length -1])  {
                    result = separatorToken.getParser().parse(node, true, depth + 1, context);
                    if (result.isNoMatch()) break; else matchedTokens = matchedTokens + result.getMatchedTokens();
                }
                node.incrementIndex(builder.getCurrentOffset());
            }

            if (variant.isIncomplete()) {
                Set<TokenType> expected = new THashSet<TokenType>();
                expected.add(separatorToken.getTokenType());
                ParseBuilderErrorHandler.updateBuilderError(expected, context);
                return stepOut(marker, depth, ParseResultType.PARTIAL_MATCH, matchedTokens, node, context);
            } else {
                return stepOut(marker, depth, ParseResultType.FULL_MATCH, matchedTokens, node, context);
            }


        } else {
            return stepOut(marker, depth, ParseResultType.NO_MATCH, matchedTokens, node, context);
        }
    }

    private QualifiedIdentifierVariant getMostProbableParseVariant(ParserBuilder builder, ParsePathNode node) {
        QualifiedIdentifierElementType elementType = getElementType();
        TokenType separatorToken = elementType.getSeparatorToken().getTokenType();
        ElementTypeLookupCache lookupCache = elementType.getLookupCache();
        SharedTokenTypeBundle sharedTokenTypes = getElementType().getLanguage().getSharedTokenTypes();
        TokenType identifier = sharedTokenTypes.getIdentifier();


        List<TokenType> chan = new ArrayList<TokenType>();
        int offset = 0;
        boolean wasSeparator = true;
        TokenType tokenType = builder.lookAhead(offset);
        while (tokenType != null) {
            if (tokenType == separatorToken) {
                if (wasSeparator) chan.add(identifier);
                wasSeparator = true;
            } else {
                if (wasSeparator) {
                    if (tokenType.isIdentifier() || lookupCache.containsToken(tokenType))
                        chan.add(tokenType); else
                        chan.add(identifier);
                } else {
                   break;
                }
                wasSeparator = false;
            }
            offset++;
            tokenType = builder.lookAhead(offset);
            if (tokenType == null && wasSeparator) chan.add(identifier);
        }

        QualifiedIdentifierVariant mostProbableVariant = null;

        for (LeafElementType[] elementTypes : getElementType().getVariants()) {
            if (elementTypes.length <= chan.size()) {
                int matchedTokens = 0;
                for (int i=0; i<elementTypes.length; i++) {
                    if (elementTypes[i].getTokenType().matches(chan.get(i))) {
                        matchedTokens++;
                    }
                }
                if (mostProbableVariant == null || mostProbableVariant.getMatchedTokens() < matchedTokens) {
                    mostProbableVariant = mostProbableVariant == null ?
                            new QualifiedIdentifierVariant(elementTypes, matchedTokens) :
                            mostProbableVariant.replace(elementTypes, matchedTokens);
                }

            }
        }

        return mostProbableVariant;
    }

    private QualifiedIdentifierVariant getMostProbableParseVariant_(ParserBuilder builder, ParsePathNode node) {

        TokenElementType separatorToken = getElementType().getSeparatorToken();

        QualifiedIdentifierVariant mostProbableVariant = null;
        int initialSiblingIndex = node.getCurrentSiblingIndex();

        try {
            for (LeafElementType[] variants : getElementType().getVariants()) {
                int offset = 0;
                //PsiBuilder.Marker marker = builder.mark();
                int matchedTokens = 0;
                for (int i=0; i< variants.length; i++) {
                    TokenType tokenType = builder.lookAhead(offset);
                    // if no mach -> consider as partial if not first element

                    node.setCurrentSiblingIndex(i);
                    if (match(variants[i], tokenType, node, true)) {
                        matchedTokens++;
                        offset++;


                        tokenType = builder.lookAhead(offset);
                        boolean isSeparator = tokenType == separatorToken.getTokenType();
                        boolean isFullMatch = matchedTokens == variants.length;
                        boolean isLastElement = i == variants.length - 1;

                        if (isLastElement) {
                            QualifiedIdentifierVariant variant = new QualifiedIdentifierVariant(variants, matchedTokens);
                            if ((isFullMatch && !isSeparator) || variant.containsNonIdentifierTokens()) {
                                //markerRollbackTo(marker);
                                return variant;
                            }

                            if (mostProbableVariant == null || matchedTokens > mostProbableVariant.getMatchedTokens()) {
                                mostProbableVariant = variant;
                            }
                            break;
                        } else {
                            if (!isSeparator) {  // is not separator token
                                QualifiedIdentifierVariant variant = new QualifiedIdentifierVariant(variants, matchedTokens);
                                if (mostProbableVariant == null || mostProbableVariant.getMatchedTokens() < variant.getMatchedTokens()) {
                                    mostProbableVariant = variant;
                                }
                                break;
                            }
                        }
                        offset++;
                    } else {
                        if (matchedTokens > 0)  {
                            QualifiedIdentifierVariant variant = new QualifiedIdentifierVariant(variants, matchedTokens);
                            if (variant.containsNonIdentifierTokens()) {
                                //markerRollbackTo(marker);
                                return variant;
                            }
                            if (mostProbableVariant == null || mostProbableVariant.getMatchedTokens() < variant.getMatchedTokens()) {
                                mostProbableVariant = variant;
                            }
                        }
                        break;
                    }
                }
            }
        }
        finally {
            node.setCurrentSiblingIndex(initialSiblingIndex);
        }

        return mostProbableVariant;
    }

    private boolean match(LeafElementType leafElementType, TokenType tokenType, PathNode node, boolean leniant) {
        if (leafElementType instanceof IdentifierElementType) {
            return tokenType != null && (tokenType.isIdentifier() || (leniant && isSuppressibleReservedWord(tokenType, node)));
        } else if (leafElementType instanceof TokenElementType) {
            TokenElementType tokenElementType = (TokenElementType) leafElementType;
            return tokenElementType.getTokenType() == tokenType;
        }
        return false;
    }
}
TOP

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

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.