Package org.intellij.lang.jflex.parser

Source Code of org.intellij.lang.jflex.parser.JFlexParser

package org.intellij.lang.jflex.parser;

import com.intellij.lang.ASTNode;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.PsiParser;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.psi.tree.IElementType;
import org.intellij.lang.jflex.JFlexElementTypes;
import org.intellij.lang.jflex.util.JFlexBundle;
import org.jetbrains.annotations.NotNull;

/**
* Parser.
*
* @author Alexey Efimov, Max Ishchenko
*/
public class JFlexParser implements PsiParser {

    private static final Logger LOG = Logger.getInstance("#JFlexParser");

    private final Project project;

    public JFlexParser(Project project) {
        this.project = project;
    }

    @NotNull
    public ASTNode parse(IElementType root, PsiBuilder builder) {

        final PsiBuilder.Marker rootMarker = builder.mark();

        while (!builder.eof()) {
            parse(builder);
        }
        rootMarker.done(root);

        return builder.getTreeBuilt();

    }

    private void parse(PsiBuilder builder) {
        IElementType first = builder.getTokenType();
        if (first == JFlexElementTypes.MACROS) {
            parseMacroDefinition(builder);
        } else if (first == JFlexElementTypes.CLASS_KEYWORD) {
            parseClassStatement(builder);
        } else if (first == JFlexElementTypes.STATE_KEYWORD) {
            parseStateStatement(builder);
        } else if (first == JFlexElementTypes.XSTATE_KEYWORD) {
            parseXstateStatement(builder);
        } else if (first == JFlexElementTypes.STATE_REF) {
            parseStateReference(builder);
        } else if (first == JFlexElementTypes.IMPLEMENTS_KEYWORD) {
            parseImplementsStatement(builder);
        } else if (first == JFlexElementTypes.TYPE_KEYWORD) {
            parseTypeStatement(builder);
        } else if (first == JFlexElementTypes.JAVA_CODE) {
            parseJavaCode(builder);
        } else if (first == JFlexElementTypes.REGEXP_MACROS_REF) {
            parseMacroReference(builder);
        } else {
            builder.advanceLexer();
        }
    }

    private void parseStateReference(PsiBuilder builder) {
        PsiBuilder.Marker mark = builder.mark();
        builder.advanceLexer();
        mark.done(JFlexElementTypes.STATE_REF);
    }

    private void parseCommaSeparatedOptionStatement(PsiBuilder builder, IElementType finishWith) {
        parseCommaSeparatedOptionStatement(builder, finishWith, JFlexElementTypes.OPTION_PARAMETER);
    }

    private void parseCommaSeparatedOptionStatement(PsiBuilder builder, IElementType finishWith, IElementType markWith) {

        PsiBuilder.Marker stateMarker = builder.mark();
        builder.advanceLexer();

        boolean first = true;

        while (builder.getTokenType() == JFlexElementTypes.OPTION_PARAMETER || builder.getTokenType() == JFlexElementTypes.OPTION_COMMA) {

            if (first) {
                first = false;
            } else {
                //parsing commas or go to next expr
                if (builder.getTokenType() == JFlexElementTypes.OPTION_COMMA) {
                    builder.advanceLexer();
                } else {
                    builder.error(JFlexBundle.message("parser.comma.expected"));
                }
            }

            PsiBuilder.Marker interfaceMarker = builder.mark();
            if (builder.getTokenType() == JFlexElementTypes.OPTION_PARAMETER) {
                builder.advanceLexer();
                interfaceMarker.done(markWith);
            } else {
                builder.error(JFlexBundle.message("parser.expression.expected"));
                interfaceMarker.drop();
                break;
            }
        }

        stateMarker.done(finishWith);

    }

    private void parseStateStatement(PsiBuilder builder) {
        parseCommaSeparatedOptionStatement(builder, JFlexElementTypes.STATE_STATEMENT, JFlexElementTypes.STATE_DEFINITION);

    }

    private void parseXstateStatement(PsiBuilder builder) {
        parseCommaSeparatedOptionStatement(builder, JFlexElementTypes.STATE_STATEMENT, JFlexElementTypes.STATE_DEFINITION);
    }

    private void parseMacroDefinition(PsiBuilder builder) {

        PsiBuilder.Marker macroDefinition = builder.mark();
        builder.advanceLexer();

        if (builder.getTokenType() != JFlexElementTypes.EQ) {
            builder.error(JFlexBundle.message("parser.eq.expected"));
        } else {
            builder.advanceLexer();
        }

        int found = 0;
        PsiBuilder.Marker macrovalue = builder.mark();

        while (JFlexElementTypes.REGEXP_SCOPE.contains(builder.getTokenType())) {
            found++;
            builder.advanceLexer();
        }

        if (found == 0) {
            macrovalue.drop();
            builder.error(JFlexBundle.message("parser.macrovalue.expected"));
        } else {
            macrovalue.done(JFlexElementTypes.REGEXP);
        }

        macroDefinition.done(JFlexElementTypes.MACRO_DEFINITION);

    }

    private void parseMacroReference(PsiBuilder builder) {
        PsiBuilder.Marker macroMarker = builder.mark();
        builder.advanceLexer();
        macroMarker.done(JFlexElementTypes.REGEXP_MACROS_REF);
    }

    private void parseImplementsStatement(PsiBuilder builder) {
        parseCommaSeparatedOptionStatement(builder, JFlexElementTypes.IMPLEMENTS_STATEMENT);
    }

    private void parseTypeStatement(PsiBuilder builder) {
        LOG.assertTrue(builder.getTokenType() == JFlexElementTypes.TYPE_KEYWORD);
        PsiBuilder.Marker marker = builder.mark();
        builder.advanceLexer();
        parseOptionParamExpression(builder);
        marker.done(JFlexElementTypes.TYPE_STATEMENT);
    }

    private void parseJavaCode(PsiBuilder builder) {
        PsiBuilder.Marker marker = builder.mark();
        builder.advanceLexer();
        marker.done(JFlexElementTypes.JAVA_CODE);
    }

    private void parseClassStatement(PsiBuilder builder) {
        LOG.assertTrue(builder.getTokenType() == JFlexElementTypes.CLASS_KEYWORD);
        PsiBuilder.Marker marker = builder.mark();
        builder.advanceLexer();
        parseOptionParamExpression(builder);
        marker.done(JFlexElementTypes.CLASS_STATEMENT);
    }

    private void parseOptionParamExpression(PsiBuilder builder) {
        PsiBuilder.Marker expr = builder.mark();
        if (builder.getTokenType() != JFlexElementTypes.OPTION_PARAMETER) {
            builder.error(JFlexBundle.message("parser.expression.expected"));
            expr.drop();
        } else {
            builder.advanceLexer();
            expr.done(JFlexElementTypes.OPTION_PARAMETER);
        }
    }
}
TOP

Related Classes of org.intellij.lang.jflex.parser.JFlexParser

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.