| package org.eclipse.dltk.itcl.internal.core.parser.processors; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.dltk.ast.ASTNode; |
| import org.eclipse.dltk.ast.Modifiers; |
| import org.eclipse.dltk.ast.declarations.TypeDeclaration; |
| import org.eclipse.dltk.ast.expressions.Expression; |
| import org.eclipse.dltk.ast.references.SimpleReference; |
| import org.eclipse.dltk.compiler.problem.ProblemSeverities; |
| import org.eclipse.dltk.itcl.internal.core.IIncrTclModifiers; |
| import org.eclipse.dltk.itcl.internal.core.classes.IncrTclClassesManager; |
| import org.eclipse.dltk.itcl.internal.core.parser.ast.IncrTclFieldDeclaration; |
| import org.eclipse.dltk.itcl.internal.core.parser.ast.IncrTclMethodDeclaration; |
| import org.eclipse.dltk.tcl.ast.TclStatement; |
| import org.eclipse.dltk.tcl.ast.expressions.TclBlockExpression; |
| import org.eclipse.dltk.tcl.core.AbstractTclCommandProcessor; |
| import org.eclipse.dltk.tcl.core.ITclParser; |
| import org.eclipse.dltk.tcl.core.TclParseUtil; |
| import org.eclipse.dltk.tcl.core.ast.ExtendedTclMethodDeclaration; |
| |
| public class IncrTclClassCommandProcessor extends AbstractTclCommandProcessor { |
| @Override |
| public ASTNode process(TclStatement statement, ITclParser parser, ASTNode parent) { |
| if (statement == null || (statement != null && statement.getCount() == 0)) { |
| return null; |
| } |
| if (statement.getCount() != 3) { |
| // error not correct arguments |
| return null; |
| } |
| Expression classNameExpr = statement.getAt(1); |
| Expression blockExpr = statement.getAt(2); |
| if (classNameExpr instanceof SimpleReference && blockExpr instanceof TclBlockExpression) { |
| TclBlockExpression block = (TclBlockExpression) blockExpr; |
| TypeDeclaration type = new TypeDeclaration(((SimpleReference) classNameExpr).getName(), |
| classNameExpr.sourceStart(), classNameExpr.sourceEnd(), statement.sourceStart(), |
| statement.sourceEnd()); |
| type.setModifiers(IIncrTclModifiers.AccIncrTcl); |
| this.addToParent(parent, type); |
| // Report type to list of types. |
| IncrTclClassesManager.getDefault().add(type.getName()); |
| |
| List commands = block.parseBlockSimple(false); |
| for (int i = 0; i < commands.size(); i++) { |
| ASTNode nde = (ASTNode) commands.get(i); |
| if (nde instanceof TclStatement) { |
| TclStatement st = (TclStatement) nde; |
| Expression commandName = st.getAt(0); |
| if (commandName instanceof SimpleReference) { |
| String commandNameStr = ((SimpleReference) commandName).getName(); |
| if ("inherit".equals(commandNameStr)) { |
| handleInherit(st, type, parser); |
| } else if ("public".equals(commandNameStr)) { |
| handleWithModifierSub(st, type, Modifiers.AccPublic, parser); |
| } else if ("protected".equals(commandNameStr)) { |
| handleWithModifierSub(st, type, Modifiers.AccProtected, parser); |
| } else if ("private".equals(commandNameStr)) { |
| handleWithModifierSub(st, type, Modifiers.AccPrivate, parser); |
| } else { |
| handleWithModifier(commandNameStr, st, type, Modifiers.AccPrivate, parser); |
| } |
| } |
| } |
| } |
| return type; |
| } |
| return null; |
| } |
| |
| private void handleDestructor(TclStatement statement, TypeDeclaration type, ITclParser parser) { |
| if (statement.getCount() != 2) { |
| this.report(parser, "Wrong number of arguments", statement.sourceStart(), statement.sourceEnd(), |
| ProblemSeverities.Error); |
| addToParent(type, statement); |
| return; |
| } |
| Expression procCode = statement.getAt(1); |
| |
| ExtendedTclMethodDeclaration method = new ExtendedTclMethodDeclaration(statement.sourceStart(), |
| statement.sourceEnd()); |
| method.setName("destructor"); |
| Expression o = statement.getAt(0); |
| method.setNameStart(o.sourceStart()); |
| method.setNameEnd(o.sourceEnd()); |
| method.setModifier(IIncrTclModifiers.AccIncrTcl | IIncrTclModifiers.AccDestructor); |
| method.setDeclaringType(type); |
| IncrTclUtils.parseBlockAdd(parser, procCode, method); |
| type.getMethodList().add(method); |
| this.addToParent(type, method); |
| } |
| |
| private void handleWithModifierSub(TclStatement statement, TypeDeclaration type, int modifier, ITclParser parser) { |
| List expressions = statement.getExpressions(); |
| List newExpressions = new ArrayList(); |
| newExpressions.addAll(expressions); |
| if (newExpressions.size() > 0) { |
| newExpressions.remove(0); |
| } |
| TclStatement sub = new TclStatement(newExpressions); |
| Expression commandName = sub.getAt(0); |
| if (commandName instanceof SimpleReference) { |
| handleWithModifier(((SimpleReference) commandName).getName(), sub, type, modifier, parser); |
| } |
| } |
| |
| private void handleConstructor(TclStatement statement, TypeDeclaration type, ITclParser parser) { |
| if (statement.getCount() < 3) { |
| this.report(parser, "Wrong number of arguments", statement.sourceStart(), statement.sourceEnd(), |
| ProblemSeverities.Error); |
| addToParent(type, statement); |
| return; |
| } |
| Expression procArguments = statement.getAt(1); |
| Expression procCode = null; |
| // Expression procInit = null; |
| if (statement.getCount() == 3) { |
| procCode = statement.getAt(2); |
| } else if (statement.getCount() == 4) { |
| procCode = statement.getAt(3); |
| // procInit = statement.getAt(2); |
| } |
| |
| List arguments = IncrTclUtils.extractMethodArguments(procArguments); |
| |
| ExtendedTclMethodDeclaration method = new ExtendedTclMethodDeclaration(statement.sourceStart(), |
| statement.sourceEnd()); |
| method.setDeclaringType(type); |
| method.setName("constructor"); |
| Expression o = statement.getAt(0); |
| method.setNameStart(o.sourceStart()); |
| method.setNameEnd(o.sourceEnd()); |
| method.acceptArguments(arguments); |
| method.setModifier(IIncrTclModifiers.AccIncrTcl | IIncrTclModifiers.AccConstructor); |
| IncrTclUtils.parseBlockAdd(parser, procCode, method); |
| type.getMethodList().add(method); |
| this.addToParent(type, method); |
| } |
| |
| private void handleWithModifier(String commandNameStr, TclStatement statement, TypeDeclaration type, int modifier, |
| ITclParser parser) { |
| |
| if ("method".equals(commandNameStr)) { |
| handleMethod(statement, type, modifier, parser); |
| } else if ("proc".equals(commandNameStr)) { |
| handleMethod(statement, type, modifier | IIncrTclModifiers.AccIncrTclProc, parser); |
| } else if ("variable".equals(commandNameStr)) { |
| handleVariable(statement, type, modifier, parser); |
| } else if ("common".equals(commandNameStr)) { |
| handleCommon(statement, type, modifier, parser); |
| } else if ("set".equals(commandNameStr)) { |
| handleSet(statement, type, modifier, parser); |
| } else if ("array".equals(commandNameStr)) { |
| handleArray(statement, type, modifier); |
| } else if ("constructor".equals(commandNameStr)) { |
| handleConstructor(statement, type, parser); |
| } else if ("destructor".equals(commandNameStr)) { |
| handleDestructor(statement, type, parser); |
| } |
| } |
| |
| private void handleSet(TclStatement statement, TypeDeclaration type, int modifier, ITclParser parser) { |
| processVariable(statement, type, modifier, parser); |
| } |
| |
| private void processVariable(TclStatement statement, TypeDeclaration type, int modifier, ITclParser parser) { |
| if (statement.getCount() < 2) { |
| this.report(parser, "Syntax error: at least one argument expected.", statement, ProblemSeverities.Error); |
| return; |
| } |
| Expression variableName = statement.getAt(1); |
| Expression variableValue = null; |
| if (statement.getCount() == 3) |
| variableValue = statement.getAt(2); |
| if (variableName == null) { |
| throw new RuntimeException("empty variable name"); |
| } |
| SimpleReference variable = TclParseUtil.makeVariable(variableName); |
| if (variable != null) { |
| IncrTclFieldDeclaration var = new IncrTclFieldDeclaration(variable.getName(), variable.sourceStart(), |
| variable.sourceEnd(), statement.sourceStart(), statement.sourceEnd()); |
| var.setModifier(IIncrTclModifiers.AccIncrTcl | modifier); |
| var.setDeclaringType(type); |
| this.addToParent(type, var); |
| type.getFieldList().add(var); |
| } |
| } |
| |
| private void handleArray(TclStatement statement, TypeDeclaration type, int modifier) { |
| // processVariable(statement, type, modifier, parser); |
| } |
| |
| private void handleCommon(TclStatement statement, TypeDeclaration type, int modifier, ITclParser parser) { |
| if (statement.getCount() < 2) { |
| this.report(parser, "Syntax error: one argument expected.", statement, ProblemSeverities.Error); |
| return; |
| } |
| Expression variableName = statement.getAt(1); |
| if (variableName == null) { |
| throw new RuntimeException("empty variable name"); |
| } |
| SimpleReference variable = TclParseUtil.makeVariable(variableName); |
| if (variable != null) { |
| IncrTclFieldDeclaration var = new IncrTclFieldDeclaration(variable.getName(), variable.sourceStart(), |
| variable.sourceEnd(), statement.sourceStart(), statement.sourceEnd()); |
| var.setModifier(IIncrTclModifiers.AccIncrTcl | modifier); |
| var.setDeclaringType(type); |
| this.addToParent(type, var); |
| } |
| } |
| |
| private void handleVariable(TclStatement statement, TypeDeclaration type, int modifier, ITclParser parser) { |
| processVariable(statement, type, modifier, parser); |
| } |
| |
| private void handleMethod(TclStatement statement, TypeDeclaration type, int modifier, ITclParser parser) { |
| if (statement.getCount() < 2) { |
| this.report(parser, "Wrong number of arguments", statement.sourceStart(), statement.sourceEnd(), |
| ProblemSeverities.Error); |
| addToParent(type, statement); |
| return; |
| } |
| Expression procName = statement.getAt(1); |
| |
| String sName = IncrTclUtils.extractMethodName(procName); |
| if (sName == null || sName.length() == 0) { |
| this.report(parser, "Wrong number of arguments", statement.sourceStart(), statement.sourceEnd(), |
| ProblemSeverities.Error); |
| addToParent(type, statement); |
| return; |
| } |
| Expression procArguments = null;// statement.getAt(2); |
| Expression procCode = null;// statement.getAt(3); |
| if (statement.getCount() >= 3) { |
| procArguments = statement.getAt(2); |
| } |
| if (statement.getCount() == 4) { |
| procCode = statement.getAt(3); |
| } |
| |
| List arguments = IncrTclUtils.extractMethodArguments(procArguments); |
| |
| IncrTclMethodDeclaration method = new IncrTclMethodDeclaration(statement.sourceStart(), statement.sourceEnd()); |
| method.setName(sName); |
| method.setNameStart(procName.sourceStart()); |
| method.setNameEnd(procName.sourceEnd()); |
| method.acceptArguments(arguments); |
| method.setModifier(IIncrTclModifiers.AccIncrTcl | modifier); |
| method.setDeclaringType(type); |
| if ((modifier & IIncrTclModifiers.AccIncrTclProc) != 0) { |
| method.setKind(ExtendedTclMethodDeclaration.KIND_PROC); |
| } else { |
| method.setKind(ExtendedTclMethodDeclaration.KIND_INSTPROC); |
| } |
| IncrTclUtils.parseBlockAdd(parser, procCode, method); |
| type.getMethodList().add(method); |
| |
| this.addToParent(type, method); |
| } |
| |
| private void handleInherit(TclStatement statement, TypeDeclaration type, ITclParser parser) { |
| for (int i = 1; i < statement.getCount(); i++) { |
| Expression expr = statement.getAt(i); |
| if (expr instanceof SimpleReference) { |
| type.addSuperClass(expr); |
| } |
| } |
| } |
| } |