State.java
/*
* Copyright 2013 Michael Mackenzie High
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mackenziehigh.snowflake;
/**
* An instance of this class stores the mutable state of a parser.
*
* @author Michael Mackenzie High
*/
final class State
{
/**
* This object records the starts/successes/failures of match-attempts.
*/
public final Tracer tracer;
/**
* This is the input being parsed by the parser.
*/
public final char[] input;
/**
* This is the current position of the parser.
*
* <p>
* The current position of the parser is the start position of the next match.
* When a rule matches, the position of the parser moves forward (i.e. advances).
* When the the parser backtracks, the position of the parser moves backward.
* Note, predicate rules do not cause the position to advance, even if they successfully match.
* </p>
*/
public int position = 0;
/**
* This is the farthest position that parsing has reached, thus far.
*/
public int farthest_position = 0;
/**
* Sole Constructor.
*
* @param input is to input to be parsed.
*/
public State(final char[] input, final int trace_count)
{
Utils.checkNonNull(input);
this.input = input;
this.tracer = new Tracer(trace_count);
}
/**
* This method is called whenever a rule begins a match attempt.
*
* @param rule is the rule itself.
* @return the current position of the parser.
*/
public int begin(final Rule rule)
{
// Record the start of a new match-attempt.
this.tracer.add(rule, position, TraceElementReason.BEGIN);
return position;
}
/**
* This method is called by a rule that has just successfully matched.
*
* @param rule is the rule itself.
*/
public void succeed(final Rule rule)
{
// Record the success of a match-attempt.
this.tracer.add(rule, position, TraceElementReason.SUCCESS);
}
/**
* This method is called by a rule that has just failed to match.
*
* @param rule is the rule itself.
* @param restore_position is the position in the parser's input to backtrack to.
*/
public void fail(final Rule rule, final int restore_position)
{
// Record the failure of a match-attempt.
this.tracer.add(rule, position, TraceElementReason.FAIL);
// Backtrack
this.position = restore_position;
}
/**
* This method returns the number of characters in the input that still can be consumed.
*
* @return the number of characters in the input waiting to be parsed.
*/
public int remaining() { return input.length - position; }
/**
* This method returns the next character in the input and advances the position.
*
* @return the next character in the input.
* @throws IndexOutOfBoundsException if there is no input waiting to be consumed.
*/
public char next()
{
// The parser is moving forward.
// If this is the farthest position the parser has reached, record the location.
// This record will help the user find syntax-errors.
this.farthest_position = position + 1 > farthest_position
? position : farthest_position;
// Return the next character from the parser's input and advance one positition forward.
return input[position++];
}
}