KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > languages > ParserManagerImpl


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.modules.languages;
20
21 import java.lang.ref.WeakReference JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Map JavaDoc;
25 import java.util.ArrayList JavaDoc;
26 import javax.swing.JEditorPane JavaDoc;
27 import javax.swing.SwingUtilities JavaDoc;
28 import javax.swing.event.DocumentEvent JavaDoc;
29 import javax.swing.event.DocumentListener JavaDoc;
30 import javax.swing.text.Document JavaDoc;
31 import org.netbeans.api.languages.ASTEvaluator;
32 import org.netbeans.api.languages.ASTEvaluator;
33 import org.netbeans.api.languages.ASTItem;
34 import org.netbeans.api.languages.ASTPath;
35 import org.netbeans.api.languages.LanguagesManager;
36 import org.netbeans.api.languages.ParserManager;
37 import org.netbeans.api.languages.ParserManagerListener;
38 import org.netbeans.api.languages.ASTToken;
39 import org.netbeans.api.languages.SyntaxContext;
40 import org.netbeans.api.languages.ParseException;
41 import org.netbeans.api.lexer.Token;
42 import org.netbeans.api.lexer.TokenHierarchy;
43 import org.netbeans.api.lexer.TokenSequence;
44 import org.netbeans.api.languages.SyntaxContext;
45 import org.netbeans.api.languages.ASTNode;
46 import org.netbeans.modules.languages.parser.TokenInput;
47 import org.netbeans.modules.languages.LanguagesManagerImpl;
48 import org.netbeans.modules.languages.LanguagesManagerImpl.LanguagesManagerListener;
49 import org.netbeans.modules.languages.parser.LLSyntaxAnalyser;
50 import org.netbeans.modules.editor.NbEditorDocument;
51 import org.openide.cookies.EditorCookie;
52 import org.openide.util.RequestProcessor;
53 import org.openide.ErrorManager;
54 import org.openide.windows.TopComponent;
55
56
57 /**
58  *
59  * @author Jan Jancura
60  */

61 public class ParserManagerImpl extends ParserManager {
62
63     private Document JavaDoc doc;
64     private ASTNode ast = null;
65     private ParseException exception = null;
66     private State state = State.NOT_PARSED;
67     private List JavaDoc<ParserManagerListener> listeners = new ArrayList JavaDoc<ParserManagerListener> ();
68     private List JavaDoc<ASTEvaluator> evaluators = new ArrayList JavaDoc<ASTEvaluator> ();
69     private static RequestProcessor rp = new RequestProcessor ("Parser");
70     
71     
72     public ParserManagerImpl (Document JavaDoc doc) {
73         this.doc = doc;
74         new DocListener (this, doc);
75         String JavaDoc mimeType = (String JavaDoc) doc.getProperty ("mimeType");
76     }
77     
78     public State getState () {
79         return state;
80     }
81     
82     public ASTNode getAST () throws ParseException {
83         if (exception != null) throw exception;
84         return ast;
85     }
86     
87     public void addListener (ParserManagerListener l) {
88         listeners.add (l);
89     }
90     
91     public void removeListener (ParserManagerListener l) {
92         listeners.remove (l);
93     }
94     
95     public void addASTEvaluator (ASTEvaluator e) {
96         evaluators.add (e);
97     }
98     
99     public void removeASTEvaluator (ASTEvaluator e) {
100         evaluators.remove (e);
101     }
102     
103     
104     // private methods .........................................................
105

106     private RequestProcessor.Task parsingTask;
107     
108     private synchronized void startParsing () {
109         setChange (State.PARSING, ast);
110         if (parsingTask != null) {
111             String JavaDoc mimeType = (String JavaDoc) doc.getProperty ("mimeType");
112             try {
113                 Language l = ((LanguagesManagerImpl) LanguagesManager.getDefault ()).
114                     getLanguage (mimeType);
115                 LLSyntaxAnalyser a = l.getAnalyser ();
116                 a.cancel ();
117             } catch (ParseException ex) {
118                 ex.printStackTrace();
119             }
120             parsingTask.cancel ();
121         }
122         parsingTask = rp.post (new Runnable JavaDoc () {
123             public void run () {
124                 parseAST ();
125             }
126         }, 1000);
127     }
128     
129     private void setChange (State state, ASTNode root) {
130         if (state == this.state) return;
131         
132         //switch (state) {case PARSING:System.out.println("parsing started");break;case OK:System.out.println("parsed OK");break;case ERROR:System.out.println("parser ERROR");};
133

134         this.state = state;
135         this.ast = root;
136         exception = null;
137         Iterator JavaDoc<ParserManagerListener> it = new ArrayList JavaDoc<ParserManagerListener> (listeners).iterator ();
138         while (it.hasNext ()) {
139             ParserManagerListener l = it.next ();
140             l.parsed (state, root);
141         }
142         if (state == State.PARSING) return;
143         if (!evaluators.isEmpty ()) {
144             Iterator JavaDoc<ASTEvaluator> it2 = evaluators.iterator ();
145             while (it2.hasNext ()) {
146                 ASTEvaluator e = it2.next ();
147                 e.beforeEvaluation (state, root);
148             }
149             evaluate (state, root, root, new ArrayList JavaDoc<ASTItem> ());
150             it2 = evaluators.iterator ();
151             while (it2.hasNext ()) {
152                 ASTEvaluator e = it2.next ();
153                 e.afterEvaluation (state, root);
154             }
155         }
156         refreshPanes ();
157     }
158     
159     private void evaluate (State state, ASTItem root, ASTItem item, List JavaDoc<ASTItem> path) {
160         path.add (item);
161         ASTPath path2 = ASTPath.create (path);
162         Iterator JavaDoc<ASTEvaluator> it = evaluators.iterator ();
163         while (it.hasNext ()) {
164             ASTEvaluator e = it.next ();
165             e.evaluate (state, path2);
166         }
167         Iterator JavaDoc<ASTItem> it2 = item.getChildren ().iterator ();
168         while (it2.hasNext ())
169             evaluate (state, root, it2.next (), path);
170         path.remove (path.size () - 1);
171     }
172     
173     private void setChange (ParseException ex) {
174         state = State.ERROR;
175         ast = null;
176         exception = ex;
177         Iterator JavaDoc<ParserManagerListener> it = new ArrayList JavaDoc<ParserManagerListener> (listeners).iterator ();
178         while (it.hasNext ()) {
179             ParserManagerListener l = it.next ();
180             l.parsed (state, ast);
181         }
182         if (state == State.PARSING) return;
183         refreshPanes();
184     }
185     
186     private void refreshPanes() {
187         SwingUtilities.invokeLater(new Runnable JavaDoc() {
188             public void run() {
189                 Iterator JavaDoc it = TopComponent.getRegistry ().getOpened ().iterator ();
190                 while (it.hasNext ()) {
191                     TopComponent tc = (TopComponent) it.next ();
192                     EditorCookie ec = (EditorCookie) tc.getLookup ().lookup (EditorCookie.class);
193                     if (ec == null) continue;
194                     JEditorPane JavaDoc[] eps = ec.getOpenedPanes ();
195                     if (eps == null) {
196                         continue;
197                     }
198                     int i, k = eps.length;
199                     for (i = 0; i < k; i++) {
200                         if (eps[i].getDocument () == doc) {
201                             eps[i].repaint ();
202                         }
203                     }
204                 }
205             }
206         });
207     }
208     
209     private void parseAST () {
210         try {
211             setChange (State.PARSING, ast);
212             ast = parse (doc);
213             if (ast == null) {
214                 setChange (new ParseException ("ast is null?!"));
215                 return;
216             }
217             ast = process (ast);
218             if (ast == null) {
219                 setChange (new ParseException ("ast is null?!"));
220                 return;
221             }
222             setChange (State.OK, ast);
223         } catch (ParseException ex) {
224             if (ex.getASTNode () != null) {
225                 ASTNode ast = process (ex.getASTNode ());
226                 ex = new ParseException (ex, ast);
227             }
228             setChange (ex);
229             ErrorManager.getDefault ().notify (ex);
230         }
231     }
232     
233     private ASTNode process (ASTNode root) {
234         try {
235             String JavaDoc mimeType = (String JavaDoc) doc.getProperty ("mimeType");
236             Language l = ((LanguagesManagerImpl) LanguagesManager.getDefault ()).
237                 getLanguage (mimeType);
238             Feature astProperties = l.getFeature ("AST");
239             if (astProperties != null && ast != null) {
240                 return (ASTNode) astProperties.getValue (
241                     "process",
242                     SyntaxContext.create (doc, ASTPath.create (root))
243                 );
244             }
245             return root;
246         } catch (Exception JavaDoc ex) {
247             ErrorManager.getDefault ().notify (ex);
248             return root;
249         }
250     }
251     
252     private static ASTNode parse (Document JavaDoc doc) throws ParseException {
253         String JavaDoc mimeType = (String JavaDoc) doc.getProperty ("mimeType");
254         Language l = ((LanguagesManagerImpl) LanguagesManager.getDefault ()).
255             getLanguage (mimeType);
256         LLSyntaxAnalyser a = l.getAnalyser ();
257         long start = System.currentTimeMillis ();
258
259         TokenInput input = createTokenInput (doc);
260         long to = System.currentTimeMillis () - start;
261         ASTNode n = a.read (input, true);
262         System.out.println("parse " + doc.getProperty ("title") + " " + (System.currentTimeMillis () - start) + " " + to);
263         return n;
264     }
265
266     private static TokenInput createTokenInput (Document JavaDoc doc) {
267         try {
268             if (doc instanceof NbEditorDocument)
269                 ((NbEditorDocument) doc).readLock ();
270             TokenHierarchy th = TokenHierarchy.get (doc);
271             TokenSequence ts = th.tokenSequence ();
272             return TokenInput.create (getTokens (ts));
273         } finally {
274             if (doc instanceof NbEditorDocument)
275                 ((NbEditorDocument) doc).readUnlock ();
276         }
277     }
278     
279     private static List JavaDoc<ASTToken> getTokens (TokenSequence ts) {
280         List JavaDoc<ASTToken> tokens = new ArrayList JavaDoc<ASTToken> ();
281         while (ts.moveNext ()) {
282             Token t = ts.token ();
283             String JavaDoc type = t.id ().name ();
284             int offset = ts.offset ();
285             String JavaDoc ttype = (String JavaDoc) t.getProperty ("type");
286             if (ttype == null || ttype.equals ("E")) {
287                 List JavaDoc<ASTToken> children = null;
288                 TokenSequence ts2 = ts.embedded ();
289                 if (ts2 != null)
290                     children = getTokens (ts2);
291                 tokens.add (ASTToken.create (
292                     ts.language ().mimeType (),
293                     type,
294                     t.text ().toString (),
295                     offset,
296                     t.length (),
297                     children
298                 ));
299             } else
300             if (ttype.equals ("S")) {
301                 StringBuilder JavaDoc sb = new StringBuilder JavaDoc (t.text ().toString ());
302                 List JavaDoc<ASTToken> children = new ArrayList JavaDoc<ASTToken> ();
303                 TokenSequence ts2 = ts.embedded ();
304 // if (ts2 != null)
305
// children.addAll (
306
// getTokens (ts2)
307
// );
308
while (ts.moveNext ()) {
309                     t = ts.token ();
310                     ttype = (String JavaDoc) t.getProperty ("type");
311                     if (ttype == null) {
312                         ts.movePrevious ();
313                         break;
314                     }
315                     if (ttype.equals ("E")) {
316                         ts2 = ts.embedded ();
317 // children.add (ASTToken.create (
318
// ts2.language ().mimeType (),
319
// t.id ().name (),
320
// t.text ().toString (),
321
// ts.offset (),
322
// t.length (),
323
// getTokens (ts2)
324
// ));
325
children.addAll (
326                             getTokens (ts2)
327                         );
328                         continue;
329                     }
330                     if (ttype.equals ("S")) {
331                         ts.movePrevious ();
332                         break;
333                     }
334                     if (!ttype.equals ("C"))
335                         throw new IllegalArgumentException JavaDoc ();
336 // ts2 = ts.embedded ();
337
// if (ts2 != null)
338
// children.addAll (
339
// getTokens (ts2)
340
// );
341
if (!type.equals (t.id ().name ()))
342                         throw new IllegalArgumentException JavaDoc ();
343                     sb.append (t.text ().toString ());
344                 }
345                 int no = ts.offset () + ts.token ().length ();
346                 tokens.add (ASTToken.create (
347                     ts.language ().mimeType (),
348                     type,
349                     sb.toString (),
350                     offset,
351                     no - offset,
352                     children
353                 ));
354             } else
355                 throw new IllegalArgumentException JavaDoc ();
356         }
357         return tokens;
358     }
359     
360     
361     // innerclasses ............................................................
362

363     private static class DocListener implements DocumentListener JavaDoc,
364     LanguagesManagerListener {
365         
366         private WeakReference JavaDoc<ParserManagerImpl> pmwr;
367         private ParserManagerImpl pman;
368         
369         DocListener (ParserManagerImpl pm, Document JavaDoc doc) {
370             pmwr = new WeakReference JavaDoc<ParserManagerImpl> (pm);
371             pman = pm;
372             doc.addDocumentListener (this);
373             ((LanguagesManagerImpl) LanguagesManager.getDefault ()).addLanguagesManagerListener (this);
374         }
375         
376         private ParserManagerImpl getPM () {
377             ParserManagerImpl pm = pmwr.get ();
378             pman = null;
379             if (pm != null) return pm;
380             ((LanguagesManagerImpl) LanguagesManager.getDefault ()).removeLanguagesManagerListener (this);
381             return null;
382         }
383         
384         public void insertUpdate (DocumentEvent JavaDoc e) {
385             ParserManagerImpl pm = getPM ();
386             if (pm == null) return;
387             pm.startParsing ();
388         }
389
390         public void removeUpdate (DocumentEvent JavaDoc e) {
391             ParserManagerImpl pm = getPM ();
392             if (pm == null) return;
393             pm.startParsing ();
394         }
395
396         public void changedUpdate (DocumentEvent JavaDoc e) {
397             getPM ();
398         }
399
400         public void languageChanged (String JavaDoc mimeType) {
401             ParserManagerImpl pm = getPM ();
402             if (pm == null) return;
403             pm.startParsing ();
404         }
405
406         public void languageAdded(String JavaDoc mimeType) {
407             getPM ();
408         }
409
410         public void languageRemoved(String JavaDoc mimeType) {
411             getPM ();
412         }
413     }
414 }
415
416
417
418
Popular Tags