/* * Copyright (c) 2009, IETR/INSA of Rennes * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the IETR/INSA of Rennes nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ package net.sf.orcc.df.util; import java.util.List; import net.sf.orcc.ir.Expression; import net.sf.orcc.ir.IrFactory; import net.sf.orcc.ir.OpBinary; /** * This class defines a parser of binary operation sequences. This parser * translates expressions such as "e(1) op(1) e(2) ... op(n-1) e(n)" to a binary * expression tree with respect to operator precedence. * * <p> * This code is based on code written by Sam Harwell found on the site of ANTLR. * </p> * * @author Matthieu Wipliez * */ public class BinOpSeqParser { /** * Creates the precedence tree from the given list of expressions, * operators, and the start and stop indexes. * * @param expressions * a list of expressions * @param operators * a list of binary operators * @param startIndex * start index * @param stopIndex * stop index * @return an expression */ private static Expression createPrecedenceTree( List<Expression> expressions, List<OpBinary> operators, int startIndex, int stopIndex) { if (stopIndex == startIndex) { return expressions.get(startIndex); } int pivot = findPivot(operators, startIndex, stopIndex - 1); OpBinary op = operators.get(pivot); Expression e1 = createPrecedenceTree(expressions, operators, startIndex, pivot); Expression e2 = createPrecedenceTree(expressions, operators, pivot + 1, stopIndex); return IrFactory.eINSTANCE.createExprBinary(e1, op, e2, IrFactory.eINSTANCE.createTypeVoid()); } /** * Returns the index of the pivot, which is the operator that has the * highest precedence between start index and stop index. The pivot is * therefore the operator that binds the least with its operands. * * @param operators * a list of operators * @param startIndex * start index * @param stopIndex * stop index * @return the index of the pivot operator */ private static int findPivot(List<OpBinary> operators, int startIndex, int stopIndex) { int pivot = startIndex; OpBinary bop = operators.get(pivot); int pivotRank = bop.getPrecedence(); for (int i = startIndex + 1; i <= stopIndex; i++) { bop = operators.get(i); int current = bop.getPrecedence(); boolean rtl = bop.isRightAssociative(); if (pivotRank < current || (current == pivotRank && rtl)) { pivot = i; pivotRank = current; } } return pivot; } /** * Parses a sequence of expressions and binary operators to a binary * expression tree. * * @param expressions * a list of expressions * @param operators * a list of binary operators * @return a binary expression tree */ public static Expression parse(List<Expression> expressions, List<OpBinary> operators) { return createPrecedenceTree(expressions, operators, 0, expressions.size() - 1); } }