package org.eclipse.dltk.tcl.internal.parser; import java.util.Arrays; import java.util.Iterator; import java.util.List; import org.eclipse.dltk.ast.ASTNode; import org.eclipse.dltk.ast.declarations.ModuleDeclaration; import org.eclipse.dltk.ast.expressions.Expression; import org.eclipse.dltk.ast.parser.AbstractSourceParser; import org.eclipse.dltk.ast.parser.ISourceParserExtension; import org.eclipse.dltk.ast.references.SimpleReference; import org.eclipse.dltk.compiler.env.IModuleSource; import org.eclipse.dltk.compiler.problem.IProblemReporter; import org.eclipse.dltk.core.DLTKCore; import org.eclipse.dltk.core.builder.ISourceLineTracker; import org.eclipse.dltk.tcl.ast.TclStatement; import org.eclipse.dltk.tcl.ast.expressions.TclExecuteExpression; import org.eclipse.dltk.tcl.core.ITclCommandDetector; import org.eclipse.dltk.tcl.core.ITclCommandDetector.CommandInfo; import org.eclipse.dltk.tcl.core.ITclCommandDetectorExtension; import org.eclipse.dltk.tcl.core.ITclCommandProcessor; import org.eclipse.dltk.tcl.core.ITclParser; import org.eclipse.dltk.tcl.core.ITclSourceParser; import org.eclipse.dltk.tcl.core.TclParseUtil; import org.eclipse.dltk.tcl.core.TclPlugin; import org.eclipse.dltk.tcl.core.ast.TclAdvancedExecuteExpression; import org.eclipse.dltk.tcl.internal.parser.ext.CommandManager; import org.eclipse.dltk.tcl.internal.parser.raw.SimpleTclParser; import org.eclipse.dltk.tcl.internal.parser.raw.TclCommand; import org.eclipse.dltk.tcl.internal.parser.raw.TclParseException; import org.eclipse.dltk.tcl.internal.parser.raw.TclScript; import org.eclipse.dltk.utils.TextUtils; /** * @deprecated */ @Deprecated public class TclSourceParser extends AbstractSourceParser implements ITclSourceParser, ITclParser, ISourceParserExtension { private IProblemReporter problemReporter; protected ISourceLineTracker codeModel; protected String content; private String fileName; private int startPos = 0; boolean useProcessors = true; private int flags; private boolean useDetectors = true; private ModuleDeclaration moduleDeclaration; @Override public ModuleDeclaration parse(IModuleSource input, IProblemReporter reporter) { initDetectors(); this.problemReporter = reporter; this.content = input.getSourceContents(); this.codeModel = TextUtils.createLineTracker(this.content); this.fileName = input.getFileName(); this.moduleDeclaration = new ModuleDeclaration(this.content.length()); this.parse(this.content, 0, moduleDeclaration); return moduleDeclaration; } private void initDetectors() { if (detectors == null) { detectors = CommandManager.getInstance().getDetectors(); } } private ITclCommandProcessor localProcessor = new ITclCommandProcessor() { @Override public ASTNode process(TclStatement st, ITclParser parser, ASTNode parent) { if (parent != null) { TclParseUtil.addToDeclaration(parent, st); // Replace execute expressions and parse they content. convertExecuteToBlocks(st); } return st; } @Override public void setCurrentASTTree(ModuleDeclaration module) { } @Override public void setDetectedParameter(Object parameter) { } }; private ITclCommandDetector[] detectors; private void convertExecuteToBlocks(TclStatement st) { ASTNode[] nodes = st.getExpressions() .toArray(new ASTNode[st.getCount()]); for (int i = 0; i < nodes.length; i++) { if (nodes[i] instanceof TclExecuteExpression) { TclExecuteExpression tclExecuteExpression = ((TclExecuteExpression) nodes[i]); String expression = tclExecuteExpression.getExpression(); if (expression.length() > 2) { expression = expression.substring(1, expression.length() - 1); TclAdvancedExecuteExpression newExpr = new TclAdvancedExecuteExpression( nodes[i].sourceStart(), nodes[i].sourceEnd()); nodes[i] = newExpr; st.setExpressions(Arrays.asList(nodes)); parse(expression, nodes[i].sourceStart() + 1 - getStartPos(), newExpr); } } } st.setExpressions(Arrays.asList(nodes)); } @Override public void parse(String content, int offset, ASTNode decl) { initDetectors(); TclScript script = null; try { script = SimpleTclParser.staticParse(content); } catch (TclParseException e) { if (DLTKCore.DEBUG_PARSER) { e.printStackTrace(); } return; } if (script == null) { return; } List commands = script.getCommands(); for (Iterator iter = commands.iterator(); iter.hasNext();) { TclCommand command = (TclCommand) iter.next(); // Command handling TclStatement st = TclParseUtil.convertToAST(command, this.getFileName(), offset, this.content, this.startPos); if (st == null) { continue; // could be null on errors in source code } ITclCommandProcessor processor = this.locateProcessor(st, content, offset, decl); if (processor != null) { try { ASTNode nde = processor.process(st, this, decl); if (nde == null) { nde = localProcessor.process(st, this, decl); } if (nde != null && this.useDetectors) { for (int i = 0; i < this.detectors.length; i++) { if (detectors[i] != null) { detectors[i].processASTNode(nde); } } } } catch (Exception e) { TclPlugin.error(e); } } } } private ITclCommandProcessor locateProcessor(TclStatement command, String content, int offset, ASTNode decl) { if (this.useProcessors == false) { return localProcessor; } if (command != null && command.getCount() > 0) { Expression expr = command.getAt(0); if (!(expr instanceof SimpleReference)) { return localProcessor; } String name = ((SimpleReference) expr).getName(); if (name.startsWith("::")) { name = name.substring(2); } ITclCommandProcessor processor = CommandManager.getInstance() .getProcessor(name); if (processor == null) { // advanced command detection. if (this.useDetectors) { for (int i = 0; i < detectors.length; i++) { if (detectors[i] == null) { continue; } if (detectors[i] instanceof ITclCommandDetectorExtension) { ((ITclCommandDetectorExtension) detectors[i]) .setBuildRuntimeModelFlag( isBuildingRuntimeModel()); } CommandInfo commandName = detectors[i].detectCommand( command, this.moduleDeclaration, decl); if (commandName != null) { processor = CommandManager.getInstance() .getProcessor(commandName.commandName); if (processor != null) { processor.setDetectedParameter( commandName.parameter); } break; } } } } if (processor != null) { processor.setCurrentASTTree(this.moduleDeclaration); return processor; } } return this.localProcessor; } @Override public ISourceLineTracker getCodeModel() { return this.codeModel; } public String getContent() { return this.content; } public String substring(int start, int end) { if (start > end) { return ""; } try { return this.content.substring(start - this.startPos, end - this.startPos); } catch (IndexOutOfBoundsException e) { if (DLTKCore.DEBUG) { e.printStackTrace(); } } return "####error####"; } @Override public IProblemReporter getProblemReporter() { return this.problemReporter; } @Override public String getFileName() { return this.fileName; } @Override public void setOffset(int offset) { this.startPos = offset; } @Override public int getStartPos() { return this.startPos; } @Override public void setProcessorsState(boolean state) { this.useProcessors = state; } @Override public void setFlags(int flags) { this.flags = flags; } private boolean isBuildingRuntimeModel() { return false; // (flags & ISourceParserConstants.RUNTIME_MODEL) != 0 } public void setUseDetectors(boolean b) { this.useDetectors = false; } public void setProblemReporter(IProblemReporter problemReporter2) { this.problemReporter = problemReporter2; } public void setModuleDeclaration(ModuleDeclaration moduleDeclaration) { this.moduleDeclaration = moduleDeclaration; } public void setContent(String content2) { this.content = content2; } }