org.snapscript.parse.MatchFirstGrammar 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 MatchFirstGrammar implements Grammar {
private final List grammars;
private final String name;
private final int count;
private final int index;
public MatchFirstGrammar(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 MatchFirstMatcher(matchers, name, index, length);
}
private static class MatchFirstMatcher implements GrammarMatcher {
private final SparseArray cache;
private final GrammarMatcher[] matchers;
private final BitSet failure;
private final String name;
private final int index;
public MatchFirstMatcher(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 mark = checker.mark(index);
for(GrammarMatcher matcher : matchers) {
if(matcher.check(checker, depth + 1)) {
cache.set(position, matcher);
return true;
}
}
failure.set(position);
checker.reset(mark, index);
}
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) {
for(GrammarMatcher matcher : matchers) {
if(matcher.build(builder, depth + 1)) {
cache.set(position, matcher);
return true;
}
}
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) + "}";
}
}
}