package parser;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import grammar.Expression;
import source.Source;
import source.SourceStream;
/**
* This class holds the minimal amount of data that needs to be remembered for
* each expression graph node traversed while parsing the input. Since the graph
* can contain cycles, nodes can be traversed multiple times, generating each
* time a new ParseData object.
*/
public class ParseData
{
/****************************************************************************/
final Expression expr;
/****************************************************************************/
final Source source;
/****************************************************************************/
final int begin;
/****************************************************************************/
final boolean atomic;
/****************************************************************************/
final List<Match> childs;
/****************************************************************************/
final ParseErrors errors;
/****************************************************************************/
ParseData(Expression expr, SourceStream stream, boolean atomic)
{
this.expr = expr;
this.source = stream.source;
this.begin = stream.position;
this.atomic = atomic;
this.errors = atomic ? null : new ParseErrors(expr, begin);
this.childs = atomic
? Collections.<Match>emptyList()
: new ArrayList<Match>();
}
/*****************************************************************************
* Make a ParseData from a Match. Useful to inject matches (as ParseData) into
* the memoization table.
*/
ParseData(int position, Match match)
{
this.expr = match.expr;
this.source = match.source;
this.begin = position;
this.end = position;
this.atomic = false;
this.childs = null;
this.errors = new ParseErrors(expr, begin);
this.match = match;
this.succeeded = true;
}
/****************************************************************************/
Match match = null;
/****************************************************************************/
int end;
/****************************************************************************/
boolean succeeded = false;
/*****************************************************************************
* Marks the match as successful.
*/
void succeed(int position)
{
end = position;
succeeded = true;
match = new Match(expr, source, begin, end, childs);
expr.callbacks().parseDo(match);
}
/*****************************************************************************
* Marks the match as unsuccessful and backtrack to the begin of the partially
* matched expression.
*/
void fail()
{
end = begin;
succeeded = false;
}
/*****************************************************************************
* Combines the data associated to a sub-expression with this data.
*/
void merge(ParseData sub)
{
if (atomic) { return; }
if (sub.atomic) {
errors.merge(sub.begin);
}
else {
errors.merge(sub.errors);
}
if (sub.succeeded) {
childs.add(sub.match);
}
}
}