![JAR search and dependency download from the Maven repository](/logo.png)
org.netbeans.editor.ext.MultiSyntax Maven / Gradle / Ivy
/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is NetBeans. The Initial Developer of the Original
* Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
* Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.editor.ext;
import java.util.Arrays;
import java.util.ArrayList;
import org.netbeans.editor.Syntax;
/**
* Composition of several syntaxes together. There are several different
* situations in which this class can be used efficiently:
* 1) Syntax that wants to use some other syntax internally for
* recognizing one or more tokens. Example is java analyzer that would
* like to use html-syntax for detail parsing block comments.
*
* 2) Master syntax that will manage two or more slave syntaxes. Example is the
* master syntax managing java-syntax and html-syntax. The result would
* be the same like in the previous example but it's more independent.
*
* 3) Master syntax that handles switching of the two or more other syntaxes. Only one
* slave syntax is active at one time.
*
* 4) An aribitrary combination and nesting of the previous examples.
*
* @author Miloslav Metelka
* @version 1.00
*/
public class MultiSyntax extends Syntax {
/** Slave syntaxes that can be used for scanning. They can
* be added by registerSyntax().
*/
private SyntaxInfo slaveSyntaxChain;
/** Last chain member of the slaveSyntaxChain */
private SyntaxInfo slaveSyntaxChainEnd;
/** Register a particular slave syntax. */
protected void registerSyntax(Syntax slaveSyntax) {
slaveSyntaxChainEnd = new SyntaxInfo(slaveSyntax, slaveSyntaxChainEnd);
if (slaveSyntaxChain == null) {
slaveSyntaxChain = slaveSyntaxChainEnd;
}
}
/** Store state of this analyzer into given mark state. */
public void storeState(StateInfo stateInfo) {
super.storeState(stateInfo);
((MultiStateInfo)stateInfo).store(this);
}
public void loadInitState() {
super.loadInitState();
SyntaxInfo syntaxItem = slaveSyntaxChain;
while (syntaxItem != null) {
syntaxItem.syntax.loadInitState();
syntaxItem = syntaxItem.next;
}
}
public void load(StateInfo stateInfo, char buffer[], int offset, int len,
boolean lastBuffer, int stopPosition) {
((MultiStateInfo)stateInfo).load(this, buffer, offset, len, lastBuffer, stopPosition);
super.load(stateInfo, buffer, offset, len, lastBuffer, stopPosition);
}
public StateInfo createStateInfo() {
return new MultiStateInfo();
}
/** Compare state of this analyzer to given state info. The basic
* implementation does the following:
* 1. state info of the main syntax is compared
* 2. if the result is EQUAL_STATE then go through all the registered slave syntaxes:
* a) get the info
*/
public int compareState(StateInfo stateInfo) {
int diff = super.compareState(stateInfo);
if (diff == EQUAL_STATE) {
diff = ((MultiStateInfo)stateInfo).compare(this);
}
return diff;
}
/** Class that can contain any number of the additional state infos from
* other syntaxes. The state infos stored are identified
* by the their syntax classes.
*/
public static class MultiStateInfo extends BaseStateInfo {
private ChainItem stateInfoChain;
/** Goes through all the syntaxes and inits them. If the multi-state-info has
* valid state-info for the given syntax the state-info is used.
* Otherwise the syntax is inited to the init state.
*/
void load(MultiSyntax masterSyntax, char[] buffer, int offset, int len,
boolean lastBuffer, int stopPosition) {
SyntaxInfo syntaxItem = masterSyntax.slaveSyntaxChain;
while (syntaxItem != null) {
StateInfo loadInfo = null;
int masterOffsetDelta = 0;
Syntax s = syntaxItem.syntax;
if (syntaxItem.active) {
Class sc = s.getClass();
ChainItem item = stateInfoChain;
while (item != null) {
if (item.syntaxClass == sc && item.valid) {
loadInfo = item.stateInfo;
masterOffsetDelta = item.masterOffsetDelta;
break;
}
item = item.prev;
}
}
s.load(loadInfo, buffer, offset + masterOffsetDelta,
len - masterOffsetDelta, lastBuffer, stopPosition);
syntaxItem = syntaxItem.next;
}
}
void store(MultiSyntax masterSyntax) {
// Invalidate all state-info chain items
ChainItem item = stateInfoChain;
while (item != null) {
item.valid = false;
item = item.prev;
}
// Go through active syntaxes and store their info and master-offset
SyntaxInfo syntaxItem = masterSyntax.slaveSyntaxChain;
while (syntaxItem != null) {
if (syntaxItem.active) {
Syntax s = syntaxItem.syntax;
Class sc = s.getClass();
item = stateInfoChain;
while (item != null) {
if (item.syntaxClass == sc) { // found right item
break;
}
item = item.prev;
}
if (item == null) { // not found, add new
item = stateInfoChain = new ChainItem(s.createStateInfo(),
sc, stateInfoChain);
}
// Store the state and compute masterOffsetDelta
s.storeState(item.stateInfo);
item.masterOffsetDelta = s.getOffset() - masterSyntax.getOffset();
item.valid = true;
}
syntaxItem = syntaxItem.next;
}
}
int compare(MultiSyntax masterSyntax) {
int ret = Syntax.EQUAL_STATE;
// Go through valid state-info chain items
ChainItem item = stateInfoChain;
while (item != null && ret == Syntax.EQUAL_STATE) {
if (item.valid) {
Class sc = item.syntaxClass;
SyntaxInfo syntaxItem = masterSyntax.slaveSyntaxChain;
while (syntaxItem != null) {
if (syntaxItem.syntax.getClass() == sc) {
if (syntaxItem.active) {
ret = syntaxItem.syntax.compareState(item.stateInfo);
} else { // syntax not active but should be
ret = Syntax.DIFFERENT_STATE;
}
break;
}
syntaxItem = syntaxItem.next;
}
}
item = item.prev;
}
return ret;
}
static class ChainItem {
/** Whether this item is valid. It can become invalid if the syntax that it represents
* becomes inactive in this item.
*/
boolean valid;
/** State info of the particular slave syntax */
StateInfo stateInfo;
/* Delta of the offset variable of the slave syntax against the offset
* variable of the master syntax.
*/
int masterOffsetDelta;
/** Class of the syntax this info is for */
Class syntaxClass;
/** Previous chain item in the list */
ChainItem prev;
ChainItem(StateInfo stateInfo, Class syntaxClass, ChainItem prev) {
this.stateInfo = stateInfo;
this.syntaxClass = syntaxClass;
this.prev = prev;
}
}
}
/** Extended info about one slave syntax */
static class SyntaxInfo {
SyntaxInfo(Syntax syntax, SyntaxInfo prevChainEnd) {
this.syntax = syntax;
if (prevChainEnd != null) {
prev = prevChainEnd;
prevChainEnd.next = this;
}
}
/** The slave syntax itself */
Syntax syntax;
/** Whether this syntax is actively scanning the text. There can be possibly more
* syntaxes scanning the in a nested way.
*/
boolean active;
/** Next member in the chain */
SyntaxInfo next;
/** Previous member in the chain */
SyntaxInfo prev;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy