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    }