KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > editor > ext > MultiSyntax


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
20 package org.netbeans.editor.ext;
21
22 import java.util.Arrays JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import org.netbeans.editor.Syntax;
25
26 /**
27 * Composition of several syntaxes together. There are several different
28 * situations in which this class can be used efficiently:
29 * 1) Syntax that wants to use some other syntax internally for
30 * recognizing one or more tokens. Example is java analyzer that would
31 * like to use html-syntax for detail parsing block comments.
32 *
33 * 2) Master syntax that will manage two or more slave syntaxes. Example is the
34 * master syntax managing java-syntax and html-syntax. The result would
35 * be the same like in the previous example but it's more independent.
36 *
37 * 3) Master syntax that handles switching of the two or more other syntaxes. Only one
38 * slave syntax is active at one time.
39 *
40 * 4) An aribitrary combination and nesting of the previous examples.
41 *
42 * @author Miloslav Metelka
43 * @version 1.00
44 */

45
46 public class MultiSyntax extends Syntax {
47
48     /** Slave syntaxes that can be used for scanning. They can
49     * be added by registerSyntax().
50     */

51     private SyntaxInfo slaveSyntaxChain;
52
53     /** Last chain member of the slaveSyntaxChain */
54     private SyntaxInfo slaveSyntaxChainEnd;
55
56     /** Register a particular slave syntax. */
57     protected void registerSyntax(Syntax slaveSyntax) {
58         slaveSyntaxChainEnd = new SyntaxInfo(slaveSyntax, slaveSyntaxChainEnd);
59         if (slaveSyntaxChain == null) {
60             slaveSyntaxChain = slaveSyntaxChainEnd;
61         }
62     }
63
64     /** Store state of this analyzer into given mark state. */
65     public void storeState(StateInfo stateInfo) {
66         super.storeState(stateInfo);
67         ((MultiStateInfo)stateInfo).store(this);
68     }
69
70     public void loadInitState() {
71         super.loadInitState();
72         SyntaxInfo syntaxItem = slaveSyntaxChain;
73         while (syntaxItem != null) {
74             syntaxItem.syntax.loadInitState();
75             syntaxItem = syntaxItem.next;
76         }
77     }
78
79     public void load(StateInfo stateInfo, char buffer[], int offset, int len,
80                      boolean lastBuffer, int stopPosition) {
81         ((MultiStateInfo)stateInfo).load(this, buffer, offset, len, lastBuffer, stopPosition);
82         super.load(stateInfo, buffer, offset, len, lastBuffer, stopPosition);
83     }
84
85     public StateInfo createStateInfo() {
86         return new MultiStateInfo();
87     }
88
89     /** Compare state of this analyzer to given state info. The basic
90     * implementation does the following:
91     * 1. state info of the main syntax is compared
92     * 2. if the result is EQUAL_STATE then go through all the registered slave syntaxes:
93     * a) get the info
94     */

95     public int compareState(StateInfo stateInfo) {
96         int diff = super.compareState(stateInfo);
97         if (diff == EQUAL_STATE) {
98             diff = ((MultiStateInfo)stateInfo).compare(this);
99         }
100         return diff;
101     }
102
103
104     /** Class that can contain any number of the additional state infos from
105     * other syntaxes. The state infos stored are identified
106     * by the their syntax classes.
107     */

108     public static class MultiStateInfo extends BaseStateInfo {
109
110         private ChainItem stateInfoChain;
111
112         /** Goes through all the syntaxes and inits them. If the multi-state-info has
113         * valid state-info for the given syntax the state-info is used.
114         * Otherwise the syntax is inited to the init state.
115         */

116         void load(MultiSyntax masterSyntax, char[] buffer, int offset, int len,
117                   boolean lastBuffer, int stopPosition) {
118             SyntaxInfo syntaxItem = masterSyntax.slaveSyntaxChain;
119             while (syntaxItem != null) {
120                 StateInfo loadInfo = null;
121                 int masterOffsetDelta = 0;
122                 Syntax s = syntaxItem.syntax;
123                 if (syntaxItem.active) {
124                     Class JavaDoc sc = s.getClass();
125                     ChainItem item = stateInfoChain;
126                     while (item != null) {
127                         if (item.syntaxClass == sc && item.valid) {
128                             loadInfo = item.stateInfo;
129                             masterOffsetDelta = item.masterOffsetDelta;
130                             break;
131                         }
132                         item = item.prev;
133                     }
134                 }
135                 s.load(loadInfo, buffer, offset + masterOffsetDelta,
136                        len - masterOffsetDelta, lastBuffer, stopPosition);
137                 syntaxItem = syntaxItem.next;
138             }
139         }
140
141         void store(MultiSyntax masterSyntax) {
142             // Invalidate all state-info chain items
143
ChainItem item = stateInfoChain;
144             while (item != null) {
145                 item.valid = false;
146                 item = item.prev;
147             }
148
149             // Go through active syntaxes and store their info and master-offset
150
SyntaxInfo syntaxItem = masterSyntax.slaveSyntaxChain;
151             while (syntaxItem != null) {
152                 if (syntaxItem.active) {
153                     Syntax s = syntaxItem.syntax;
154                     Class JavaDoc sc = s.getClass();
155                     item = stateInfoChain;
156                     while (item != null) {
157                         if (item.syntaxClass == sc) { // found right item
158
break;
159                         }
160                         item = item.prev;
161                     }
162                     if (item == null) { // not found, add new
163
item = stateInfoChain = new ChainItem(s.createStateInfo(),
164                                                               sc, stateInfoChain);
165                     }
166                     // Store the state and compute masterOffsetDelta
167
s.storeState(item.stateInfo);
168                     item.masterOffsetDelta = s.getOffset() - masterSyntax.getOffset();
169                     item.valid = true;
170                 }
171                 syntaxItem = syntaxItem.next;
172             }
173         }
174
175         int compare(MultiSyntax masterSyntax) {
176             int ret = Syntax.EQUAL_STATE;
177             // Go through valid state-info chain items
178
ChainItem item = stateInfoChain;
179             while (item != null && ret == Syntax.EQUAL_STATE) {
180                 if (item.valid) {
181                     Class JavaDoc sc = item.syntaxClass;
182                     SyntaxInfo syntaxItem = masterSyntax.slaveSyntaxChain;
183                     while (syntaxItem != null) {
184                         if (syntaxItem.syntax.getClass() == sc) {
185                             if (syntaxItem.active) {
186                                 ret = syntaxItem.syntax.compareState(item.stateInfo);
187                             } else { // syntax not active but should be
188
ret = Syntax.DIFFERENT_STATE;
189                             }
190                             break;
191                         }
192                         syntaxItem = syntaxItem.next;
193                     }
194                 }
195                 item = item.prev;
196             }
197             return ret;
198         }
199
200         static class ChainItem {
201
202             /** Whether this item is valid. It can become invalid if the syntax that it represents
203             * becomes inactive in this item.
204             */

205             boolean valid;
206
207             /** State info of the particular slave syntax */
208             StateInfo stateInfo;
209
210             /* Delta of the offset variable of the slave syntax against the offset
211             * variable of the master syntax.
212             */

213             int masterOffsetDelta;
214
215             /** Class of the syntax this info is for */
216             Class JavaDoc syntaxClass;
217
218
219             /** Previous chain item in the list */
220             ChainItem prev;
221
222             ChainItem(StateInfo stateInfo, Class JavaDoc syntaxClass, ChainItem prev) {
223                 this.stateInfo = stateInfo;
224                 this.syntaxClass = syntaxClass;
225                 this.prev = prev;
226             }
227
228         }
229
230     }
231
232
233     /** Extended info about one slave syntax */
234     static class SyntaxInfo {
235
236         SyntaxInfo(Syntax syntax, SyntaxInfo prevChainEnd) {
237             this.syntax = syntax;
238
239             if (prevChainEnd != null) {
240                 prev = prevChainEnd;
241                 prevChainEnd.next = this;
242             }
243         }
244
245         /** The slave syntax itself */
246         Syntax syntax;
247
248         /** Whether this syntax is actively scanning the text. There can be possibly more
249         * syntaxes scanning the in a nested way.
250         */

251         boolean active;
252
253         /** Next member in the chain */
254         SyntaxInfo next;
255
256         /** Previous member in the chain */
257         SyntaxInfo prev;
258
259     }
260
261 }
262
Popular Tags