org.snapscript.parse.MatchOneGrammar Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of snap Show documentation
Show all versions of snap Show documentation
Dynamic scripting for the JVM
package org.snapscript.parse;
import java.util.Arrays;
import java.util.List;
import org.snapscript.common.BitSet;
import org.snapscript.common.SparseArray;
public class MatchOneGrammar implements Grammar {
private final List grammars;
private final String name;
private final int count;
private final int index;
public MatchOneGrammar(List grammars, String name, int count, int index) {
this.grammars = grammars;
this.index = index;
this.count = count;
this.name = name;
}
@Override
public GrammarMatcher create(GrammarCache cache, int length) {
GrammarMatcher[] matchers = new GrammarMatcher[count];
for(int i = 0; i < count; i++) {
Grammar grammar = grammars.get(i);
matchers[i] = grammar.create(cache, length);
}
return new MatchOneMatcher(matchers, name, index, length);
}
private static class MatchOneMatcher implements GrammarMatcher {
private final SparseArray cache;
private final GrammarMatcher[] matchers;
private final BitSet failure;
private final String name;
private final int index;
public MatchOneMatcher(GrammarMatcher[] matchers, String name, int index, int length) {
this.cache = new SparseArray(length);
this.failure = new BitSet(length);
this.matchers = matchers;
this.index = index;
this.name = name;
}
@Override
public boolean check(SyntaxChecker checker, int depth) {
int position = checker.position();
if(!failure.get(position)) {
GrammarMatcher best = cache.get(position);
if(best == null) {
int size = -1;
for(GrammarMatcher matcher : matchers) {
int mark = checker.mark(index);
if(mark != -1) {
if(matcher.check(checker, 0)) {
int offset = checker.reset(mark, index);
if(offset > size) {
size = offset;
best = matcher;
}
}
checker.reset(mark, index);
}
}
if(best != null) {
cache.set(position, best);
} else {
failure.set(position);
}
}
if(best != null) {
if(!best.check(checker, 0)) {
throw new ParseException("Could not read node in " + name);
}
return true;
}
}
return false;
}
@Override
public boolean build(SyntaxBuilder builder, int depth) {
int position = builder.position();
if(!failure.get(position)) {
GrammarMatcher best = cache.get(position);
if(best == null) {
int size = -1;
for(GrammarMatcher matcher : matchers) {
SyntaxBuilder child = builder.mark(index);
if(child != null) {
if(matcher.build(child, 0)) {
int offset = child.reset();
if(offset > size) {
size = offset;
best = matcher;
}
} else {
child.reset();
}
}
}
if(best != null) {
cache.set(position, best);
} else {
failure.set(position);
}
}
if(best != null) {
if(!best.build(builder, 0)) {
throw new ParseException("Could not read node in " + name);
}
return true;
}
}
return false;
}
@Override
public String toString() {
return Arrays.toString(matchers);
}
}
}