ParserOutput.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;
import java.io.PrintStream;
import java.io.PrintWriter;
/**
* An instance of this class is the output of a parser.
*
* @author Mackenzie High
*/
public final class ParserOutput
{
/**
* This is the parse-tree, if parsing was successful; otherwise, this field is null.
*/
final ITreeNode parse_tree;
/**
* This is the object that recorded the parsing-attempt.
*/
final Tracer tracer;
/**
* This is the farthest location that parsing reached.
*/
final int farthest_position;
/**
* This is the input that the parser attempted to parse.
*/
final char[] input;
/**
* Sole Constructor.
*
* @param input is the input that the parser tried to parse.
* @param parse_tree is the parse-tree that was created by the parser,
* or null, if parsing was unsuccessful.
* @param tracer is the object that recorded the parsing-attempt.
* @param farthest_match is the farthest location that parsing reached.
*/
ParserOutput(final char[] input,
final ITreeNode parse_tree,
final Tracer tracer,
final int farthest_position)
{
Utils.checkNonNull(input);
Utils.checkNonNull(tracer);
this.input = input;
this.parse_tree = parse_tree;
this.tracer = tracer;
this.farthest_position = farthest_position;
}
/**
* This method determines whether parsing succeeded.
*
* @return true, if and only if, parsing was successful.
*/
public boolean success()
{
return parse_tree != null;
}
/**
* This method returns the farthest location that parsing reached.
*
* <p>The returned position is often useful, when searching for syntax-errors.</p>
*
* @return the aforedescribed location, which is the index relating to the parser's input.
*/
public int lengthOfConsumption()
{
return farthest_position;
}
/**
* This method returns a record describing stages of the parsing-attempt.
*
* <p>The returned list may be useful for debugging grammar and/or finding syntax-errors.</p>
*
* @return the aforedescribed record.
*/
public Trace trace()
{
return tracer.output();
}
/**
* This method retrieves and returns the parse-tree created by this parser.
*
* <p>The returned value is actually the root node in the parse-tree.</p>
*
* @return the parse-tree created by the parser, or null, if no such parse-tree exists.
*/
public ITreeNode parseTree()
{
return parse_tree;
}
/**
* This method prints a message describing the status of the output.
*
* <p> If
* <code>sucess() == true</code>, then the string "Parsing Succeeded!" is printed. </p>
*
* <p> If
* <code>sucess() == false</code>, then the string "Parsing Failed!" is printed. </p>
*
* @param writer is the writer to write to.
* @param newline is the style of the newlines in the parser's input.
* @param estimate is true, if and only if the line and column numbers are to be written also.
* @param exact is true, if and only if the length of consumption is to be written also.
* @param trace is true, if and only if the trace is to be written also.
*/
public void print(final PrintWriter writer,
final NewlineStyles newline,
final boolean estimate,
final boolean exact,
final boolean trace)
{
if (success())
{
writer.println("Parsing Succeeded!");
}
else
{
writer.println("Parsing Failed!");
final int position = lengthOfConsumption();
if (estimate)
{
final LinesAndColumns finder = new LinesAndColumns(input, newline);
final int line = position > 0 ? finder.lineNumbers()[position] : 1;
final int column = position > 0 ? finder.columnNumbers()[position] : 1;
writer.println();
writer.print("Syntax Error Position (Approximate):");
writer.println();
writer.print(" Line: #");
writer.println(line);
writer.print(" Column: #");
writer.println(column);
}
if (exact)
{
writer.println();
writer.print("Length of Consumption: ");
writer.println(lengthOfConsumption());
}
if (trace)
{
writer.println();
tracer.output().print(writer);
}
}
}
/**
* Convenience overload of:
* <code>print(PrintWriter, boolean, boolean, boolean)</code>.
*
* <p>See the aforementioned method for more details.</p>
*
* @param stream is the stream to write to.
* @param newline is the style of the newlines in the parser's input.
* @param estimate is true, if and only if the line and column numbers are to be written.
* @param exact is true, if and only if the length of consumption is to be written.
* @param trace is true, if and only if the trace is to be written.
*/
public void print(final PrintStream stream,
final NewlineStyles newline,
final boolean estimate,
final boolean exact,
final boolean trace)
{
final PrintWriter writer = new PrintWriter(stream);
print(writer, newline, estimate, exact, trace);
writer.flush();
}
/**
* Equivalent to:
* <code>print(writer, NewlineStyles.fromSystem(), estimate, exact, trace)</code>.
*/
public void print(final PrintWriter writer,
final boolean estimate,
final boolean exact,
final boolean trace)
{
print(writer, NewlineStyles.fromSystem(), estimate, exact, trace);
}
/**
* Equivalent to:
* <code>print(stream, NewlineStyles.fromSystem(), estimate, exact, trace)</code>.
*/
public void print(final PrintStream stream,
final boolean estimate,
final boolean exact,
final boolean trace)
{
print(stream, NewlineStyles.fromSystem(), estimate, exact, trace);
}
/**
* This method makes reporting the existence of syntax errors simpler.
*
* @throws ParsingFailedException <code>if(!this.success())</code>
*/
public void requireSuccess()
throws ParsingFailedException
{
if (!success())
{
throw new ParsingFailedException(this);
}
}
}