/*************************************************************************** * Copyright (C) by Fabrizio Montesi * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library 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. * * * * For details about the authors of this software, see the AUTHORS file. * ***************************************************************************/ package jolie.lang.parse.ast; import jolie.lang.parse.ast.expression.ConstantStringExpression; import jolie.lang.parse.ast.expression.ConstantIntegerExpression; import java.io.Serializable; import java.util.LinkedList; import java.util.List; import jolie.lang.Constants; import jolie.lang.parse.OLVisitor; import jolie.lang.parse.context.ParsingContext; import jolie.util.Pair; public class VariablePathNode extends OLSyntaxNode implements Serializable { public static enum Type { NORMAL, GLOBAL, CSET } private final List< Pair< OLSyntaxNode, OLSyntaxNode > > path; private final Type type; public VariablePathNode( ParsingContext context, Type type ) { super( context ); path = new LinkedList< Pair< OLSyntaxNode, OLSyntaxNode > >(); this.type = type; } public Type type() { return type; } public boolean isGlobal() { return type == Type.GLOBAL; } public boolean isCSet() { return type == Type.CSET; } public boolean isStatic() { for( Pair< OLSyntaxNode, OLSyntaxNode > node : path ) { if ( node.key() instanceof ConstantStringExpression == false ) { return false; } if ( node.value() != null && node.value() instanceof ConstantIntegerExpression == false ) { return false; } } return true; } public static void levelPaths( VariablePathNode leftPath, VariablePathNode rightPath ) { int leftIndex = leftPath.path().size() - 1; int rightIndex = rightPath.path().size() - 1; Pair< OLSyntaxNode, OLSyntaxNode > left = leftPath.path().get( leftIndex ); Pair< OLSyntaxNode, OLSyntaxNode > right = rightPath.path().get( rightIndex ); if ( left.value() == null && right.value() != null ) { left = new Pair< OLSyntaxNode, OLSyntaxNode >( left.key(), new ConstantIntegerExpression( leftPath.context(), 0 ) ); leftPath.path().set( leftIndex, left ); } else if ( left.value() != null && right.value() == null ) { right = new Pair< OLSyntaxNode, OLSyntaxNode >( right.key(), new ConstantIntegerExpression( rightPath.context(), 0 ) ); rightPath.path().set( rightIndex, right ); } } public void append( Pair< OLSyntaxNode, OLSyntaxNode > node ) { path.add( node ); } public List< Pair< OLSyntaxNode, OLSyntaxNode > > path() { return path; } public void accept( OLVisitor visitor ) { visitor.visit( this ); } public boolean isEquivalentTo( VariablePathNode right ) { return checkVariablePathNodeEquivalence( this, right ); } private static boolean checkVariablePathNodeEquivalence( VariablePathNode left, VariablePathNode right ) { if ( left.path.size() != right.path.size() ) { return false; } if ( left.type != right.type ) { return false; } Pair< OLSyntaxNode, OLSyntaxNode > leftPair, rightPair; for( int i = 0; i < left.path.size(); i++ ) { leftPair = left.path.get( i ); rightPair = right.path.get( i ); if ( checkNodeKeyEquivalence( leftPair.key(), rightPair.key() ) == false || checkNodeIndexEquivalence( leftPair.value(), rightPair.value() ) == false ) { return false; } } return true; } private static boolean checkNodeKeyEquivalence( OLSyntaxNode left, OLSyntaxNode right ) { if ( left.equals( right ) ) { return true; } if ( left instanceof ConstantStringExpression && right instanceof ConstantStringExpression ) { return ((ConstantStringExpression)left).value().equals( ((ConstantStringExpression)right).value() ); } return false; } private static boolean checkNodeIndexEquivalence( OLSyntaxNode left, OLSyntaxNode right ) { if ( left == right ) { // Used for null values and same objects return true; } if ( left == null && right instanceof ConstantIntegerExpression ) { return ((ConstantIntegerExpression)right).value() == 0; } if ( right == null && left instanceof ConstantIntegerExpression ) { return ((ConstantIntegerExpression)left).value() == 0; } if ( left != null && right != null ) { if ( left.equals( right ) ) { return true; } if ( left instanceof ConstantIntegerExpression && right instanceof ConstantIntegerExpression ) { return ((ConstantIntegerExpression)left).value() == ((ConstantIntegerExpression)right).value(); } } return false; } public String toPrettyString() { StringBuilder builder = new StringBuilder(); Pair< OLSyntaxNode, OLSyntaxNode > node; if ( isGlobal() ) { builder.append( Constants.GLOBAL ).append( '.' ); } for( int i = 0; i < path.size(); i++ ) { node = path.get( i ); if ( node.key() instanceof ConstantStringExpression ) { builder.append( ((ConstantStringExpression)node.key()).value() ); } else { builder.append( "<Expression>" ); } if ( node.value() != null ) { if ( node.value() instanceof ConstantIntegerExpression ) { ConstantIntegerExpression expr = (ConstantIntegerExpression) node.value(); if ( expr.value() != 0 ) { builder.append( '[' ) .append( node.value() ) .append( ']' ); } } else { builder.append( '[' ) .append( "<Expression>" ) .append( ']' ); } } if ( i < path.size() - 1 ) { builder.append( '.' ); } } return builder.toString(); } }