Package pspdash.data.compiler

Source Code of pspdash.data.compiler.FindLastExpression

// PSP Dashboard - Data Automation Tool for PSP-like processes
// Copyright (C) 2003 Software Process Dashboard Initiative
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//
// The author(s) may be contacted at:
// OO-ALC/TISHD
// Attn: PSP Dashboard Group
// 6137 Wardleigh Road
// Hill AFB, UT 84056-5843
//
// E-Mail POC:  processdash-devel@lists.sourceforge.net

package pspdash.data.compiler;

import java.io.PushbackReader;
import java.io.StringReader;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import pspdash.ResourcePool;
import pspdash.data.DateData;
import pspdash.data.ImmutableDoubleData;
import pspdash.data.ImmutableStringData;
import pspdash.data.StringData;
import pspdash.data.TagData;

import pspdash.data.compiler.lexer.*;
import pspdash.data.compiler.parser.*;
import pspdash.data.compiler.node.*;
import pspdash.data.compiler.analysis.*;


public class Compiler extends DepthFirstAdapter {

    private CompiledScript script = null;

    private static final ResourcePool compilerPool =
        new ResourcePool("compilerPool") {
                protected Object createNewResource() {
                    return new Compiler(); } };

    public Compiler() {}

    void setScript(CompiledScript script) {
        this.script = script;
    }

    public static CompiledScript compile(PValue expression)
        throws CompilationException
    {
        Compiler compiler = null;
        CompiledScript result = null;
        try {
            // get a compiler from the pool.
            compiler = (Compiler) compilerPool.get();

            // compile the expression into a CompiledScript object.
            result = new CompiledScript();
            compiler.setScript(result);
            expression.apply(compiler);
            compiler.setScript(null);
            result.setSaveString(expression.toString());
            result.commit();
        } finally {
            // release the compiler.
            compilerPool.release(compiler);
        }
        return result;
    }

    private static Map scriptCache =
        Collections.synchronizedMap(new HashMap());

    public static CompiledScript compile(String expression)
        throws CompilationException
    {
        Object result = scriptCache.get(expression);
        if (result instanceof CompiledScript)
            return (CompiledScript) result;
        if (result instanceof CompilationException)
            throw (CompilationException) result;

        try {
            result = compile(compileVal(expression));
            scriptCache.put(expression, result);
            return (CompiledScript) result;
        } catch (CompilationException e) {
            scriptCache.put(expression, e);
            throw e;
        }
    }


    public static PValue compileVal(String expression)
        throws CompilationException
    {
        try {
            // Create a Parser instance.
            Parser p = new Parser(new Lexer(new PushbackReader
                (new StringReader("[foo] = " + expression + ";"), 1024)));

            // Parse the input
            Start tree = p.parse();

            // get the expression and return it
            FindLastExpression search = new FindLastExpression();
            tree.apply(search);
            return search.expression;

        } catch (Exception e) {
            throw new CompilationException("Error while compiling: " + e);
        }
    }


    public static CompiledScript exprAndDefined(CompiledScript s,
                                                String identifier) {
        CompiledScript result = new CompiledScript(s);
        result.add(FunctionCall.PUSH_STACK_MARKER);
        result.add(new PushVariable(identifier));
        result.add(FunctionCall.get("Defined"));
        result.add(LogicOperators.AND);
        result.commit();

        return result;
    }


    private void binaryExpression(Node left, Node op, Node right) {
        if (left  != null) left.apply(this);
        if (right != null) right.apply(this);
        if (op    != null) op.apply(this);
    }

    public void caseABinaryLevel7Expr(ABinaryLevel7Expr node)
    {
        inABinaryLevel7Expr(node);
        binaryExpression(node.getLeft(), node.getOp(), node.getRight());
        outABinaryLevel7Expr(node);
    }

    public void caseABinaryLevel6Expr(ABinaryLevel6Expr node)
    {
        inABinaryLevel6Expr(node);
        binaryExpression(node.getLeft(), node.getOp(), node.getRight());
        outABinaryLevel6Expr(node);
    }

    public void caseABinaryLevel5Expr(ABinaryLevel5Expr node)
    {
        inABinaryLevel5Expr(node);
        binaryExpression(node.getLeft(), node.getOp(), node.getRight());
        outABinaryLevel5Expr(node);
    }

    public void caseABinary1Level4Expr(ABinary1Level4Expr node)
    {
        inABinary1Level4Expr(node);
        binaryExpression(node.getLeft(), node.getOp(), node.getRight());
        outABinary1Level4Expr(node);
    }

    public void caseABinary2Level4Expr(ABinary2Level4Expr node)
    {
        inABinary2Level4Expr(node);
        binaryExpression(node.getLeft(), node.getOp(), node.getRight());
        outABinary2Level4Expr(node);
    }

    public void caseABinaryLevel3Expr(ABinaryLevel3Expr node)
    {
        inABinaryLevel3Expr(node);
        binaryExpression(node.getLeft(), node.getOp(), node.getRight());
        outABinaryLevel3Expr(node);
    }

    public void caseABinaryLevel2Expr(ABinaryLevel2Expr node)
    {
        inABinaryLevel2Expr(node);
        binaryExpression(node.getLeft(), node.getOp(), node.getRight());
        outABinaryLevel2Expr(node);
    }

    public void caseAUnaryNotLevel1Expr(AUnaryNotLevel1Expr node) {
        inAUnaryNotLevel1Expr(node);
        binaryExpression(null, node.getOp(), node.getRight());
        outAUnaryNotLevel1Expr(node);
    }

    private static final Instruction PUSH_ZERO =
        new PushConstant(ImmutableDoubleData.EDITABLE_ZERO);
    private static final Instruction PUSH_UNDEF_NUM =
        new PushConstant(ImmutableDoubleData.EDITABLE_UNDEF_NAN);

    public void caseAUnaryMinusLevel1Expr(AUnaryMinusLevel1Expr node) {
        inAUnaryMinusLevel1Expr(node);
        add(PUSH_ZERO);
        binaryExpression(null, node.getOp(), node.getRight());
        outAUnaryMinusLevel1Expr(node);
    }

    public void caseAScript1FunctionCall(AScript1FunctionCall node)
    {
        inAScript1FunctionCall(node);
        add(FunctionCall.PUSH_STACK_MARKER);
        if(node.getScript() != null)
            node.getScript().apply(this);
        if(node.getArglist() != null)
            node.getArglist().apply(this);
        if(node.getScript1FunctionName() != null)
            node.getScript1FunctionName().apply(this);
        outAScript1FunctionCall(node);
    }

    public void caseAFunctionCall(AFunctionCall node)
    {
        inAFunctionCall(node);
        add(FunctionCall.PUSH_STACK_MARKER);
        if(node.getArglist() != null)
            node.getArglist().apply(this);
        if(node.getFunctionName() != null)
            node.getFunctionName().apply(this);
        outAFunctionCall(node);
    }

    public void caseTMult(TMult node)   { add(MathOperators.MULTIPLY); }
    public void caseTDiv(TDiv node)     { add(MathOperators.DIVIDE);   }
    public void caseTPlus(TPlus node)   { add(MathOperators.ADD);      }
    public void caseTMinus(TMinus node) { add(MathOperators.SUBTRACT); }

    public void caseTConcat(TConcat node) { add(StringOperators.CONCAT); }
    public void caseTPathconcat(TPathconcat node) {
        add(StringOperators.PATHCONCAT); }

    public void caseTLogicAnd(TLogicAnd node) { add(LogicOperators.AND); }
    public void caseTLogicOr(TLogicOr node)   { add(LogicOperators.OR)}
    public void caseTLogicNot(TLogicNot node) { add(LogicOperators.NOT); }

    public void caseTEq(TEq node)     { add(RelationalOperators.EQ);   }
    public void caseTNeq(TNeq node)   { add(RelationalOperators.NEQ)}
    public void caseTLt(TLt node)     { add(RelationalOperators.LT);   }
    public void caseTLteq(TLteq node) { add(RelationalOperators.LTEQ); }
    public void caseTGt(TGt node)     { add(RelationalOperators.GT);   }
    public void caseTGteq(TGteq node) { add(RelationalOperators.GTEQ); }

    public void caseTFunctionName(TFunctionName node) {
        add(FunctionCall.get(node.getText())); }
    public void caseTScript1FunctionName(TScript1FunctionName node) {
        add(FunctionCall.get(node.getText())); }
    public void caseTIdentifier(TIdentifier node) {
        add(new PushVariable(trimDelim(node))); }
    public void caseTStringLiteral(TStringLiteral node) {
        add(new PushConstant(new ImmutableStringData(trimDelim(node)))); }
    public void caseTDateLiteral(TDateLiteral node) {
        try {
            add(new PushConstant(new DateData(node.getText())));
        } catch (Exception mve) {
            throw new CompilationException
                ("Couldn't parse date literal '" + node.getText() + "'.");
        }
    }
    public void caseAZeroTerm(AZeroTerm node) { add(PUSH_ZERO); }
    public void caseAUndefNumTerm(AUndefNumTerm node) { add(PUSH_UNDEF_NUM); }
    public void caseTNumberLiteral(TNumberLiteral node) {
        try {
            add(new PushConstant(new ImmutableDoubleData(node.getText())));
        } catch (Exception mve) {
            throw new CompilationException
                ("Couldn't parse number literal '" + node.getText() + "'.");
        }
    }
    public void caseTTag(TTag node) {
        add(new PushConstant(TagData.getInstance())); }
    public void caseTNull(TNull node) {
        add(new PushConstant(null)); }
    public void caseTTrue(TTrue node) {
        add(new PushConstant(ImmutableDoubleData.TRUE)); }
    public void caseTFalse(TFalse node) {
        add(new PushConstant(ImmutableDoubleData.FALSE)); }

    public void caseASimpleScript(ASimpleScript node) {
        add(new PushObject(compile(node.getValue())));
    }

    /** Convenience routine for adding an instruction to the script */
    private void add(Instruction i) { script.add(i); }

    /** Convenience routine: trims the first and last char from a string */
    public static String trimDelim(Token node) {
        return trimDelim(node.getText()); }
    public static String trimDelim(String text) {
        if (text == null) return null;
        int len = text.length();
        if (len < 2) return "";
        return StringData.unescapeString(text.substring(1, len-1)).intern();
    }

    public static String escapeLiteral(String literal) {
        return pspdash.EscapeString.escape(literal, '\\', "'\"[]");
    }
}

class FindLastExpression extends DepthFirstAdapter {
    PValue expression = null;
    public FindLastExpression() {}
    public void caseANewStyleDeclaration(ANewStyleDeclaration node) {
        expression = node.getValue();
    }
}
TOP

Related Classes of pspdash.data.compiler.FindLastExpression

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.