001 package org.meta_environment.eclipse.parser;
002
003 import java.util.Iterator;
004
005 import org.eclipse.core.resources.IFile;
006 import org.eclipse.core.runtime.IPath;
007 import org.eclipse.core.runtime.IProgressMonitor;
008 import org.eclipse.imp.language.ILanguageService;
009 import org.eclipse.imp.language.Language;
010 import org.eclipse.imp.language.LanguageRegistry;
011 import org.eclipse.imp.model.ISourceProject;
012 import org.eclipse.imp.parser.ILexer;
013 import org.eclipse.imp.parser.IMessageHandler;
014 import org.eclipse.imp.parser.IParseController;
015 import org.eclipse.imp.parser.IParser;
016 import org.eclipse.imp.parser.ISourcePositionLocator;
017 import org.eclipse.imp.services.IAnnotationTypeInfo;
018 import org.eclipse.imp.services.ILanguageSyntaxProperties;
019 import org.eclipse.jface.text.IRegion;
020 import org.meta_environment.eclipse.Activator;
021 import org.meta_environment.eclipse.tokens.TokenIterator;
022 import org.meta_environment.eclipse.tokens.TokenLocator;
023
024 import toolbus.adapter.eclipse.EclipseTool;
025 import aterm.ATerm;
026 import aterm.ATermAppl;
027 import aterm.ATermList;
028 import errorapi.Factory;
029 import errorapi.types.Area;
030 import errorapi.types.Error;
031 import errorapi.types.ErrorList;
032 import errorapi.types.Subject;
033
034 public class ParseController extends EclipseTool implements IParseController,
035 ILanguageService {
036
037 private IPath filePath;
038
039 private String absPath;
040
041 private ISourceProject project;
042
043 private IMessageHandler handler;
044
045 private ErrorList errors;
046
047 public ATerm result;
048
049 Factory eFactory;
050
051 public ParseController() {
052 super("parse-controller");
053 eFactory = Factory.getInstance(factory);
054
055 // Hack to make sure the other tools are loaded
056 // one parse request can trigger a snd-eval to another
057 // tool (like the build tool) which has not connected
058 // yet. The eclipse initialization routine is single-threaded,
059 // such that this results in a deadlock. Another cause is
060 // that the editors which are part of the workbench are
061 // initialized before the earlyStartup methods are called.
062 Activator.getInstance().earlyStartup();
063 }
064
065 public IAnnotationTypeInfo getAnnotationTypeInfo() {
066 return null;
067 }
068
069 public Object getCurrentAst() {
070 return result;
071 }
072
073 public ILexer getLexer() {
074 return null;
075 }
076
077 public ISourcePositionLocator getNodeLocator() {
078 return new TokenLocator();
079 }
080
081 public IParser getParser() {
082 return null;
083 }
084
085 public IPath getPath() {
086 return filePath;
087 }
088
089 public ISourceProject getProject() {
090 return project;
091 }
092
093 public ILanguageSyntaxProperties getSyntaxProperties() {
094 // TODO Auto-generated method stub
095 return null;
096 }
097
098 public void initialize(IPath filePath, ISourceProject project, IMessageHandler handler) {
099 this.filePath = filePath;
100 this.project = project;
101 this.handler = handler;
102
103 connect(); // NOTE: This may only be called once.
104
105 // try to make path absolute
106 IFile file = project.getRawProject().getFile(filePath);
107
108 if (file.exists()) {
109 absPath = file.getLocation().toOSString();
110 } else {
111 absPath = filePath.toOSString();
112 }
113 }
114
115 public Object parse(String input, boolean scanOnly, IProgressMonitor monitor) {
116 String l = this.getLanguage().getName();
117
118 ATermAppl response = sendRequest(factory.make("parse(<str>,<str>,<str>)", l, absPath, input));
119 ATerm res = response.getArgument(0);
120
121 if (res.getType() == ATerm.APPL) {
122 ATermAppl appl = (ATermAppl) res;
123 String name = appl.getName();
124
125 if (name.equals(TIME_OUT)) {
126 result = null;
127 errors = null;
128 return null;
129 } else if (name.equals("correct")) {
130 result = appl.getArgument(0);
131 errors = null;
132 return result;
133 } else if (name.equals("error")) {
134 result = null;
135 errors = eFactory.SummaryFromTerm(appl.getArgument(0)).getList();
136 handleErrors(errors);
137 return null;
138 }
139 }
140
141 return result;
142 }
143
144 private void handleErrors(ErrorList list) {
145 for (; !list.isEmpty(); list = list.getTail()) {
146 Error error = list.getHead();
147 Subject subject = error.getList().getHead();
148 Area area;
149
150 if (subject.hasLocation()) {
151 area = subject.getLocation().getArea();
152 } else {
153 area = eFactory.makeArea_Area(0, 0, 0, 0, 0, 0);
154 }
155
156 handler.handleSimpleMessage(error.getDescription() + ": "
157 + subject.getDescription(), area.getOffset(), area
158 .getOffset()
159 + area.getLength(), area.getBeginColumn(), area
160 .getEndColumn(), area.getBeginLine(), area.getEndLine());
161 }
162 }
163
164 public Iterator<?> getTokenIterator(IRegion region) {
165 if (result != null) {
166 ATermAppl response = sendRequest(factory.make("highlight(<term>)", result));
167 ATerm ack = response.getArgument(0);
168
169 if (ack instanceof ATermList) {
170 ATermList slices = (ATermList) ack;
171 return new TokenIterator(eFactory, slices);
172 }
173 // timeout happened
174 }
175
176 return new TokenIterator(eFactory, factory.makeList());
177 }
178
179 public Language getLanguage() {
180 return LanguageRegistry.findLanguage(filePath, null);
181 }
182 }