package org.eclipse.dltk.tcl.internal.core.parser.processors.tcl; import java.util.List; import org.eclipse.dltk.ast.ASTListNode; import org.eclipse.dltk.ast.ASTNode; import org.eclipse.dltk.ast.references.SimpleReference; import org.eclipse.dltk.ast.statements.Block; import org.eclipse.dltk.ast.statements.Statement; import org.eclipse.dltk.compiler.problem.ProblemSeverities; import org.eclipse.dltk.tcl.ast.TclStatement; import org.eclipse.dltk.tcl.ast.expressions.TclBlockExpression; import org.eclipse.dltk.tcl.ast.expressions.TclExecuteExpression; import org.eclipse.dltk.tcl.core.AbstractTclCommandProcessor; import org.eclipse.dltk.tcl.core.ITclParser; import org.eclipse.dltk.tcl.core.ast.IfStatement; import org.eclipse.dltk.tcl.core.ast.TclAdvancedExecuteExpression; public class TclIfProcessor extends AbstractTclCommandProcessor { private static final String THEN = "then"; //$NON-NLS-1$ private static final String ELSE = "else"; //$NON-NLS-1$ private static final String ELSEIF = "elseif"; //$NON-NLS-1$ private static class IfStatementError extends Exception { final int start; final int end; /** * @param message * @param node */ public IfStatementError(String message, ASTNode node) { this(message, node.sourceStart(), node.sourceEnd()); } /** * @param message * @param start * @param end */ public IfStatementError(String message, int start, int end) { super(message); this.start = start; this.end = end; } } private static class IfContext { final ITclParser parser; final TclStatement statement; final List exprs; int index; public IfContext(ITclParser parser, TclStatement statement) { this.parser = parser; this.statement = statement; this.exprs = statement.getExpressions(); index = 1; } public int start() { return statement.sourceStart(); } public int end() { return statement.sourceEnd(); } public int size() { return exprs.size(); } public ASTNode get(int i) { return (ASTNode) exprs.get(i); } public ASTNode get() { return get(index++); } boolean isEOF() { return index >= exprs.size(); } } public TclIfProcessor() { } public ASTNode process(TclStatement statement, ITclParser parser, ASTNode parent) { final IfContext context = new IfContext(parser, statement); IfStatement ifStatement = new IfStatement(context.start(), context .end()); addToParent(parent, ifStatement); try { parseIf(context, ifStatement); if (!context.isEOF()) { final ASTNode extraBegin = context.get(context.index); final ASTNode extraEnd = context.get(context.size() - 1); report(parser, Messages.TclIfProcessor_unexpectedStatements, extraBegin.sourceStart(), extraEnd.sourceEnd(), ProblemSeverities.Error); } } catch (IfStatementError e) { // if (DLTKCore.DEBUG) { // e.printStackTrace(); // } report(parser, e.getMessage(), e.start, e.end, ProblemSeverities.Error); } return ifStatement; } private void parseIf(IfContext context, IfStatement ifStatement) throws IfStatementError { ifStatement.acceptCondition(parseCondition(context)); if (context.isEOF()) { throw new IfStatementError( Messages.TclIfProcessor_missingThenBlock, context.start(), context.end()); } if (checkKeyword(context, THEN)) { if (context.isEOF()) { throw new IfStatementError( Messages.TclIfProcessor_missingThenBlock, context .start(), context.end()); } } ifStatement.acceptThen(parseBranch(context, true, Messages.TclIfProcessor_incorrectThenBlock)); if (!context.isEOF()) { if (checkKeyword(context, ELSEIF)) { final ASTNode elseIfKeyword = context.get(context.index - 1); final IfStatement nestedIf = new IfStatement(elseIfKeyword .sourceStart(), context.end()); parseIf(context, nestedIf); ifStatement.acceptElse(nestedIf); } else { if (checkKeyword(context, ELSE)) { if (context.isEOF()) { throw new IfStatementError( Messages.TclIfProcessor_incorrectElse, context .start(), context.end()); } } ifStatement.acceptElse(parseBranch(context, false, Messages.TclIfProcessor_incorrectElseBlock)); } } } private Statement parseBranch(IfContext context, boolean wrapAsBlock, String message) throws IfStatementError { final ASTNode node = context.get(); if (node instanceof TclBlockExpression) { final Block block = new Block(node.sourceStart(), node.sourceEnd()); parseBlock(context.parser, block, (TclBlockExpression) node); return block; } else if (node instanceof SimpleReference) { final Block block = new Block(node.sourceStart(), node.sourceEnd()); block.addStatement(node); return block; } else if (node instanceof TclStatement) { if (wrapAsBlock) { final Block block = new Block(node.sourceStart(), node .sourceEnd()); block.addStatement(node); return block; } else { return (TclStatement) node; } } else if (node instanceof TclExecuteExpression) { if (wrapAsBlock) { final Block block = new Block(node.sourceStart(), node .sourceEnd()); block.addStatement(node); return block; } else { return (TclExecuteExpression) node; } } else if (node instanceof Block) { return (Block) node; } else { throw new IfStatementError(message, context.start(), context.end()); } } /** * @param exprs * @param index * @param keyword * @return */ private boolean checkKeyword(IfContext context, String keyword) { final ASTNode node = context.get(context.index); if (node instanceof SimpleReference) { final SimpleReference ref = (SimpleReference) node; if (keyword.equals(ref.getName())) { ++context.index; return true; } } return false; } private void parseBlock(ITclParser parser, Block el, TclBlockExpression block) { String blockContent = block.getBlock(); blockContent = blockContent.substring(1, blockContent.length() - 1); parser.parse(blockContent, block.sourceStart() + 1- parser.getStartPos(), el); } private ASTNode parseCondition(IfContext context) throws IfStatementError { if (context.isEOF()) { throw new IfStatementError( Messages.TclIfProcessor_missingCondition, context.start(), context.end()); } ASTNode node = context.get(); if (node instanceof TclBlockExpression) { TclBlockExpression bl = (TclBlockExpression) node; List parseBlock = bl.parseBlockSimple(false); ASTListNode list = new ASTListNode(bl.sourceStart() + 1, bl .sourceEnd() - 1); for (int j = 0; j < parseBlock.size(); j++) { Object st = parseBlock.get(j); if (st instanceof TclStatement) { List expressions = ((TclStatement) st).getExpressions(); for (int k = 0; k < expressions.size(); k++) { ASTNode expr = (ASTNode) expressions.get(k); list.addNode(expr); } } } return list; } else if (node instanceof SimpleReference) { return node; } else if (node instanceof TclAdvancedExecuteExpression) { TclAdvancedExecuteExpression ex = (TclAdvancedExecuteExpression) node; List childs = ex.getChilds(); return new ASTListNode(node.sourceStart(), node.sourceEnd(), childs); } else if (node instanceof TclExecuteExpression) { return node; } else if (node instanceof Block) { return node; } throw new IfStatementError(Messages.TclIfProcessor_incorrectCondition, node); } }