| /******************************************************************************* |
| * Copyright (c) 2009 xored software, Inc. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * xored software, Inc. - initial API and Implementation (Alex Panchenko) |
| *******************************************************************************/ |
| package org.eclipse.dltk.tcl.internal.structure; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.IdentityHashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Stack; |
| |
| import org.eclipse.dltk.compiler.ISourceElementRequestor; |
| import org.eclipse.dltk.tcl.ast.AstFactory; |
| import org.eclipse.dltk.tcl.ast.Script; |
| import org.eclipse.dltk.tcl.ast.TclArgument; |
| import org.eclipse.dltk.tcl.ast.TclCommand; |
| import org.eclipse.dltk.tcl.parser.ITclErrorReporter; |
| import org.eclipse.dltk.tcl.parser.TclParser; |
| import org.eclipse.dltk.tcl.parser.definitions.DefinitionManager; |
| import org.eclipse.dltk.tcl.parser.definitions.NamespaceScopeProcessor; |
| import org.eclipse.dltk.tcl.structure.ITclModelBuildContext; |
| import org.eclipse.dltk.tcl.structure.ITclTypeHandler; |
| import org.eclipse.dltk.tcl.structure.ITclTypeResolver; |
| import org.eclipse.dltk.tcl.structure.TclProcessorUtil; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| |
| public class TclModelBuildContext implements ITclModelBuildContext { |
| |
| private static class TopLevelNamespace implements ITclTypeHandler { |
| |
| public String getNamespace() { |
| return "::"; |
| } |
| |
| public void leave(ISourceElementRequestor requestor) { |
| // empty |
| } |
| |
| } |
| |
| private final TclSourceElementParser2 fParser; |
| private final ISourceElementRequestor fRequestor; |
| private final ITclErrorReporter errorReporter; |
| |
| public TclModelBuildContext(TclSourceElementParser2 parser, |
| ISourceElementRequestor requestor, ITclErrorReporter errorReporter) { |
| this.fParser = parser; |
| this.fRequestor = requestor; |
| this.errorReporter = errorReporter; |
| this.exitStack.push(new TopLevelNamespace()); |
| } |
| |
| public ISourceElementRequestor getRequestor() { |
| return fRequestor; |
| } |
| |
| public ITclErrorReporter getErrorReporter() { |
| return errorReporter; |
| } |
| |
| private Stack<ITclTypeHandler> exitStack = new Stack<ITclTypeHandler>(); |
| |
| public String getEnclosingNamespace() { |
| for (int head = exitStack.size(); --head >= 0;) { |
| ITclTypeHandler handler = exitStack.get(head); |
| final String namespace = handler.getNamespace(); |
| if (namespace != null) { |
| return namespace; |
| } |
| } |
| return null; |
| } |
| |
| private Map<TclCommand, List<ITclModelHandler>> handlers = new IdentityHashMap<TclCommand, List<ITclModelHandler>>(); |
| |
| public void addHandler(TclCommand command, ITclModelHandler handler) { |
| List<ITclModelHandler> commandHandlers = handlers.get(command); |
| if (commandHandlers == null) { |
| commandHandlers = new ArrayList<ITclModelHandler>(4); |
| handlers.put(command, commandHandlers); |
| } |
| commandHandlers.add(handler); |
| if (handler instanceof ITclTypeHandler) { |
| exitStack.push((ITclTypeHandler) handler); |
| } |
| } |
| |
| public void leave(TclCommand command) { |
| final List<ITclModelHandler> commandHandlers = handlers.remove(command); |
| if (commandHandlers != null) { |
| for (ITclModelHandler handler : commandHandlers) { |
| handler.leave(fRequestor); |
| if (handler instanceof ITclTypeHandler) { |
| exitStack.remove(handler); |
| } |
| } |
| } |
| } |
| |
| public void enterNamespace(ITclTypeHandler typeHandler) { |
| exitStack.push(typeHandler); |
| } |
| |
| public void leaveNamespace(ITclTypeHandler namespace) { |
| if (exitStack.remove(namespace)) { |
| namespace.leave(fRequestor); |
| } |
| } |
| |
| private TclTypeResolver typeResolver = null; |
| |
| @SuppressWarnings("unchecked") |
| public <E> E get(Class<E> clazz) { |
| if (clazz == ITclTypeResolver.class) { |
| if (typeResolver == null) { |
| typeResolver = new TclTypeResolver(fRequestor, this); |
| } |
| return (E) typeResolver; |
| } else { |
| return null; |
| } |
| } |
| |
| public List<TclCommand> parse(String source, int offset) { |
| return parse(source, offset, 0); |
| } |
| |
| public List<TclCommand> parse(String source, int offset, int options) { |
| final TclParser newParser = new TclParser(); |
| newParser.setGlobalOffset(offset); |
| final NamespaceScopeProcessor coreProcessor = DefinitionManager |
| .getInstance().createProcessor(); |
| List<TclCommand> commands = newParser.parse(source, errorReporter, |
| coreProcessor); |
| if ((options & NO_TRAVERSE) == 0) { |
| fParser.traverse(commands, this); |
| } |
| return commands; |
| } |
| |
| public Script parse(TclArgument arg) { |
| return parse(arg, 0); |
| } |
| |
| public Script parse(TclArgument arg, int options) { |
| if (arg instanceof Script) { |
| final Script script = (Script) arg; |
| if ((options & NO_TRAVERSE) == 0) { |
| fParser.traverse(script.getCommands(), this); |
| } |
| return script; |
| } else { |
| final Script script = AstFactory.eINSTANCE.createScript(); |
| script.setStart(arg.getStart()); |
| script.setEnd(arg.getEnd()); |
| final ITclParserInput input = TclProcessorUtil.asInput(arg); |
| if (input != null) { |
| script.setContentStart(input.getStart()); |
| script.setContentEnd(input.getEnd()); |
| script.getCommands().addAll( |
| parse(input.getContent(), input.getStart(), options)); |
| } else { |
| script.setContentStart(arg.getStart()); |
| script.setContentEnd(arg.getEnd()); |
| } |
| EcoreUtil.replace(arg, script); |
| return script; |
| } |
| } |
| |
| private final Map<String, Object> attributes = new HashMap<String, Object>(); |
| |
| public Object getAttribute(String name) { |
| return attributes.get(name); |
| } |
| |
| public void setAttribute(String name, Object value) { |
| attributes.put(name, value); |
| } |
| |
| } |