package net.java.textilej.parser.tag;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* <em>Experimental: this API is subject to change</em>
*
* Define a dialect of textile.
*
*
* @author dgreen
*
*/
public abstract class Dialect {
protected List<BlockTag> blockTags = new ArrayList<BlockTag>();
private PatternBasedSyntax<ReplacementTokenProcessor,ReplacementToken> tokenSyntax = new PatternBasedSyntax<ReplacementTokenProcessor,ReplacementToken>();
private PatternBasedSyntax<PhraseModifierProcessor, PhraseModifier> phraseModifierSyntax = new PatternBasedSyntax<PhraseModifierProcessor, PhraseModifier>();
public BlockTagProcessor startBlock(String lineText, int offset) {
for (BlockTag tag: blockTags) {
BlockTagProcessor processor = tag.start(lineText, offset);
if (processor != null) {
return processor;
}
}
return null;
}
protected void addToken(ReplacementToken token) {
tokenSyntax.elements.add(token);
}
public ReplacementTokenProcessor findReplacementToken(String lineText,int offset) {
return tokenSyntax.findReplacementToken(lineText, offset);
}
protected void addPhraseModifier(PhraseModifier modifier) {
phraseModifierSyntax.elements.add(modifier);
}
public PhraseModifierProcessor findPhraseModifier(String lineText,int offset) {
return phraseModifierSyntax.findReplacementToken(lineText, offset);
}
private static class PatternBasedSyntax<P extends PatternBasedElementProcessor,T extends PatternBasedElement<P>> {
protected List<T> elements = new ArrayList<T>();
protected Pattern elementPattern;
protected List<Integer> elementGroup = new ArrayList<Integer>();
public P findReplacementToken(String lineText,int offset) {
if (elementPattern == null && !elements.isEmpty()) {
StringBuilder buf = new StringBuilder();
int group = 0;
for (T element: elements) {
if (buf.length() > 0) {
buf.append('|');
}
++group;
buf.append('(');
buf.append(element.getPattern());
buf.append(')');
elementGroup.add(group);
group += element.getPatternGroupCount();
}
if (buf.length() != 0) {
elementPattern = Pattern.compile(buf.toString());
}
}
if (elementPattern != null) {
Matcher matcher = elementPattern.matcher(lineText);
if (offset > 0) {
matcher.region(offset, lineText.length());
}
if (matcher.find()) {
for (int x = 0;x<elementGroup.size();++x) {
int group = elementGroup.get(x);
String value = matcher.group(group);
if (value != null) {
T element = elements.get(x);
P processor = element.newProcessor();
processor.setLineStartOffset(matcher.start());
processor.setLineEndOffset(matcher.end());
for (int y = 0;y<element.getPatternGroupCount();++y) {
processor.setGroup(y+1,matcher.group(group+y+1));
}
return processor;
}
}
throw new IllegalStateException();
} else {
return null;
}
} else {
return null;
}
}
}
}