1 19 20 package org.netbeans.modules.languages; 21 22 import org.netbeans.api.languages.ASTItem; 23 import org.netbeans.api.languages.ASTPath; 24 import org.netbeans.api.languages.LanguagesManager; 25 import org.netbeans.api.languages.ParseException; 26 import org.netbeans.api.languages.ASTNode; 27 import org.netbeans.api.languages.ASTToken; 28 import org.netbeans.modules.languages.LanguagesManagerImpl; 29 import org.netbeans.modules.languages.parser.*; 30 import java.awt.*; 31 import java.util.*; 32 import java.util.List ; 33 import org.netbeans.modules.languages.parser.LLSyntaxAnalyser; 34 import org.netbeans.modules.languages.parser.LLSyntaxAnalyser.Rule; 35 import org.openide.ErrorManager; 36 37 38 42 public class Language { 43 44 45 public static final String ACTION = "ACTION"; 46 public static final String AST = "AST"; 47 public static final String BRACE = "BRACE"; 48 public static final String COLOR = "COLOR"; 49 public static final String COMPLETE = "COMPLETE"; 50 public static final String COMPLETION = "COMPLETION"; 51 public static final String FOLD = "FOLD"; 52 public static final String HYPERLINK = "HYPERLINK"; 53 public static final String IMPORT = "IMPORT"; 54 public static final String INDENT = "INDENT"; 55 public static final String MARK = "MARK"; 56 public static final String NAVIGATOR = "NAVIGATOR"; 57 public static final String PARSE = "PARSE"; 58 public static final String PROPERTIES = "PROPERTIES"; 59 public static final String REFORMAT = "REFORMAT"; 60 public static final String SKIP = "SKIP"; 61 public static final String STORE = "STORE"; 62 public static final String TOKEN = "TOKEN"; 63 public static final String TOOLTIP = "TOOLTIP"; 64 65 private Parser parser; 66 private List <TokenType> tokenTypes = new ArrayList<TokenType> (); 67 private Set<String > skipTokenTypes; 68 private String mimeType; 69 private LLSyntaxAnalyser analyser = null; 70 private List <ASTNode> grammarASTNodes = new ArrayList<ASTNode> (); 71 private List <Rule> grammarRules; 72 private List <Language> importedLangauges = new ArrayList<Language> (); 73 74 75 76 public Language (String mimeType) { 77 this.mimeType = mimeType; 78 } 79 80 81 83 public String getMimeType () { 84 return mimeType; 85 } 86 87 public Parser getParser () { 88 if (parser == null) 89 parser = Parser.create (tokenTypes); 90 return parser; 91 } 92 93 public List <TokenType> getTokenTypes () { 94 return Collections.unmodifiableList (tokenTypes); 95 } 96 97 public Set<String > getSkipTokenTypes () { 98 if (skipTokenTypes == null) { 99 skipTokenTypes = new HashSet<String > (); 100 List <Feature> ss = getFeatures ("SKIP"); 101 Iterator<Feature> it = ss.iterator (); 102 while (it.hasNext ()) { 103 Feature s = it.next (); 104 skipTokenTypes.add (s.getSelector ().getAsString ()); 105 } 106 } 107 return skipTokenTypes; 108 } 109 110 public boolean hasAnalyser () { 111 return !grammarASTNodes.isEmpty (); 112 } 113 114 public LLSyntaxAnalyser getAnalyser () { 115 if (analyser != null) return analyser; 116 synchronized (this) { 117 if (analyser != null) return analyser; 118 analyser = LLSyntaxAnalyser.create (this); 119 return analyser; 120 } 121 } 122 123 public List <Language> getImportedLanguages () { 124 return importedLangauges; 125 } 126 127 public static TokenType createTokenType ( 128 String startState, 129 Pattern<TokenType> pattern, 130 String type, 131 String endState, 132 int priority, 133 Feature properties 134 ) { 135 return new TokenType ( 136 startState, 137 pattern, 138 type, 139 endState, 140 priority, 141 properties 142 ); 143 } 144 145 146 148 void addToken ( 149 String startState, 150 String type, 151 Pattern pattern, 152 String endState, 153 Feature properties 154 ) { 155 if (parser != null) 156 throw new InternalError (); 157 tokenTypes.add (createTokenType ( 158 startState, 159 pattern, 160 type, 161 endState, 162 tokenTypes.size (), 163 properties 164 )); 165 } 166 167 void addRule (ASTNode rule) { 168 if (analyser != null) 169 throw new InternalError (); 170 grammarASTNodes.add (rule); 171 } 172 173 public void addRule (Rule rule) { 174 if (grammarRules == null) grammarRules = new ArrayList<Rule> (); 175 grammarRules.add (rule); 176 } 177 178 public List <Rule> getRules () { 179 if (grammarRules == null) 180 grammarRules = Petra.convert (grammarASTNodes, getMimeType ()); 181 return grammarRules; 182 } 183 184 private Feature preprocessorImport; 185 186 public Feature getPreprocessorImport () { 187 return preprocessorImport; 188 } 189 190 private Map<String ,Feature> tokenImports = new HashMap<String ,Feature> (); 191 192 public Map<String ,Feature> getTokenImports () { 193 return tokenImports; 194 } 195 196 void importLanguage ( 197 Feature feature 198 ) { 199 try { 200 String mimeType = (String ) feature.getValue ("mimeType"); 201 Language language = ((LanguagesManagerImpl) LanguagesManager.getDefault ()).getLanguage (mimeType); 202 if (feature.getPattern ("start") != null) { 203 assert (preprocessorImport == null); 205 preprocessorImport = feature; 206 importedLangauges.add (language); 207 return; 208 } 209 if (feature.getValue ("state") == null) { 210 String tokenName = feature.getSelector ().getAsString (); 211 assert (!tokenImports.containsKey (tokenName)); 212 tokenImports.put (tokenName, feature); 213 importedLangauges.add (language); 214 return; 215 } 216 217 String state = (String ) feature.getValue ("state"); 218 String tokenName = feature.getSelector ().getAsString (); 219 220 Iterator<TokenType> it = language.getTokenTypes ().iterator (); 222 while (it.hasNext ()) { 223 TokenType tt = it.next (); 224 String startState = tt.getStartState (); 225 Pattern pattern = tt.getPattern ().clonePattern (); 226 String endState = tt.getEndState (); 227 if (startState == null || Parser.DEFAULT_STATE.equals (startState)) 228 startState = state; 229 else 230 startState = tokenName + '-' + startState; 231 if (endState == null || Parser.DEFAULT_STATE.equals (endState)) 232 endState = state; 233 else 234 endState = tokenName + '-' + endState; 235 addToken (startState, tt.getType (), pattern, endState, tt.getProperties ()); 236 } 237 238 grammarASTNodes.addAll (language.grammarASTNodes); 240 importAllFeatures (language); 242 importedLangauges.addAll (language.importedLangauges); 243 tokenImports.putAll (language.tokenImports); 244 } catch (ParseException ex) { 245 ErrorManager.getDefault ().notify (ex); 246 } 247 } 248 249 250 252 private void importAllFeatures (Language l) { 253 Iterator<String > it = l.featureLists.keySet ().iterator (); 254 while (it.hasNext ()) { 255 String featureName = it.next (); 256 List <Feature> features = l.getFeatures (featureName); 257 Iterator<Feature> it2 = features.iterator (); 258 while (it2.hasNext ()) { 259 Feature f = it2.next (); 260 addFeature (f); 261 } 262 } 263 } 264 265 private Map<String ,List <Feature>> featureLists = new HashMap<String ,List <Feature>> (); 266 private Map<String ,Object > featuresMap = new HashMap<String ,Object > (); 267 private static final Object BLA = new Object (); 268 269 public void addFeature (Feature feature) { 270 String featureName = feature.getFeatureName (); 271 if (featureName.equals ("IMPORT")) { 272 importLanguage (feature); 273 return; 274 } 275 276 List <Feature> list = featureLists.get (featureName); 277 if (list == null) { 278 list = new ArrayList<Feature> (); 279 featureLists.put (featureName, list); 280 } 281 list.add (feature); 282 283 if (feature.getSelector () == null) { 284 Object o = featuresMap.get (featureName); 285 if (o == null) 286 featuresMap.put (featureName, feature); 287 else 288 if (o instanceof List ) 289 ((List ) o).add (feature); 290 else { 291 List <Feature> l = new ArrayList<Feature> (); 292 l.add ((Feature) o); 293 l.add (feature); 294 featuresMap.put (featureName, l); 295 } 296 return; 297 } 298 Map m = (Map) featuresMap.get (featureName); 299 if (m == null) { 300 m = new HashMap (); 301 featuresMap.put (featureName, m); 302 } 303 List <String > path = feature.getSelector ().getPath (); 304 for (int i = path.size () - 1; i > 0; i--) { 305 String name = path.get (i); 306 Object o = m.get (name); 307 if (o instanceof Map) 308 m = (Map) o; 309 else { 310 Map mm = new HashMap (); 311 if (o != null) 312 mm.put (BLA, o); 313 m.put (name, mm); 314 m = mm; 315 } 316 } 317 String name = path.get (0); 318 Object o = m.get (name); 319 if (o instanceof List ) 320 ((List <Feature>) o).add (feature); 321 else 322 if (o instanceof Map) { 323 m = (Map) o; 324 o = m.get (BLA); 325 if (o instanceof List ) 326 ((List ) o).add (feature); 327 else 328 if (o == null) 329 m.put (BLA, feature); 330 else { 331 List l = new ArrayList (); 332 l.add (o); 333 l.add (feature); 334 m.put (BLA, l); 335 } 336 } else 337 if (o == null) 338 m.put (name, feature); 339 else { 340 List l = new ArrayList (); 341 l.add (o); 342 l.add (feature); 343 m.put (name, l); 344 } 345 } 346 347 public List <Feature> getFeatures (String featureName) { 348 List <Feature> r = featureLists.get (featureName); 349 if (r != null) return r; 350 return Collections.<Feature>emptyList (); 351 } 352 353 public Feature getFeature (String featureName) { 354 List <Feature> r = featureLists.get (featureName); 355 if (r == null) return null; 356 if (r.size () == 1) return r.get (0); 357 throw new IllegalArgumentException (); 358 } 359 360 public Feature getFeature (String featureName, ASTPath path) { 361 List <Feature> r = getFeatures (featureName, path); 362 if (r.isEmpty ()) return null; 363 if (r.size () == 1) return r.get (0); 364 throw new IllegalArgumentException (); 365 } 366 367 public Feature getFeature (String featureName, String id) { 368 Map m = (Map) featuresMap.get (featureName); 369 if (m == null) return null; 370 Object o = m.get (id); 371 if (o instanceof Map) 372 o = ((Map) o).get (BLA); 373 if (o == null) return null; 374 if (o instanceof Feature) 375 return (Feature) o; 376 List <Feature> r = (List <Feature>) o; 377 if (r.isEmpty ()) return null; 378 if (r.size () == 1) return r.get (0); 379 throw new IllegalArgumentException (); 380 } 381 382 public List <Feature> getFeatures (String featureName, ASTPath path) { 383 Map m = (Map) featuresMap.get (featureName); 384 if (m == null) return Collections.<Feature>emptyList (); 385 Object last = null; 386 int i = path.size () - 1; 387 for (; i > 0; i--) { 388 ASTItem item = path.get (i); 389 String name = item instanceof ASTToken ? 390 ((ASTToken) item).getType () : 391 ((ASTNode) item).getNT (); 392 Object o = m.get (name); 393 if (m.containsKey (BLA)) 394 last = m.get (BLA); 395 if (o instanceof Map) { 396 m = (Map) o; 397 continue; 398 } 399 if (o instanceof List ) 400 return (List <Feature>) o; 401 if (o != null) 402 return Collections.<Feature>singletonList ((Feature) o); 403 if (last != null) { 404 if (last instanceof List ) 405 return (List <Feature>) last; 406 return Collections.<Feature>singletonList ((Feature) o); 407 } 408 break; 409 } 410 return Collections.<Feature>emptyList (); 411 } 412 413 466 494 503 void print () { 504 System.out.println("\nPrint " + mimeType); 505 System.out.println("Tokens:"); 506 Iterator<TokenType> it = getTokenTypes ().iterator (); 507 while (it.hasNext ()) { 508 TokenType r = it.next (); 509 System.out.println(" " + r); 510 } 511 System.out.println("Grammar Rules:"); 512 Iterator<Rule> it2 = getAnalyser ().getRules ().iterator (); 513 while (it.hasNext ()) { 514 Rule r = it2.next (); 515 System.out.println(" " + r); 516 } 517 } 518 519 public String toString () { 520 return "Language " + mimeType; 521 } 522 523 524 526 public static final class TokenType { 527 528 private String startState; 529 private Pattern<TokenType> pattern; 530 private String type; 531 private String endState; 532 private int priority; 533 private Feature properties; 534 535 private TokenType ( 536 String startState, 537 Pattern<TokenType> pattern, 538 String type, 539 String endState, 540 int priority, 541 Feature properties 542 ) { 543 this.startState = startState == null ? Parser.DEFAULT_STATE : startState; 544 this.pattern = pattern; 545 this.type = type; 546 this.endState = endState == null ? Parser.DEFAULT_STATE : endState; 547 this.priority = priority; 548 this.properties = properties; 549 } 550 551 public String getType () { 552 return type; 553 } 554 555 public String getStartState () { 556 return startState; 557 } 558 559 public String getEndState () { 560 return endState; 561 } 562 563 public Pattern<TokenType> getPattern () { 564 return pattern; 565 } 566 567 public int getPriority () { 568 return priority; 569 } 570 571 public Feature getProperties () { 572 return properties; 573 } 574 575 public String toString () { 576 return "Rule " + startState + " : type " + type + " : " + endState; 577 } 578 } 579 } 580 581 582 | Popular Tags |