/*
* Copyright 2010 Pablo Arrighi, Alex Concha, Miguel Lezama for version 1.
* Copyright 2013 Pablo Arrighi, Miguel Lezama, Kevin Mazet for version 2.
*
* This file is part of GOOL.
*
* GOOL 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, version 3.
*
* GOOL 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 version 3 for more details.
*
* You should have received a copy of the GNU General Public License along with GOOL,
* in the file COPYING.txt. If not, see <http://www.gnu.org/licenses/>.
*/
package gool.recognizer.cpp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTArrayModifier;
import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTCastExpression;
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
import org.eclipse.cdt.core.dom.ast.IASTConditionalExpression;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTDefaultStatement;
import org.eclipse.cdt.core.dom.ast.IASTDoStatement;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTExpressionList;
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
import org.eclipse.cdt.core.dom.ast.IASTForStatement;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTIfStatement;
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.dom.ast.IASTReturnStatement;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTSwitchStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree.IASTInclusionNode;
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTWhileStatement;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IField;
import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IParameter;
import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTryBlockStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisibilityLabel;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import gool.ast.core.ArrayAccess;
import gool.ast.core.Assign;
import gool.ast.core.BinaryOperation;
import gool.ast.core.Block;
import gool.ast.core.CastExpression;
import gool.ast.core.Catch;
import gool.ast.core.ClassDef;
import gool.ast.core.ClassNew;
import gool.ast.core.Constant;
import gool.ast.core.CustomDependency;
import gool.ast.core.Dec;
import gool.ast.core.Expression;
import gool.ast.core.ExpressionUnknown;
import gool.ast.core.Field;
import gool.ast.core.FieldAccess;
import gool.ast.core.For;
import gool.ast.core.Identifier;
import gool.ast.core.If;
import gool.ast.core.Meth;
import gool.ast.core.MethCall;
import gool.ast.core.Modifier;
import gool.ast.core.Operator;
import gool.ast.core.Return;
import gool.ast.core.Statement;
import gool.ast.core.This;
import gool.ast.core.Throw;
import gool.ast.core.Try;
import gool.ast.core.UnImplemented;
import gool.ast.core.UnaryOperation;
import gool.ast.core.UnrecognizedDependency;
import gool.ast.core.VarDeclaration;
import gool.ast.core.While;
import gool.ast.system.SystemOutDependency;
import gool.ast.system.SystemOutPrintCall;
import gool.ast.type.IType;
import gool.ast.type.TypeBool;
import gool.ast.type.TypeClass;
import gool.ast.type.TypeInt;
import gool.ast.type.TypeNone;
import gool.ast.type.TypeString;
import gool.ast.type.TypeUnknown;
import gool.generator.common.Platform;
import gool.generator.cpp.CppPlatform;
import gool.recognizer.common.RecognizerMatcher;
import gool.recognizer.cpp.ast.declaration.ASTCppDeclaration;
import gool.recognizer.cpp.ast.declaration.ASTCppFunctionDefinition;
import gool.recognizer.cpp.ast.declaration.ASTCppSimpleDeclaration;
import gool.recognizer.cpp.ast.declaration.ASTCppVisibilityLabel;
import gool.recognizer.cpp.ast.declarator.ASTCppArrayDeclarator;
import gool.recognizer.cpp.ast.declarator.ASTCppDeclarator;
import gool.recognizer.cpp.ast.declarator.ASTCppFieldDeclarator;
import gool.recognizer.cpp.ast.declarator.ASTCppFunctionDeclarator;
import gool.recognizer.cpp.ast.declspecifier.ASTCppCompositeTypeSpecifier;
import gool.recognizer.cpp.ast.declspecifier.ASTCppDeclSpecifier;
import gool.recognizer.cpp.ast.declspecifier.ASTCppEnumerationSpecifier;
import gool.recognizer.cpp.ast.declspecifier.ASTCppNamedTypeSpecifier;
import gool.recognizer.cpp.ast.declspecifier.ASTCppSimpleDeclSpecifier;
import gool.recognizer.cpp.ast.expression.ASTCppArraySubscriptExpression;
import gool.recognizer.cpp.ast.expression.ASTCppBinaryExpression;
import gool.recognizer.cpp.ast.expression.ASTCppCastExpression;
import gool.recognizer.cpp.ast.expression.ASTCppConditionalExpression;
import gool.recognizer.cpp.ast.expression.ASTCppExpression;
import gool.recognizer.cpp.ast.expression.ASTCppExpressionList;
import gool.recognizer.cpp.ast.expression.ASTCppFieldReference;
import gool.recognizer.cpp.ast.expression.ASTCppFunctionCallExpression;
import gool.recognizer.cpp.ast.expression.ASTCppIdExpression;
import gool.recognizer.cpp.ast.expression.ASTCppLiteralExpression;
import gool.recognizer.cpp.ast.expression.ASTCppUnaryExpression;
import gool.recognizer.cpp.ast.initializer.ASTCppConstructorInitializer;
import gool.recognizer.cpp.ast.initializer.ASTCppInitializer;
import gool.recognizer.cpp.ast.initializer.ASTCppInitializerExpression;
import gool.recognizer.cpp.ast.name.ASTCppName;
import gool.recognizer.cpp.ast.other.ASTCppBaseSpecifier;
import gool.recognizer.cpp.ast.other.ASTCppEnumerator;
import gool.recognizer.cpp.ast.other.ASTCppIncludeStatement;
import gool.recognizer.cpp.ast.other.ASTCppParameterDeclaration;
import gool.recognizer.cpp.ast.other.ASTCppTranslationUnit;
import gool.recognizer.cpp.ast.statement.ASTCppCatchHandler;
import gool.recognizer.cpp.ast.statement.ASTCppCompoundStatement;
import gool.recognizer.cpp.ast.statement.ASTCppDeclarationStatement;
import gool.recognizer.cpp.ast.statement.ASTCppDefaultStatement;
import gool.recognizer.cpp.ast.statement.ASTCppDoStatement;
import gool.recognizer.cpp.ast.statement.ASTCppExpressionStatement;
import gool.recognizer.cpp.ast.statement.ASTCppForStatement;
import gool.recognizer.cpp.ast.statement.ASTCppIfStatement;
import gool.recognizer.cpp.ast.statement.ASTCppReturnStatement;
import gool.recognizer.cpp.ast.statement.ASTCppStatement;
import gool.recognizer.cpp.ast.statement.ASTCppSwitchStatement;
import gool.recognizer.cpp.ast.statement.ASTCppTryBlockStatement;
import gool.recognizer.cpp.ast.statement.ASTCppWhileStatement;
import gool.recognizer.cpp.visitor.IVisitorASTCpp;
/**
* This class is the recognizer for the language C++. It transforms
* a C++ AST into a GOOL AST.
*/
public class CppRecognizer implements IVisitorASTCpp {
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////// FIELDS ///////////////////////////////////
/**
* The helper used to help the recognizer.
*/
protected HelperCppRecognizer helper = new HelperCppRecognizer(this) ;
/**
* The default platform used to specify the Target Language, which will be
* annotated in the newly created classes.
*/
protected Platform defaultPlatform;
/**
* The list of abstract GOOL classes and packages that will be generated.
*/
protected Map<gool.ast.type.IType, ClassDef> goolClasses = new HashMap<gool.ast.type.IType, ClassDef>();
/**
* The stack of actives classes (used to know in which class insert a method or a field).
*/
protected Stack<ClassDef> stackClassActives = new Stack<ClassDef>();
/**
* The active method (used to know in which method insert a statement).
* If no method active is available, methActive is null.
*/
protected Meth methActive = null ;
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////// GET/SET ///////////////////////////////////
/**
* Gets the default platform used to specify the Target Language.
* @return
* The default platform.
*/
public final Platform getDefaultPlatform() {
return defaultPlatform ;
}
/**
* Sets the default platform used to specify the Target Language.
* @param defaultPlatform
* : The new value of the default platform.
*/
public final void setDefaultPlatform(Platform defaultPlatform) {
this.defaultPlatform = defaultPlatform;
}
/**
* Gets the list of abstract GOOL classes and packages that will be generated.
* @return
* The list of abstract GOOL classes and packages that will be generated.
*/
public final Collection<ClassDef> getGoolClasses() {
return goolClasses.values();
}
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
/////////////////////////// VISITORS OF AST VISITOR ///////////////////////////
@Override
public Object visit(ASTCppTranslationUnit node, Object data) {
IASTTranslationUnit tu = node.getNode() ;
// Create an new class with the name of the file.
String className = helper.createClassNameFromFilename(tu.getContainingFilename());
ClassDef unitaryClass = helper.getClassDef(className);
// The class is added to goolClasses when it doesn't exist yet.
if (unitaryClass == null){
unitaryClass = helper.createClassDef(className);
goolClasses.put(unitaryClass.getType(),unitaryClass);
}
// Add to stack active.
stackClassActives.push(unitaryClass);
// Initialized the recognizer matcher.
RecognizerMatcher.init("cpp");
// Visit the dependency.
IDependencyTree tree = tu.getDependencyTree();
for(IASTInclusionNode inc : tree.getInclusions()){
helper.visitIncludeStatment(inc.getIncludeDirective(), this, data);
}
// Visit the declarations.
helper.visitTranslationUnit(tu, this, new Context());
// Visit errors.
helper.visitErrors(tu.getChildren(), this, data);
// Drop from stack active.
stackClassActives.pop();
return null;
}
@Override
public Object visit(ASTCppIncludeStatement node, Object data) {
IASTPreprocessorIncludeStatement inc = node.getNode();
// Visit the named include.
String dependencyString = helper.visitName(inc.getName(), this, data);
// Check this library.
if (!RecognizerMatcher.matchImport(dependencyString)) {
stackClassActives.peek()
.addDependency(new UnrecognizedDependency(dependencyString));
}
/*else{
stackClassActives.peek()
.addDependency(new RecognizedDependency(dependencyString));
}*/
return null ;
}
@Override
public Object visit(ASTCppDeclaration node, Object data) {
IASTDeclaration dec = node.getNode();
// Add an error because unrecognized.
helper.addAnError(dec.getRawSignature(), "This declaration");
return null;
}
@Override
public Object visit(ASTCppSimpleDeclaration node, Object data) {
IASTSimpleDeclaration dec = node.getNode();
// Visit the declaration specifier.
helper.visitDeclSpecifier(dec.getDeclSpecifier(), this, data) ;
// Visit and adds to return the declarators.
List<Dec> decs = new ArrayList<Dec>();
for(IASTNode decDecl : dec.getDeclarators()){
decs.add(helper.visitDeclarator((IASTDeclarator) decDecl, this, data));
}
// Change the context
Context context = (Context) data ;
context.nameSpec = null ;
// Return declarations.
return decs;
}
@Override
public Object visit(ASTCppFunctionDefinition node, Object data) {
IASTFunctionDefinition dec = node.getNode() ;
// Gets the context.
Context context = ((Context)data) ;
// Visit the declaration specifier.
List<Modifier> listmodifiers = new ArrayList<Modifier>();
Object modifiers = helper.visitDeclSpecifier(dec.getDeclSpecifier(), this, data) ;
if(modifiers instanceof List<?>){
listmodifiers.addAll((Collection<? extends Modifier>) modifiers);
}
// We resolved the binding to know the real type.
IASTName functionDefintionName = dec.getDeclarator().getName();
IBinding functionDefintionBind = functionDefintionName.resolveBinding() ;
// Is a method definition.
if(functionDefintionBind instanceof ICPPMethod){
// Create and add the method.
ICPPMethod method = (ICPPMethod)functionDefintionBind ;
helper.createAndAddMethod(method, context.nameSpec);
}
// Is a function definition.
else if(functionDefintionBind instanceof IFunction)
{
// Create and add a static method associated.
IFunction function = (IFunction) functionDefintionBind;
helper.createAndAddMethod(function, context.nameSpec);
}
// Is not recognized (generate an error).
else
{
stackClassActives.peek().addDependency(new UnImplemented(dec.getRawSignature(),
"Undefined declaration"));
}
// Visit and add the statment to the method.
Statement stmt = helper.visitStatement(dec.getBody(), this, data);
if(methActive != null)
methActive.addStatement(stmt);
else
System.err.println("Error, it is impossible to associate the statement.");
// Visit the declarator (for example the parameters).
helper.visitDeclarator(dec.getDeclarator(), this, data);
// And of the function.
methActive = null ;
return null;
}
@Override
public Object visit(ASTCppVisibilityLabel node, Object data) {
ICPPASTVisibilityLabel decSpec = node.getNode() ;
// Update the visibility label.
((Context)data).visibility = helper.visibilityLabelToModifier(decSpec.getVisibility());
// Return the conversion of the visibility label.
return ((Context)data).visibility ;
}
@Override
public Object visit(ASTCppDeclSpecifier node, Object data) {
// Unused.
return null;
}
@Override
public Object visit(ASTCppCompositeTypeSpecifier node, Object data) {
IASTCompositeTypeSpecifier decSpec = node.getNode() ;
// Get the name of the composite type.
String className = helper.visitName(decSpec.getName(), this, data);
// Create class.
ClassDef unitaryClass = helper.getClassDef(className);
// The class is added to goolClasses.
unitaryClass = helper.createClassDef(className);
goolClasses.put(unitaryClass.getType(),unitaryClass);
// Add to stack active.
stackClassActives.push(unitaryClass);
// Visit ICPPASTBaseSpecifier, ie. inherits declaration.
helper.visitInherits(decSpec.getChildren(), this, data) ;
// Get the visibility label (by default PUBLIC).
Context context = (Context) data ;
context.visibility = helper.visitDeclarationVisibilityLabel(decSpec.getMembers(), this, data);
// Visit the declarations.
helper.visitDeclarations(decSpec.getMembers(), this, context);
// Drop from stack active.
stackClassActives.pop();
return null;
}
@Override
public Object visit(ASTCppSimpleDeclSpecifier node, Object data) {
IASTSimpleDeclSpecifier decSpec = node.getNode() ;
// Gets the list of modifier (isLong, isImaginary, isVolatile ...)
List<Modifier> toReturn = helper.getModifierDeclaration(decSpec);
// Return the list of modifier associated.
return toReturn;
}
@Override
public Object visit(ASTCppNamedTypeSpecifier node, Object data) {
IASTNamedTypeSpecifier decSpec = node.getNode() ;
// Get and add to the context, the name of the specifier.
Context context = (Context) data ;
context.nameSpec = helper.visitName(decSpec.getName(), this, data);
return null;
}
@Override
public Object visit(ASTCppEnumerationSpecifier node, Object data) {
IASTEnumerationSpecifier decSpec = node.getNode();
// Gets the name of the enumeration.
String name = helper.visitName(decSpec.getName(), this, data);
// Gets the list of enumerators associated.
List<Field> enumerators = helper.visitsEnumerators(
decSpec.getEnumerators(), this, data);
// Create and add the enumeration in the gool ast.
helper.createAndAddEnum(name, enumerators);
return null;
}
@Override
public Object visit(ASTCppEnumerator node, Object data) {
IASTEnumerationSpecifier.IASTEnumerator enumerator = node.getNode();
// Gets the name of the enumerator.
String name = helper.visitName(enumerator.getName(), this, data);
// Gets the initial value of the enumerator.
Expression exp = helper.visitExpression(enumerator.getValue(), this, data);
// Create the field with modifiers PUBLIC and STATIC.
Field toReturn = new Field(name, TypeInt.INSTANCE, exp) ;
toReturn.addModifier(Modifier.PUBLIC);
toReturn.addModifier(Modifier.STATIC);
// Return the enumerator, as a field.
return toReturn;
}
@Override
public Object visit(ASTCppBaseSpecifier node, Object data) {
ICPPASTBaseSpecifier baseSpecifier = node.getNode();
boolean correct = false ;
IASTName name = baseSpecifier.getName();
if (name.isReference()) {
// Resolved bindind.
// We recognized inheritance.
IBinding b = name.resolveBinding();
if (b instanceof ICPPClassType){
if(stackClassActives.peek().getParentClass() == null)
stackClassActives.peek().setParentClass(
new gool.ast.type.TypeClass(name.toString()));
else{
// Unrecognozed this part because no multiple inheritance in gool ast.
stackClassActives.peek().addDependency(
new UnImplemented(baseSpecifier.getRawSignature(),
"Multiple inheritance"));
}
correct = true ;
}
}
// Case error : unrecognized this part.
if(!correct && name.isReference()){
if(stackClassActives.peek().getParentClass() == null)
stackClassActives.peek().setParentClass(new gool.ast.type.TypeUnknown(name.toString()));
else
stackClassActives.peek().addDependency(
new UnImplemented(baseSpecifier.getRawSignature(), "Multiple inheritance (and Unknown type)"));
}
return null;
}
@Override
public Object visit(ASTCppDeclarator node, Object data) {
IASTDeclarator decl = node.getNode();
// Gets the context.
Context context = ((Context)data) ;
// Get the visibility label.
Modifier visibility = ((Context) data).visibility ;
// To know is its a construction.
String nameSpec = ((Context) data).nameSpec ;
// Get the name of the declarator.
String nameDec = helper.visitName(decl.getName(), this, data);
// Get the initializer expression.
Expression init = helper.visitInitializer(decl.getInitializer(), this, data) ;
// Case : it is a construction.
if(nameSpec != null){
if(init instanceof ClassNew){
((ClassNew)init).setType(new TypeClass(nameSpec));
}
}
// We resolved the binding to get the real type.
IBinding bind = decl.getName().resolveBinding();
// Is a parameter definition.
if(bind instanceof IParameter){
// Add the parameter to method of the class.
helper.createAndAddParameter((IParameter) bind, nameSpec);
}
// Is a field definition.
else if(bind instanceof IField){
// Add the field to the class.
helper.createAndAddField(bind.getOwner().toString(),
(IField)bind, visibility, nameDec, init, context.nameSpec);
}
// Is a variable definition.
else if(bind instanceof IVariable){
// Add the field to the class or return the variable declaration.
VarDeclaration var = helper.createAndAddVariable(
(bind.getOwner() != null)? bind.getOwner().toString() : null,
(IVariable)bind, visibility, nameDec,
init, context.nameSpec);
if(var != null)
return var ;
}
// Case unrecognized (generate an error).
else if(!(bind instanceof IFunction)){
// Add error.
helper.addAnError(bind.getOwner().toString(), decl.getRawSignature(),
"Undefined declarator");
}
return null;
}
@Override
public Object visit(ASTCppArrayDeclarator node, Object data) {
IASTArrayDeclarator decl = node.getNode();
// Get the visibility label.
Modifier visibility = ((Context) data).visibility ;
// Get the name of the declarator.
String nameDec = helper.visitName(decl.getName(), this, data);
// Get the initializer expression.
Expression init = helper.visitInitializer(decl.getInitializer(), this, data) ;
List<Expression> dims = new ArrayList<Expression>();
for(IASTArrayModifier modifier : decl.getArrayModifiers()){
dims.add(helper.visitExpression(modifier.getConstantExpression(), this, data));
}
// We resolved the binding to get the real type.
IBinding bind = decl.getName().resolveBinding();
// Is a parameter definition.
if(bind instanceof IParameter){
// Add the parameter to method of the class.
helper.createAndAddArrayParameter((IParameter) bind, dims);
}
// Is a field definition.
else if(bind instanceof IField){
// Add the field to the class.
helper.createAndAddArrayField(bind.getOwner().toString(), (IField)bind,
visibility, nameDec, init, dims);
}
// Is a variable definition.
else if(bind instanceof IVariable){
// Add the field to the class or return the variable declaration.
VarDeclaration var = helper.createAndAddArrayVariable(
bind.getOwner().toString(), (IVariable)bind, visibility, nameDec, init, dims);
if(var != null)
return var ;
}
// Case unrecognized (generate an error).
else if(!(bind instanceof IFunction)){
// Add error.
helper.addAnError(bind.getOwner().toString(), decl.getRawSignature(), "Undefined declarator");
}
// Generate error for pointer operators.
for(IASTPointerOperator po : decl.getPointerOperators())
methActive.getClassDef().addDependency(
new UnImplemented(po.getRawSignature(), "Pointer operator"));
return null;
}
@Override
public Object visit(ASTCppFieldDeclarator node, Object data) {
// Unused.
return null;
}
@Override
public Object visit(ASTCppFunctionDeclarator node, Object data) {
IASTFunctionDeclarator decl = node.getNode();
// Visit the parameters, if exist.
int params = helper.visitParameters(decl.getChildren(), this, data);
// Generate error for pointer operators.
for(IASTPointerOperator po : decl.getPointerOperators())
methActive.getClassDef().addDependency(
new UnImplemented(po.getRawSignature(), "Pointer operator"));
// Case constructor. TODO : refactoring.
if(params == 0 && ((Context)data).nameSpec != null){
String name = helper.visitName(decl.getName(), this, data);
VarDeclaration var = new VarDeclaration(
new TypeClass(((Context)data).nameSpec), name);
var.setInitialValue(new ClassNew(new TypeClass(((Context)data).nameSpec)));
return var ;
}
return null;
}
@Override
public Object visit(ASTCppName node, Object data) {
IASTName name = node.getNode();
// Return the name.
return name.toString();
}
@Override
public Object visit(ASTCppStatement node, Object data) {
IASTStatement stmt = node.getNode();
// Error statement (generate error).
return new ExpressionUnknown(TypeNone.INSTANCE, stmt.getRawSignature()) ;
}
@Override
public Object visit(ASTCppCompoundStatement node, Object data) {
IASTCompoundStatement stmts = node.getNode();
// Create a block and add statements.
Block toReturn = new Block();
for(IASTStatement stmt : stmts.getStatements()){
Statement stmtAdd = helper.visitStatement(stmt, this, data) ;
if(stmtAdd != null)
toReturn.addStatement(stmtAdd);
}
// Return the block of statements.
return toReturn;
}
@Override
public Object visit(ASTCppDeclarationStatement node, Object data) {
IASTDeclarationStatement stmt = node.getNode();
// Get the list of declarations.
List<Dec> decs = (List<Dec>) helper.visitDeclaration(stmt.getDeclaration(), this, data);
if(decs.size() > 1){
// Case : multiple declarations.
Block toReturn = new Block();
for(Dec decToAdd : decs)
toReturn.addStatement(decToAdd);
return toReturn ;
}
if(decs.size() == 1)
// Case : one declaration.
return decs.get(0);
// Case : no declaration.
return null ;
}
@Override
public Object visit(ASTCppDefaultStatement node, Object data) {
IASTDefaultStatement stmt = node.getNode();
// Unimplemented in GOOL (generate an error).
return new ExpressionUnknown(TypeNone.INSTANCE, stmt.getRawSignature());
}
@Override
public Object visit(ASTCppDoStatement node, Object data) {
IASTDoStatement stmt = node.getNode();
// Unimplemented in GOOL (generate an error).
return new ExpressionUnknown(TypeNone.INSTANCE, stmt.getRawSignature());
}
@Override
public Object visit(ASTCppExpressionStatement node, Object data) {
IASTExpressionStatement stmt = node.getNode();
// Visit the expression as a statement.
Statement exp = helper.visitExpressionStatement(stmt.getExpression(),this,data);
return exp ;
}
@Override
public Object visit(ASTCppForStatement node, Object data) {
IASTForStatement stmt = node.getNode();
// Get the initializer (for(initializer;;)).
Statement init = helper.visitStatement(stmt.getInitializerStatement(), this, data);
// Get the condition (for(;condition;)).
Expression cond = helper.visitExpression(stmt.getConditionExpression(), this, data);
// Get the iterator (for(;;iterator)).
Statement iter = helper.visitExpression(stmt.getIterationExpression(), this, data);
// Get the body (for(;;){body}).
Statement body = helper.visitStatement(stmt.getBody(), this, data);
// Rebuild if empty.
if(init == null) init = new Block();
if(cond == null) cond = new Constant(TypeBool.INSTANCE, "");
if(iter == null) iter= new Block();
if(body == null) body = new Block();
// Return a for statement.
return new For(init, cond, iter, body);
}
@Override
public Object visit(ASTCppIfStatement node, Object data) {
IASTIfStatement stmt = node.getNode();
// Get the condition (if(condition){}else{}).
Expression cond = helper.visitExpression(stmt.getConditionExpression(), this, data);
// Get the then clause (if(){then clause}else{}).
Statement thenC = helper.visitStatement(stmt.getThenClause(), this, data);
// Get the else clause (if(){}else{else clause}).
Statement elseC = helper.visitStatement(stmt.getElseClause(), this, data);
// Return a if statement.
return new If(cond, thenC, elseC);
}
@Override
public Object visit(ASTCppReturnStatement node, Object data) {
IASTReturnStatement stmt = node.getNode();
// Get the expression returned (return expression).
Expression ret = helper.visitExpression(stmt.getReturnValue(), this, data);
// Return a return statement.
return new Return(ret);
}
@Override
public Object visit(ASTCppWhileStatement node, Object data) {
IASTWhileStatement stmt = node.getNode();
// Get the condition (while(condition){}).
Expression cond = helper.visitExpression(stmt.getCondition(), this, data);
// Get the body (while(){body}).
Statement body = helper.visitStatement(stmt.getBody(), this, data);
// Return a while statement.
return new While(cond, body);
}
@Override
public Object visit(ASTCppSwitchStatement node, Object data) {
IASTSwitchStatement stmt = node.getNode();
// Unimplemented in GOOL (generate an error).
return new ExpressionUnknown(TypeNone.INSTANCE, stmt.getRawSignature());
}
@Override
public Object visit(ASTCppTryBlockStatement node, Object data) {
ICPPASTTryBlockStatement stmt = node.getNode();
// Visit the block try.
Statement tryStmt = helper.visitStatement(
stmt.getTryBody(), this, data);
// Visits the catches statements.
// Normaly it is catch statement.
List<Statement> stmts = helper.visitStatements(
stmt.getCatchHandlers(), this, data) ;
// Check if its catch statements.
List<Catch> catches = new ArrayList<Catch>();
for(Statement catchStmt : stmts){
if(catchStmt instanceof Catch)
catches.add((Catch) catchStmt);
else
System.out.println("Catches Error");
}
// Return the new try catch finally statement.
return new Try(catches, (Block) tryStmt, new Block());
}
@Override
public Object visit(ASTCppCatchHandler node, Object data) {
ICPPASTCatchHandler stmt = node.getNode();
// Gets the parameters of the cath.
List<VarDeclaration> parameters = (List<VarDeclaration>) helper.visitDeclaration(
stmt.getDeclaration(), this, data);
// Gets the body associated of the catch.
Statement catchStmt = helper.visitStatement(
stmt.getCatchBody(), this, data);
// Check the number of parameters.
if(parameters.size() == 0){
// 0 parameter, in the catch.
// Return UKNOWN Catch.
return new Catch(new VarDeclaration(
new TypeUnknown("UNKNOWN"), "UNKNOWN"), (Block) catchStmt);
}
else if(parameters.size() > 1){
// Error, just one parameter possible.
for(int i = 1 ; i < parameters.size() ; i++){
helper.addAnError(parameters.get(i).toString(),
"Multiple parameter in a catch");
}
}
// Return the catch statement.
return new Catch(parameters.get(0), (Block) catchStmt);
}
@Override
public Object visit(ASTCppExpression node, Object data) {
IASTExpression exp = node.getNode();
// Unimplemented in GOOL (generate an error).
return new ExpressionUnknown(TypeNone.INSTANCE, exp.getRawSignature());
}
@Override
public Object visit(ASTCppArraySubscriptExpression node, Object data) {
IASTArraySubscriptExpression exp = node.getNode();
// Gets the dims access.
List<Expression> expsArray = helper.visitExpressionsParameters(
exp.getChildren(), this, data);
// Gets the array expression.
Expression expArray = helper.visitExpression(exp.getArrayExpression(), this, data);
// Return a array access.
return new ArrayAccess(expArray, expsArray.get(1));
}
@Override
public Object visit(ASTCppBinaryExpression node, Object data) {
IASTBinaryExpression binExp = node.getNode();
// Case : is the assign operator.
if(helper.isAssignOperator(binExp.getOperator())){
// Gets the left expression.
Expression exp1 = helper.visitExpression(binExp.getOperand1(), this, data);
// Gets the right expression.
Expression exp2 = helper.visitExpression(binExp.getOperand2(), this, data);
// Return a assign.
return new Assign(exp1, exp2);
}
// Case : is a binary assign operator('+=','*=',...).
else if(helper.isBinaryAssignOperator(binExp.getOperator())){
// Gets the operator, and its symbol, of the expression.
Operator op = helper.convertBinaryOperator(binExp.getOperator());
String symbol = helper.getSymboleBinaryOperator(binExp.getOperator()) ;
// Gets the context.
Context context = ((Context)data) ;
// Gets the type of the expression.
IType type = helper.convertTypeGool(binExp.getExpressionType(), context.nameSpec);
// Gets the left expression.
Expression exp1 = helper.visitExpression(binExp.getOperand1(), this, data);
// Gets the right expression.
Expression exp2 = helper.visitExpression(binExp.getOperand2(), this, data);
// Return a assign.
return new Assign(exp1, new BinaryOperation(op, exp1, exp2, type, symbol));
}
// Case : is an other binary operator.
else{
// Gets the operator, and its symbol, of the expression.
Operator op = helper.convertBinaryOperator(binExp.getOperator());
String symbol = helper.getSymboleBinaryOperator(binExp.getOperator()) ;
// Gets the context.
Context context = ((Context)data) ;
// Gets the type of the expression.
IType type = helper.convertTypeGool(binExp.getExpressionType(), context.nameSpec);
// Gets the left expression.
Expression exp1 = helper.visitExpression(binExp.getOperand1(), this, data);
// Gets the right expression.
Expression exp2 = helper.visitExpression(binExp.getOperand2(), this, data);
// Treat the case is System.out call.
if(symbol.compareTo("<<") == 0){
// Convert std::endl
if(exp2.toString().compareTo("std::endl") == 0){
exp2 = new Constant(TypeString.INSTANCE, "\n") ;
}
// Case : add parameters.
if(exp1 instanceof SystemOutPrintCall){
SystemOutPrintCall sysPrint = ((SystemOutPrintCall)exp1);
sysPrint.getParameters().set(0,
new BinaryOperation(Operator.PLUS, sysPrint.getParameters().get(0),
exp2, TypeString.INSTANCE, "+"));
return sysPrint;
}
// Case : create SystemOutPrintCall.
else if(exp1.toString().compareTo("std::cout") == 0){
methActive.getClassDef().addDependency(new SystemOutDependency());
SystemOutPrintCall target = new SystemOutPrintCall();
target.addParameter(exp2) ;
return target ;
}
}
// Return a binary expression.
return new BinaryOperation(op, exp1, exp2, type, symbol);
}
}
@Override
public Object visit(ASTCppCastExpression node, Object data) {
IASTCastExpression expCast = node.getNode();
// Gets the context.
Context context = ((Context)data) ;
// Get the type of the cast.
IType targetType = helper.convertTypeGool(expCast.getExpressionType(), context.nameSpec);
// Get the casted expression.
Expression exp = helper.visitExpression(expCast.getOperand(), this, data);
// Return a cast expression.
return new CastExpression(targetType, exp);
}
@Override
public Object visit(ASTCppConditionalExpression node, Object data) {
IASTConditionalExpression exp = node.getNode();
// Unimplemented in GOOL (generate an error).
return new ExpressionUnknown(TypeNone.INSTANCE, exp.getRawSignature());
}
@Override
public Object visit(ASTCppExpressionList node, Object data) {
IASTExpressionList exp = node.getNode();
// Unimplemented in GOOL (generate an error).
return new ExpressionUnknown(TypeNone.INSTANCE, exp.getRawSignature());
}
@Override
public Object visit(ASTCppFieldReference node, Object data) {
IASTFieldReference exp = node.getNode();
// Gets the context.
Context context = ((Context)data) ;
// Gets the type of the expression.
gool.ast.type.IType type = helper.convertTypeGool(
exp.getExpressionType(), context.nameSpec);
// Gets the name of the field.
String member = helper.visitName(exp.getFieldName(), this, data);
// Gets the target.
Expression target = helper.visitExpression(exp.getFieldOwner(), this, data);
// Case recognized method.
String methodGool = RecognizerMatcher.matchMethod(
helper.transformMethodMathcherInvocation(
exp.getFieldOwner(), exp.getFieldName()));
if(methodGool != null){
context.methGool = methodGool ;
}
// Return a field access.
return new FieldAccess(type, target, member);
}
@Override
public Object visit(ASTCppFunctionCallExpression node, Object data) {
IASTFunctionCallExpression exp = node.getNode();
// Gets the context.
Context context = ((Context)data) ;
// Gets the type of the expression.
gool.ast.type.IType type = helper.convertTypeGool(
exp.getExpressionType(), context.nameSpec);
// The target object in the method invocation.
Expression target = null;
// The method invocation.
Meth meth = null;
// Visit expression.
Expression expAccess = helper.visitExpression(
exp.getFunctionNameExpression(), this, data);
// Case : method.
if(expAccess instanceof FieldAccess){
meth = new Meth(type,((FieldAccess)expAccess).getMember());
target = ((FieldAccess)expAccess).getTarget();
}
// Case : function.
else if(expAccess instanceof Identifier){
meth = new Meth(type,((Identifier)expAccess).getName());
target = helper.getIdentifierOfTransitionUnit(exp.getTranslationUnit());
}
// Error return the expression.
else
return expAccess ;
// Gets the parameters lists of the invocation.
List<Expression> params = helper.visitExpressionsParameters(
Arrays.copyOfRange(exp.getChildren(), 1, exp.getChildren().length), this, data) ;
// Create the method invocation.
MethCall toReturn = MethCall.create(type, target, meth, null);
toReturn.addParameters(params);
// Case : the method is in the gool library.
if(context.methGool != null){
toReturn.setGoolLibraryMethod(context.methGool);
context.methGool = null ;
}
// Return a method invocation.
return toReturn;
}
@Override
public Object visit(ASTCppIdExpression node, Object data) {
IASTIdExpression exp = node.getNode();
// Gets the context.
Context context = ((Context)data) ;
// Gets the type of the expression.
gool.ast.type.IType type = helper.convertTypeGool(
exp.getExpressionType(), context.nameSpec);
// Gets the name of the identifier.
String name = helper.visitName(exp.getName(), this, data);
// Treat the case : static field access (refactoring).
if(exp.getName().isReference()){
IBinding bind = exp.getName().resolveBinding() ;
if(bind instanceof IVariable){
IVariable var = (IVariable) bind ;
if(var.getOwner() == null){
// Return static field access of the transitionUnit class.
return new FieldAccess(type,
helper.getIdentifierOfTransitionUnit(exp.getTranslationUnit()),
name);
}
}
}
// Return a identifier.
return new Identifier(type, name);
}
@Override
public Object visit(ASTCppLiteralExpression node, Object data) {
IASTLiteralExpression exp = node.getNode();
// Gets the context.
Context context = ((Context)data) ;
// Case the expression is a this.
if(exp.getRawSignature().toString().compareTo("this") == 0){
// Return the this expression.
return new This(helper.convertTypeGool(
exp.getExpressionType(), context.nameSpec));
}
// Return a constant expression.
return new Constant( helper.convertTypeGool(
exp.getExpressionType(), context.nameSpec),
exp.getRawSignature().toString());
}
@Override
public Object visit(ASTCppUnaryExpression node, Object data) {
IASTUnaryExpression unExp = node.getNode();
// Gets the context.
Context context = ((Context)data) ;
// Gets the operator, and its symbol, of the expression.
Operator op = helper.convertUnaryOperator(unExp.getOperator());
String symbol = helper.getSymboleUnaryOperator(unExp.getOperator()) ;
// Gets the type of the expression.
IType type = helper.convertTypeGool(
unExp.getExpressionType(), context.nameSpec);
// Gets the expression.
Expression exp = helper.visitExpression(unExp.getOperand(), this, data);
// Case : it is a throw.
if(symbol.compareTo("throw") == 0){
// Return a throw expression.
return new Throw(exp);
}
// Return a unary expression.
return new UnaryOperation(op, exp, type, symbol);
}
@Override
public Object visit(ASTCppInitializer node, Object data) {
// TODO Auto-generated method stub
return null;
}
@Override
public Object visit(ASTCppInitializerExpression node, Object data) {
IASTEqualsInitializer init = node.getNode();
// Gets the initializer expression.
Expression exp = helper.visitExpression(
(IASTExpression) init.getChildren()[0], this, data);
// Return a expression for an initializer.
return exp;
}
@Override
public Object visit(ASTCppConstructorInitializer node, Object data) {
ICPPASTConstructorInitializer init = node.getNode();
if(getDefaultPlatform() == CppPlatform.getInstance())
stackClassActives.peek().addDependency(new CustomDependency("A"));
// Visit expressions if exists and return a classNew.
return helper.visitExpressions(init.getChildren(), this, data);
}
@Override
public Object visit(ASTCppParameterDeclaration node, Object data) {
IASTParameterDeclaration dec = node.getNode();
// Visit the declaration specifier of the parameter.
helper.visitDeclSpecifier(dec.getDeclSpecifier(), this, data);
// Visit the declarator of the parameter.
helper.visitDeclarator(dec.getDeclarator(), this, data);
return null;
}
private class Context {
Modifier visibility ;
String nameSpec ;
String methGool ;
}
}