parser.listeners.CheckListener.java Source code

Java tutorial

Introduction

Here is the source code for parser.listeners.CheckListener.java

Source

/* 
 *  
 * CheckListener.java
 *  
 * written by Adrian Hintze
 *  
 * Copyright (c) 2015 by Adrian Hintze
 * 
 * This file is a part of Snapp!
 * 
 * Snapp! is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of
 * the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */

package parser.listeners;

import org.antlr.v4.runtime.ParserRuleContext;

import utils.Logger;
import antlr4.SnapGrammarBaseListener;
import antlr4.SnapGrammarParser.And_operatorContext;
import antlr4.SnapGrammarParser.Arithmetic_operatorContext;
import antlr4.SnapGrammarParser.Assign_operatorContext;
import antlr4.SnapGrammarParser.BooleanContext;
import antlr4.SnapGrammarParser.Comparison_operatorContext;
import antlr4.SnapGrammarParser.End_statementContext;
import antlr4.SnapGrammarParser.Glorified_arithmetic_operatorContext;
import antlr4.SnapGrammarParser.IdContext;
import antlr4.SnapGrammarParser.NumberContext;
import antlr4.SnapGrammarParser.Or_operatorContext;
import antlr4.SnapGrammarParser.Regular_expressionContext;
import antlr4.SnapGrammarParser.Sign_operatorContext;
import antlr4.SnapGrammarParser.StringContext;
import dataStructures.ClassInfo;
import dataStructures.ClassParents;
import dataStructures.GlobalInfo;
import dataStructures.WalkInfo;

public class CheckListener extends SnapGrammarBaseListener {

    /* private attributes */

    private GlobalInfo globalInfo = GlobalInfo.getInstance();

    /* private methods */

    private void add(ParserRuleContext ctx, Boolean valid, Boolean print, GlobalInfo.nodeTypes type,
            ClassInfo value) {
        if (print)
            Logger.printValue(ctx, valid.toString() + " : " + ctx.getText());
        WalkInfo info = new WalkInfo(valid, ctx.getText());
        info.setClassType(value);
        info.setNodeType(type);
        globalInfo.getCurrentQueue().add(info);
    }

    private void checkAndAdd(ParserRuleContext ctx, Boolean valid, Boolean print, GlobalInfo.nodeTypes type) {
        Boolean symbolExists;
        String code = ctx.getText();
        ClassInfo classType = null;
        if (globalInfo.getObjectContext() != null) {
            ClassInfo ci = globalInfo.getObjectContext();
            globalInfo.setPreviousObjectContext(ci);

            // this avoids issues in case one Class overwrites a method from it's parent
            if (globalInfo.isTopLevel() && globalInfo.isLeftSideAssignment())
                classType = ci.getPropertyExcludeParents(code);
            // we supose that inside a function we don't modify the prototype
            else {
                classType = ci.getProperty(code);
                //example: Object.keys will fail because we're checking
                //the function, instead of the class
                if (classType == null) {
                    if (globalInfo.getClasses().get(ci.getName()) != null) {
                        ci = globalInfo.getClasses().get(ci.getName());
                        globalInfo.setPreviousObjectContext(ci);
                        classType = ci.getProperty(code);
                    }
                }
            }

            if (code.equals("prototype")) {
                symbolExists = true;
                classType = ci;
            } else if (classType != null) {
                symbolExists = true;
            } else
                symbolExists = false;

            //TODO add property automatically to all objects instead of hardcoding it here
            if (classType == null && code.equals("constructor")) {
                symbolExists = true;
                // TODO eventually we may need to support multiple parentClass
                ClassInfo constructor = globalInfo.getDocumentScope()
                        .getSymbolOfStack(globalInfo.getObjectContext().getParentClasses().getAllParents().get(0));
                globalInfo.setObjectContext(constructor);
                classType = constructor;
            }
        } else {
            classType = globalInfo.getCurrentScope().getSymbolOfStack(code);
            if (classType == null)
                classType = globalInfo.getClasses().get(code);
            symbolExists = classType != null;
        }
        if (classType != null)
            classType = new ClassInfo(classType);
        add(ctx, symbolExists, print, type, classType);
    }

    /* public methods*/

    /*********************/
    /*  STATEMENT UTILS  */
    /*********************/

    //ASSIGN OPERATOR
    @Override
    public void enterAssign_operator(Assign_operatorContext ctx) {
        Logger.printRuleName("enterAssign_operatorCheck", ctx);
        add(ctx, true, true, null, null);
    }

    @Override
    public void exitAssign_operator(Assign_operatorContext ctx) {
        Logger.printRuleName("exitAssign_operatorCheck", ctx);
    }

    //END STATEMENT
    @Override
    public void enterEnd_statement(End_statementContext ctx) {
        //Logger.printRuleName("enterEnd_statementCheck", ctx);
        add(ctx, true, false, GlobalInfo.nodeTypes.END_STATEMENT, null);
    }

    @Override
    public void exitEnd_statement(End_statementContext ctx) {
        //Logger.printRuleName("exitEnd_statementCheck", ctx);
    }

    /********************/
    /*   INSTRUCTIONS   */
    /********************/

    //ARITHMETIC OPERATOR
    @Override
    public void enterArithmetic_operator(Arithmetic_operatorContext ctx) {
        Logger.printRuleName("enterCheckArithmetic_operator", ctx);
        add(ctx, true, true, null, null);
    }

    @Override
    public void exitArithmetic_operator(Arithmetic_operatorContext ctx) {
        Logger.printRuleName("exitCheckArithmetic_operator", ctx);
    }

    //GLORIFIED ARITHMETIC OPERATOR
    @Override
    public void enterGlorified_arithmetic_operator(Glorified_arithmetic_operatorContext ctx) {
        Logger.printRuleName("enterCheckArithmetic_operator", ctx);
        add(ctx, true, true, null, null);
    }

    @Override
    public void exitGlorified_arithmetic_operator(Glorified_arithmetic_operatorContext ctx) {
        Logger.printRuleName("exitCheckArithmetic_operator", ctx);
    }

    //AND OPERATOR
    @Override
    public void enterAnd_operator(And_operatorContext ctx) {
        Logger.printRuleName("enterCheckAnd_operator", ctx);
        add(ctx, true, true, null, null);
    }

    @Override
    public void exitAnd_operator(And_operatorContext ctx) {
        Logger.printRuleName("exitCheckAnd_operator", ctx);
    }

    //OR OPERATOR
    @Override
    public void enterOr_operator(Or_operatorContext ctx) {
        Logger.printRuleName("enterCheckOr_operator", ctx);
        add(ctx, true, true, null, null);
    }

    @Override
    public void exitOr_operator(Or_operatorContext ctx) {
        Logger.printRuleName("exitCheckOr_operator", ctx);
    }

    //COMPARISON OPERATOR
    @Override
    public void enterComparison_operator(Comparison_operatorContext ctx) {
        Logger.printRuleName("enterCheckComparison_operator", ctx);
        add(ctx, true, true, null, null);
    }

    @Override
    public void exitComparison_operator(Comparison_operatorContext ctx) {
        Logger.printRuleName("exitCheckComparison_operator", ctx);
    }

    //SIGN OPERATOR
    @Override
    public void enterSign_operator(Sign_operatorContext ctx) {
        Logger.printRuleName("enterCheckComparison_operator", ctx);
        add(ctx, true, true, null, null);
    }

    @Override
    public void exitSign_operator(Sign_operatorContext ctx) {
        Logger.printRuleName("exitCheckComparison_operator", ctx);
    }

    /********************/
    /*       ATOMS      */
    /********************/

    //IDENTIFIER
    @Override
    public void enterId(IdContext ctx) {
        Logger.printRuleName("enterCheckId", ctx);
        checkAndAdd(ctx, true, true, GlobalInfo.nodeTypes.IDENTIFIER);
    }

    @Override
    public void exitId(IdContext ctx) {
        Logger.printRuleName("exitCheckId", ctx);
    }

    //REGULAR EXPRESSION
    @Override
    public void enterRegular_expression(Regular_expressionContext ctx) {
        Logger.printRuleName("enterCheckRegular_expression", ctx);
        add(ctx, true, true, null, null);
    }

    @Override
    public void exitRegular_expression(Regular_expressionContext ctx) {
        Logger.printRuleName("exitCheckRegular_expression", ctx);
    }

    //STRING
    @Override
    public void enterString(StringContext ctx) {
        Logger.printRuleName("enterCheckString", ctx);
        add(ctx, true, true, GlobalInfo.nodeTypes.STRING, new ClassInfo("", new ClassParents("String")));
    }

    @Override
    public void exitString(StringContext ctx) {
        Logger.printRuleName("exitCheckString", ctx);
    }

    //NUMBER
    @Override
    public void enterNumber(NumberContext ctx) {
        Logger.printRuleName("enterCheckNumber", ctx);
        add(ctx, true, true, GlobalInfo.nodeTypes.NUMBER, new ClassInfo("", new ClassParents("Number")));
    }

    @Override
    public void exitNumber(NumberContext ctx) {
        Logger.printRuleName("exitCheckNumber", ctx);
    }

    //BOOLEAN
    @Override
    public void enterBoolean(BooleanContext ctx) {
        Logger.printRuleName("enterCheckBoolean", ctx);
        add(ctx, true, true, GlobalInfo.nodeTypes.BOOLEAN, new ClassInfo("", new ClassParents("Boolean")));
    }

    @Override
    public void exitBoolean(BooleanContext ctx) {
        Logger.printRuleName("exitCheckBoolean", ctx);
    }

}