package org.sigmah.shared.computation; /* * #%L * Sigmah * %% * Copyright (C) 2010 - 2016 URD * %% * 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 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 General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #L% */ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Stack; import org.sigmah.shared.computation.dependency.Scope; import org.sigmah.shared.computation.instruction.Function; import org.sigmah.shared.computation.instruction.Instruction; import org.sigmah.shared.computation.instruction.Operator; import org.sigmah.shared.dto.element.FlexibleElementDTO; /** * Environment of the parser. * * @author Raphaël Calabro (raphael.calabro@netapsys.fr) * @since 2.1 */ class ParserEnvironment { /** * Current parser state. */ private ParserState state = ParserState.WAITING_FOR_OPERAND; /** * Parser context. */ private final Stack<Context> contexts = new Stack<Context>(); /** * Flexible elements of the parent model. */ private final Map<String, FlexibleElementDTO> elements; // TODO: À utiliser. private boolean hasUnresolvedDependencies; /** * Create a new environment and push an initial context. */ ParserEnvironment(final Map<String, FlexibleElementDTO> elements) { this.elements = elements; this.contexts.push(new Context()); } /** * Add an instruction to the instruction list of the current context. * * @param instruction Instruction to add. */ void add(final Instruction instruction) { contexts.peek().instructions.add(instruction); } /** * Retrieves the last instruction added. * * @return The last instruction. */ Instruction lastInstruction() { final List<Instruction> instructions = contexts.peek().instructions; if (instructions == null || instructions.isEmpty()) { return null; } else { return instructions.get(instructions.size() - 1); } } /** * Push the given operator to the operator stack of the current context. * * @param operator Operator to push. */ void pushOnStack(final Operator operator) { contexts.peek().operators.push(operator); } /** * Retrieve and remove from the stack the operator at the peek for the * current context. * * @return Operator at the peek of the stack. */ Operator popFromStack() { return contexts.peek().operators.pop(); } /** * Retrieve the operator at the peek of the stack of the current context. * * @return Operator at the peek of the stack. */ Operator peekOfStack() { if (!contexts.peek().operators.isEmpty()) { return contexts.peek().operators.peek(); } else { return null; } } /** * Empty the operator stack and adds everything to the instruction list. */ void popEverythingFromStackToInstructions() { while (!contexts.peek().operators.isEmpty()) { contexts.peek().instructions.add(contexts.peek().operators.pop()); } } /** * Push a new context. */ void pushContext() { contexts.push(new Context()); } /** * Pop the current context and merge its content with the previous one. */ void popContext() { popEverythingFromStackToInstructions(); final Context context = contexts.pop(); contexts.peek().instructions.addAll(context.instructions); } // GETTERS & SETTERS FlexibleElementDTO getElement(String key) { return elements.get(key); } ParserState getState() { return state; } void setState(final ParserState state) { this.state = state; } List<Instruction> getInstructions() { return contexts.peek().instructions; } Scope getCurrentScope() { return contexts.peek().scope; } void setCurrentScope(Scope scope) { contexts.peek().scope = scope; } Function popLastFunction() { final Context peek = contexts.peek(); final Function function = peek.function; peek.function = null; return function; } void setLastFunction(Function function) { contexts.peek().function = function; } // CONTEXT /** * Execution context. */ private class Context { /** * Instruction list. */ private final List<Instruction> instructions = new ArrayList<Instruction>(); /** * Operator stack. */ private final Stack<Operator> operators = new Stack<Operator>(); private Function function; /** * Current scope of the context. May be null. */ private Scope scope; } }