package com.jpaulmorrison.graphics;
/**
* This class is based on a (language) parsing technique called Babel, that I
* learned in England many years ago! This class definitely has an internal
* state, so all users must create an instance of it. This class is almost the
* same as the original JavaFBP BabelParser class, except that it simply returns
* false when requested to get more data...
**/
public class BabelParser2 {
static final String copyright = "Copyright 1999, 2000, 2001, 2012, J. Paul Morrison. At your option, you may copy, "
+ "distribute, or make derivative works under the terms of the Clarified Artistic License, "
+ "based on the Everything Development Company's Artistic License. A document describing "
+ "this License may be found at http://www.jpaulmorrison.com/fbp/artistic2.htm. "
+ "THERE IS NO WARRANTY; USE THIS PRODUCT AT YOUR OWN RISK.";
private char input[];
private char output[];
private int inputIndex;
private int outputIndex;
private int endOfInput;
Integer errNo;
/**
* BabelParser constructor.
*/
public BabelParser2(String inStr, Integer errNo) {
super();
inputIndex = 0;
outputIndex = 0;
output = new char[65536];
input = inStr.toCharArray();
endOfInput = inStr.length();
this.errNo = errNo;
}
/**
* Erase output stream
*/
public void eraseOutput() {
outputIndex = 0;
}
public boolean finished() {
return inputIndex >= endOfInput;
}
/**
* Get another input Packet - return false if no more
*/
boolean getMoreInput() {
return false;
}
/**
* Take output generated by syntax scan, and return as String Output index
* is then set back to zero.
*
* @return java.lang.String
*/
public String getOutStr() {
String sym = null;
if (outputIndex > 0) {
try {
sym = new String(output, 0, outputIndex);
} catch (NullPointerException r) {
System.out.println("RuntimeException:" + r);
} catch (IndexOutOfBoundsException e) {
System.out.println("RuntimeException:" + e);
}
outputIndex = 0;
}
return sym;
}
/**
* This macro compares against a given character. Scanning is continuous
* from the end of one incoming packet to the start of the next one. End of
* input results in a false result - i.e. end of input is considered to not
* match _any_ test character.
*/
public boolean tc(char x) {
while (inputIndex >= endOfInput) {
if (!getMoreInput())
return false;
}
if (input[inputIndex] != x)
return false;
if (outputIndex >= output.length) {
errNo = new Integer(1);
return false;
}
output[outputIndex] = input[inputIndex];
outputIndex++;
inputIndex++;
return true;
}
/**
* Same as tc(char), but with modification (must be 'i', 'n' or 'o') ('n' is
* equivalent to old Babel 'IO' - I- and O-modification)
*
* @param x
* char
* @param mod
* char
*/
public boolean tc(char x, char mod) {
while (inputIndex >= endOfInput) {
if (!getMoreInput())
return false;
}
if (input[inputIndex] != x)
return false;
if (mod != 'o' && mod != 'n') {
output[outputIndex] = input[inputIndex];
outputIndex++;
}
if (mod != 'i' && mod != 'n')
inputIndex++;
return true;
}
/**
* Test for blank, CR or tab, but with modification (must be 'i', 'n' or 'o')
* ('n' is equivalent to old Babel 'IO' - I- and O-modification)
* (the only blank tests in DiagramBuilder logic are all mod'd)
*
* @param mod
* char
*/
public boolean tb(char mod) {
while (inputIndex >= endOfInput) {
if (!getMoreInput())
return false;
}
if (input[inputIndex] != ' ' &&
input[inputIndex] != '\t' &&
input[inputIndex] != '\r' &&
input[inputIndex] != '\n')
return false;
if (mod != 'o' && mod != 'n') {
output[outputIndex] = input[inputIndex];
outputIndex++;
}
if (mod != 'i' && mod != 'n')
inputIndex++;
return true;
}
/**
* This macro compares against a number (figure). Scanning is continuous
* from the end of one incoming packet to the start of the next one. End of
* input results in a false result.
*/
public boolean tf() {
while (inputIndex >= endOfInput) {
if (!getMoreInput())
return false;
}
if (!Character.isDigit(input[inputIndex]))
return false;
if (outputIndex >= output.length) {
errNo = new Integer(1);
return false;
}
output[outputIndex] = input[inputIndex];
outputIndex++;
inputIndex++;
return true;
}
/**
* Same as tf(), but with modification (must be 'i', 'o' or 'n') ('n' is
* equivalent to old Babel 'IO' - I- and O-modification)
*
* @param mod
* char
*/
public boolean tf(char mod) {
while (inputIndex >= endOfInput) {
if (!getMoreInput())
return false;
}
if (!Character.isDigit(input[inputIndex]))
return false;
if (mod != 'o' && mod != 'n') {
output[outputIndex] = input[inputIndex];
outputIndex++;
}
if (mod != 'i' && mod != 'n')
inputIndex++;
return true;
}
/**
* This macro compares against a letter. Scanning is continuous from the end
* of one incoming packet to the start of the next one. End of input results
* in a false result.
*/
public boolean tl() {
while (inputIndex >= endOfInput) {
if (!getMoreInput())
return false;
}
if (!Character.isLetter(input[inputIndex]))
return false;
if (outputIndex >= output.length) {
errNo = new Integer(1);
return false;
}
output[outputIndex] = input[inputIndex];
outputIndex++;
inputIndex++;
return true;
}
/**
* Same as tl(), but with modification (must be 'i', 'o' or 'n') ('n' is
* equivalent to old Babel 'IO' - I- and O-modification)
*
* @param mod
* char
*/
public boolean tl(char mod) {
while (inputIndex >= endOfInput) {
if (!getMoreInput())
return false;
}
if (!Character.isLetter(input[inputIndex]))
return false;
if (mod != 'o' && mod != 'n') {
output[outputIndex] = input[inputIndex];
outputIndex++;
}
if (mod != 'i' && mod != 'n')
inputIndex++;
return true;
}
/**
* Babel 'universal comparator' - it is always true, unless we are at end of
* file
*/
public boolean tu() {
while (inputIndex >= endOfInput) {
if (!getMoreInput())
return false;
}
if (outputIndex >= output.length) {
errNo = new Integer(1);
return false;
}
output[outputIndex] = input[inputIndex];
outputIndex++;
inputIndex++;
return true;
}
/**
* Same as tu(), but with modification (must be 'i', 'o' or 'n') ('n' is
* equivalent to old Babel 'IO' - I- and O-modification)
*
* @param mod
* char
*/
public boolean tu(char mod) {
while (inputIndex >= endOfInput) {
if (!getMoreInput())
return false;
}
if (mod != 'o' && mod != 'n') {
output[outputIndex] = input[inputIndex];
outputIndex++;
}
if (mod != 'i' && mod != 'n')
inputIndex++;
return true;
}
/**
* Write one char out to output stream
*
* @param x
* char
*/
public boolean w(char x) {
if (outputIndex >= output.length) {
errNo = new Integer(1);
return false;
}
output[outputIndex] = x;
outputIndex++;
return true;
}
}