Implemented on-line help system, initial trace system, debug functions.

Rewrote REPL
Added NIL and comments to parser.
Added T as a predefined constant.
Added HELP, TRACE, ENABLE-DEBUG-AST special form.
Fixed variable evaluation (shouldn't automatically eval it's value)
This commit is contained in:
Jonathan Bernard 2009-11-21 20:00:39 -06:00
parent 943c91dedc
commit dfc1234817
17 changed files with 785 additions and 104 deletions

View File

@ -6,4 +6,5 @@ package edu.utexas.cs345.jdblisp;
*/
public interface FormEntry {
SExp call(SymbolTable table, Seq arguments) throws LispException;
HelpTopic helpinfo();
}

View File

@ -0,0 +1,56 @@
package edu.utexas.cs345.jdblisp;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
/**
* FormHelpTopic
* @author Jonathan Bernard (jdbernard@gmail.com)
*/
public class FormHelpTopic extends HelpTopic {
protected final String invokation;
protected final String[][] parameters;
/**
* TODO
*/
public FormHelpTopic(String operatorName, String shortDescription,
String invokation, String longDescription, String... parameterDefinitions) {
super(operatorName, shortDescription, longDescription);
this.invokation = invokation;
assert (parameterDefinitions.length % 2 == 0);
ArrayList<String[]> paramDefs = new ArrayList<String[]>();
for (int i = 0; i < parameterDefinitions.length; i+=2) {
paramDefs.add(new String[] {
parameterDefinitions[i],
parameterDefinitions[i+1] });
}
parameters = paramDefs.toArray(new String[][] {});
}
@Override
public void print(OutputStream os, int wrapWidth) {
WrappedPrinter out = new WrappedPrinter(os, wrapWidth, true);
out.print(name + ": ");
if (shortDescription != null)
out.println(shortDescription, " ");
out.println();
out.println(invokation, " ");
out.println();
if (body != null) {
out.println(body, " ");
out.println();
}
for (String[] param : parameters) {
out.print(param[0] + "\t", " ");
out.println(param[1], " ");
}
}
}

View File

@ -6,16 +6,52 @@ package edu.utexas.cs345.jdblisp;
*/
public class FunctionEntry implements FormEntry {
public final HelpTopic helpinfo;
public final Symbol name;
protected final Symbol[] parameters;
protected final SExp body;
public FunctionEntry(Symbol[] parameters, SExp body) {
protected boolean traceEnabled;
//private Logger traceLog = Logger.getLogger(getClass());
public FunctionEntry(Symbol name, Symbol[] parameters, SExp body) {
// build invocation help string
String invokation = "(" + name.name;
for (Symbol param : parameters) invokation += " <" + param.name + ">";
invokation += ")";
String bodyInfo = "Function body: " + body.toString();
// build help topic
FormHelpTopic helpinfo = new FormHelpTopic(name.name, null, invokation, bodyInfo);
this.name = name;
this.parameters = parameters;
this.body = body;
this.helpinfo = helpinfo;
}
public FunctionEntry(Symbol name, Symbol[] parameters, SExp body,
HelpTopic helpinfo) {
this.name = name;
this.parameters = parameters;
this.body = body;
this.helpinfo = helpinfo;
}
public boolean isTraceEnabled() { return traceEnabled ;}
public void enableTrace(boolean enable) { this.traceEnabled = enable; }
public SExp call(SymbolTable symbolTable, Seq arguments) throws LispException {
String traceString = null;
SExp evaluatedArg, retVal;
if (traceEnabled)
traceString = "(" + name.name;
// bind arguments to parameters
SymbolTable localScope = new SymbolTable(symbolTable);
int i = 0;
@ -27,7 +63,10 @@ public class FunctionEntry implements FormEntry {
parameters.length, i);
// bind one arg to param
localScope.bind(parameters[i], new VariableEntry(arguments.car.eval(symbolTable)));
evaluatedArg = arguments.car.eval(symbolTable);
localScope.bind(parameters[i], new VariableEntry(evaluatedArg));
if (traceEnabled) traceString += " " + evaluatedArg.toString();
arguments = arguments.cdr;
++i;
@ -38,6 +77,18 @@ public class FunctionEntry implements FormEntry {
throw new InvalidArgumentQuantityException(parameters.length,
(i + arguments.length()));
return body.eval(localScope);
if (traceEnabled) traceString += ")";
if (traceEnabled) System.out.println(traceString);
retVal = body.eval(localScope);
if (traceEnabled)
traceString = name.name + " returned " + retVal.toString();
if (traceEnabled) System.out.println(traceString);
return retVal;
}
public HelpTopic helpinfo() { return helpinfo; }
}

View File

@ -0,0 +1,120 @@
package edu.utexas.cs345.jdblisp;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
/**
* HelpTopic
* @author Jonathan Bernard (jdbernard@gmail.com)
*/
public class HelpTopic {
public static Map<String, HelpTopic> helpTopics;
protected final String name;
protected final String shortDescription;
protected final String body;
public HelpTopic(String name, String shortDescription, String body) {
this.name = name;
this.shortDescription = shortDescription;
this.body = body;
}
public void print(OutputStream os) { print(os, 79); }
public void print(OutputStream os, int wrapWidth) {
WrappedPrinter out = new WrappedPrinter(os, wrapWidth, true);
out.println(name);
out.println(shortDescription, " ");
out.println();
out.println(body, " ");
}
class WrappedPrinter {
private PrintWriter printer;
private int wrapWidth;
private int lastPrintedLineLength = 0;
public WrappedPrinter(OutputStream os, int wrapWidth,
boolean autoflush) {
this(new PrintWriter(os, autoflush), wrapWidth);
}
public WrappedPrinter(PrintWriter pw, int wrapWidth) {
this.printer = pw;
this.wrapWidth = wrapWidth;
}
public void print(String message) { print(message, ""); }
public void print(String message, String offset) {
int lastSpaceIdx = 0;
int curLineLength = 0;
int lineStartIdx = 0;
int i = 0;
int actualWidth = wrapWidth - offset.length();
//message = message.replaceAll("[\n\r]", " ");
// print initial offset if this is the beginning of the line
if (lastPrintedLineLength == 0) {
printer.print(offset);
curLineLength = offset.length();
}
for (i = 0; i < message.length(); ++i) {
curLineLength++;
if (message.charAt(i) == '\t') curLineLength += 7;
// line has overflowed the prescribed width
if (curLineLength > actualWidth) {
// print up to the last space before the overflow
printer.println(message.substring(lineStartIdx, lastSpaceIdx));
// pick up the next line after said space
lineStartIdx = lastSpaceIdx + 1;
i = lastSpaceIdx;
curLineLength = 0;
// print initial offset if there is still more to print
if (lineStartIdx < message.length()) {
printer.print(offset);
curLineLength = offset.length();
}
}
// see whitespace, update last space index
if (Character.isWhitespace(message.charAt(i))) lastSpaceIdx = i;
}
// any left over, it will fit on one line
if (i - lineStartIdx > 1) {
String lastLine = message.substring(lineStartIdx);
printer.print(lastLine);
curLineLength += lastLine.length();
}
// save back the new position
lastPrintedLineLength = curLineLength;
}
public void println() { println("", ""); }
public void println(String message) { println(message, ""); }
public void println(String message, String offset) {
print(message, offset);
printer.println();
lastPrintedLineLength = 0;
}
}
}

View File

@ -0,0 +1,117 @@
package edu.utexas.cs345.jdblisp;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Scanner;
import edu.utexas.cs345.jdblisp.parser.Parser;
import edu.utexas.cs345.jdblisp.parser.ParseException;
/**
* @author Jonathan Bernard (jdbernard@gmail.com)
*/
public class LISPRuntime {
public static final String VERSION = "0.1.0";
public SymbolTable globalSymbolTable;
private Parser parser;
private boolean interactive = true;
boolean dumpAST = false;
private OutputStream os;
public LISPRuntime() {
this(true);
}
public LISPRuntime(boolean interactive) {
this.interactive = interactive;
Parser parser = new Parser(new ByteArrayInputStream(new byte[]{}));
globalSymbolTable = new SymbolTable();
SpecialFormEntry.defineSpecialForms(this);
globalSymbolTable.bind(new Symbol("T"), new VariableEntry(SExp.T));
}
// TODO: is this needed?
// public void setInteractive(boolean interactive) { this.interactive = interactive; }
public static void main(String[] args) throws IOException {
// create the LISP environment
LISPRuntime lisp = new LISPRuntime();
// print welcome message
System.out.println("Welcome to JDB-Lisp v" + VERSION + ", a subset of Common Lisp.");;
System.out.println("On-line help is available via the (help funcname) command.");
// parse command-line arguments (treat non-options as input files)
// TODO: replace with Apache Commons CLI
for (String arg : args) {
System.out.println("Loading file '" + arg + "...");
lisp.interactive = false;
lisp.repl(new FileInputStream(arg), System.out);
}
// drop into interactive mode
lisp.interactive = true;
lisp.repl(System.in, System.out);
}
public void repl(InputStream is, OutputStream os) throws IOException {
// wrap output in a more friendly object
this.os = os;
PrintWriter out = new PrintWriter(os,true);
parser.ReInit(is);
SExp sexp;
while (true) {
// print prompt if applicable
if (interactive) {
out.print("> ");
out.flush();
}
try { sexp = parser.sexp(); }
catch (ParseException pe) {
// using the available call to check if the stream is open.
try { is.available(); } // if an exception is
catch (IOException ioe) { break; } // then it is closed
out.println(pe.getLocalizedMessage());
continue;
}
if (dumpAST) {
out.println("ABSTRACT SYNTAX:");
out.println(sexp.display(" "));
out.println("----------------");
}
if (interactive) {
try {
SExp result = sexp.eval(globalSymbolTable);
out.println(result == null ? "NIL" : result.toString());
} catch (LispException le) {
out.println(le.getLocalizedMessage());
continue;
}
}
}
out.println("\nLeaving JDB-LISP");
}
OutputStream getOutputStream() { return os; }
}

View File

@ -13,6 +13,10 @@ public class List implements SExp {
/** {@inheritdoc}*/
public SExp eval(SymbolTable table) throws LispException {
// null is NIL
if (seq == null) return null;
// if the car of the sequence is a symbol,
if (seq.car instanceof Symbol) {
// then that symbol is the name of an operator

View File

@ -21,11 +21,13 @@ SKIP : /* WHITE SPACE */
| "\t"
| "\n"
| "\n\r"
| ";.*$"
}
TOKEN : /* PUNCTUATION */
{ < LPAREN: "(" >
| < RPAREN: ")" >
| < NIL: (["N","n"]["I","i"]["L","l"])>
}
@ -55,7 +57,8 @@ SExp sexp():
List list():
{ Seq s;
}
{ <LPAREN> s = seq() <RPAREN> { return new List(s); }
{ <LPAREN> s = seq() <RPAREN> { return new List(s); }
| <NIL> { return new List(null); } // allow NIL to be shorthand for ()
}
/**

View File

@ -15,4 +15,15 @@ public interface SExp {
String display(String offset);
public static final SExp T = new SExp() {
public SExp eval(SymbolTable table) { return this; }
public String display(String offset) { return offset + "T\n"; }
public String toString() { return "T"; }
};
/*public static final SExp NIL = new SExp() {
SExp eval(SymbolTable table) { return this; }
String display(String offset) { return offset + "NIL\n"; }
String toString() { return "NIL"; }
};*/
}

View File

@ -49,6 +49,6 @@ public class Seq implements SExp {
@Override
public String toString() {
return car.toString() + (cdr == null ? "" : cdr.toString());
return car.toString() + (cdr == null ? "" : " " + cdr.toString());
}
}

View File

@ -1,5 +1,6 @@
package edu.utexas.cs345.jdblisp;
import java.io.PrintWriter;
import java.util.ArrayList;
/**
@ -8,17 +9,103 @@ import java.util.ArrayList;
*/
public abstract class SpecialFormEntry implements FormEntry {
protected Lisp environment;
public final HelpTopic helpinfo;
public SpecialFormEntry(Lisp environment) { this.environment = environment; }
protected LISPRuntime environment;
public abstract SExp call(SymbolTable symbolTable, Seq arguments) throws LispException;
public SpecialFormEntry(LISPRuntime environment, HelpTopic helpinfo) {
this.environment = environment;
this.helpinfo = helpinfo;
}
public HelpTopic helpinfo() { return helpinfo; }
public static void defineSpecialForms(Lisp environment) {
public abstract SExp call(SymbolTable symbolTable, Seq arguments)
throws LispException;
SpecialFormEntry DEFUN = new SpecialFormEntry(environment) {
public SExp call(SymbolTable symbolTable, Seq arguments) throws LispException {
// ------------------------
// SPECIAL FORMS DEFINITION
// ------------------------
// JDB-Lisp includes on-line help for all of its special forms. See the
// help strings for documentation of the individual special forms.
/**
* TODO
*/
public static void defineSpecialForms(LISPRuntime environment) {
// ----
// HELP
// ----
SpecialFormEntry HELP = new SpecialFormEntry(
environment,
new FormHelpTopic("HELP",
"Display online help information for a topic.",
"(help <topic>)",
null,
"topic",
"either a string representing the topic to lookup or a symbol"))
{
public SExp call(SymbolTable symbolTable, Seq arguments)
throws LispException {
HelpTopic topic = null;
// no arguments: print help for HELP
if (arguments == null)
return this.call(symbolTable,
new Seq(new Symbol("HELP"), null));
// too many arguments
if (arguments.length() > 1)
throw new InvalidArgumentQuantityException(1,
arguments.length());
// try to find the topic or function help
if (arguments.car instanceof Str) {
topic = HelpTopic.helpTopics.get(
((Str) arguments.car).value);
} else if (arguments.car instanceof Symbol) {
try {
FormEntry fe = symbolTable.lookupFunction(
(Symbol) arguments.car);
topic = fe.helpinfo();
} catch (LispException le) { topic = null; }
}
// no topic found
if (topic == null) {
new PrintWriter(environment.getOutputStream(), true)
.println(
"No help information found for topic '"
+ arguments.car.toString() + "'.");
return null;
}
topic.print(environment.getOutputStream());
return null;
}
};
// -----
// DEFUN
// -----
SpecialFormEntry DEFUN = new SpecialFormEntry(
environment,
new FormHelpTopic("DEFUN", "Define a (global) function.",
"(defun <name> (<param-list>) <func-body>)",
"Create a function binding. This will replace any existing binding.",
"name", "the symbol to bind to the function definition.",
"param-list", "a list of symbols that will be bound in the "
+ "function scope to the arguments passed to the function.",
"func-body", "an sexpression evaluated when the function is "
+ "called."))
{
public SExp call(SymbolTable symbolTable, Seq arguments)
throws LispException {
Symbol functionName;
ArrayList<Symbol> parameters = new ArrayList<Symbol>();
@ -27,7 +114,7 @@ public abstract class SpecialFormEntry implements FormEntry {
// TODO: check to see if a function for this symbol exists
// and warn if so
if (arguments.length() != 3)
if (arguments == null || arguments.length() != 3)
new InvalidArgumentQuantityException(3, arguments.length());
// first argument: Symbol for function name
@ -62,14 +149,31 @@ public abstract class SpecialFormEntry implements FormEntry {
body = arguments.car;
environment.globalSymbolTable.bind(functionName,
new FunctionEntry(parameters.toArray(new Symbol[]{}), body));
new FunctionEntry(functionName,
parameters.toArray(new Symbol[]{}),
body));
return functionName;
}
};
SpecialFormEntry SETQ = new SpecialFormEntry(environment) {
public SExp call(SymbolTable symbolTable, Seq arguments) throws LispException {
// ----
// SETQ
// ----
SpecialFormEntry SETQ = new SpecialFormEntry(
environment,
new FormHelpTopic("SETQ", "Define a global variable.",
"(setq <name> <value>)",
"Bind a value to a symbol in the global symbol table.",
"name", "the symbol to bind to the given value.",
"value", "an sexpression representing the value of the "
+ "variable. The value of the variable when it is "
+ "evaluated is the evaluated value of this sexpression."))
{
public SExp call(SymbolTable symbolTable, Seq arguments)
throws LispException {
Symbol variableName;
SExp variableValue;
@ -90,7 +194,7 @@ public abstract class SpecialFormEntry implements FormEntry {
arguments = arguments.cdr;
assert (arguments != null);
variableValue = arguments.car;
variableValue = arguments.car.eval(symbolTable);
environment.globalSymbolTable.bind(variableName,
new VariableEntry(variableValue));
@ -99,7 +203,51 @@ public abstract class SpecialFormEntry implements FormEntry {
}
};
SpecialFormEntry SUM = new SpecialFormEntry(environment) {
// -----
// TRACE
// -----
SpecialFormEntry TRACE = new SpecialFormEntry(
environment,
new FormHelpTopic("TRACE",
"enable trace information for a function",
"(trace <funcname>)",
"Turn on trace information for a function.",
"funcname", "the name of the function to trace"))
{
public SExp call(SymbolTable symbolTable, Seq arguments)
throws LispException {
if (arguments == null || arguments.car == null)
return null;
if (!(arguments.car instanceof Symbol))
throw new LispException(arguments.car.toString()
+ " is not a valid function name.");
FormEntry fe = symbolTable.lookupFunction((Symbol) arguments.car);
if (fe instanceof FunctionEntry) ((FunctionEntry) fe).enableTrace(true);
// TODO: else throw error
return null;
}
};
// ---
// SUM
// ---
SpecialFormEntry SUM = new SpecialFormEntry(
environment,
new FormHelpTopic("+", "Sum several expressions.",
"(+ [<addend_1> ... <addend_n>])",
"Compute the summation of the zero or more expressions passed"
+ "as arguments. In general, expressions are evaluated "
+ "before being bound to function parameters. The"
+ " expressions passed to sum must evaluate to numbers.",
"addend_1 ... addend_n", "Addends may be any expression that "
+ "evaluates to a number."))
{
public SExp call(SymbolTable symbolTable, Seq arguments)
throws LispException {
@ -119,7 +267,22 @@ public abstract class SpecialFormEntry implements FormEntry {
}
};
SpecialFormEntry DIF = new SpecialFormEntry(environment) {
SpecialFormEntry DIF = new SpecialFormEntry(
environment,
new FormHelpTopic("-", "Subtract several expressions.",
"(- subtrahend) | (- ??? <subtrahend_1> [... <subtrahend_n>])",
"Perform a subtraction. If there is only one argument passed "
+ "then result = 0 - arg. If multiple arguments are passed"
+ " then result = arg_1 - arg_2 - ... - args_n. In "
+ "general, expressions are evaluated before being bound "
+ " to function parameters. The expressions passed to - "
+ "must evaluate to numbers.",
"???", "In the case of multiple arguments to -, this is the "
+ "number from which the others are subtracted.",
"subtrahend_1 ... subtrahend_n", "Subtrahends are numbers "
+ "subtracted from the ??? and may be any expression that "
+ "evaluates to a number."))
{
public SExp call(SymbolTable symbolTable, Seq arguments)
throws LispException {
@ -158,7 +321,17 @@ public abstract class SpecialFormEntry implements FormEntry {
}
};
SpecialFormEntry MUL = new SpecialFormEntry(environment) {
SpecialFormEntry MUL = new SpecialFormEntry(
environment,
new FormHelpTopic("*", "Multiply several expressions.",
"(+ [<multiplicand_1> ... <multiplicand_n>])",
"Compute the product of the zero or more expressions passed"
+ "as arguments. In general, expressions are evaluated "
+ "before being bound to function parameters. The"
+ " expressions passed to multiply must evaluate to numbers.",
"multiplicand_1 ... multiplicand_n", "Multiplicands may be "
+ "any expression that evaluates to a number."))
{
public SExp call(SymbolTable symbolTable, Seq arguments)
throws LispException {
@ -179,7 +352,22 @@ public abstract class SpecialFormEntry implements FormEntry {
}
};
SpecialFormEntry DIV = new SpecialFormEntry(environment) {
SpecialFormEntry DIV = new SpecialFormEntry(
environment,
new FormHelpTopic("/", "Divide several expressions.",
"(- divisor) | (- quotient <divisor_1> [... <divisor_n>])",
"Perform division. If there is only one argument passed "
+ "then result = 1/ arg. If multiple arguments are passed"
+ " then result = arg_1 / arg_2 / ... / args_n, computed "
+ "from left to right. In general, expressions are "
+ "evaluated before being bound to function parameters. "
+ "The expressions passed to / must evaluate to numbers.",
"quotient", "In the case of multiple arguments to /, this is "
+ "the number which is diveded.",
"divisor_1 ... divisor_n", "Divisors are the numbers dividing "
+ "the quotient and may be any expression that evaluates "
+ "to a number."))
{
public SExp call(SymbolTable symbolTable, Seq arguments)
throws LispException {
@ -218,11 +406,47 @@ public abstract class SpecialFormEntry implements FormEntry {
}
};
SpecialFormEntry ENABLEDEBUGAST = new SpecialFormEntry(
environment,
new FormHelpTopic("ENABLE-DEBUG-AST",
"Enable debug information: abstract syntax tree.",
"(enable-debug-ast [<enable>])",
"When DEBUG-AST is enabled, the runtime environment prints a "
+ "representation of the abstract syntax tree generated "
+ "by the parser for each sexpression it parses.",
"enable", "NIL = disabled, anything else = enabled. No "
+ "argument = enabled."))
{
public SExp call(SymbolTable symbolTable, Seq arguments)
throws LispException {
if (arguments == null) {
environment.dumpAST = true;
return null;
}
SExp retVal = arguments.car.eval(symbolTable);
if (retVal != null) environment.dumpAST = true;
else environment.dumpAST = false;
return retVal;
}
};
/*SpecialFormEntry LET = new SpecialFormEntry(environment) {
public SExp call(SymbolTable table, Seq arguments) {
// TODO
}
}*/
environment.globalSymbolTable.bind(new Symbol("HELP"), HELP);
environment.globalSymbolTable.bind(new Symbol("DEFUN"), DEFUN);
environment.globalSymbolTable.bind(new Symbol("SETQ"), SETQ);
environment.globalSymbolTable.bind(new Symbol("TRACE"), TRACE);
environment.globalSymbolTable.bind(new Symbol("+"), SUM);
environment.globalSymbolTable.bind(new Symbol("-"), DIF);
environment.globalSymbolTable.bind(new Symbol("*"), MUL);
environment.globalSymbolTable.bind(new Symbol("/"), DIV);
environment.globalSymbolTable.bind(new Symbol("ENABLE-DEBUG-AST"), ENABLEDEBUGAST);
}
}

View File

@ -13,7 +13,7 @@ public class Symbol implements SExp {
/** {@inheritdoc}*/
public SExp eval(SymbolTable table) throws LispException {
VariableEntry ve = table.lookupVariable(this);
return ve.eval(table);
return ve.value;
}
public String display(String offset) {

View File

@ -6,11 +6,7 @@ package edu.utexas.cs345.jdblisp;
*/
public class VariableEntry {
protected final SExp expression;
public final SExp value;
public VariableEntry(SExp expression) { this.expression = expression; }
public SExp eval(SymbolTable symbolTable) throws LispException {
return expression.eval(symbolTable);
}
public VariableEntry(SExp value) { this.value = value; }
}

View File

@ -23,6 +23,7 @@ public class Parser implements ParserConstants {
{if (true) return new Num(t.image);}
break;
case LPAREN:
case NIL:
s = list();
{if (true) return s;}
break;
@ -39,10 +40,22 @@ public class Parser implements ParserConstants {
*/
static final public List list() throws ParseException {
Seq s;
jj_consume_token(LPAREN);
s = seq();
jj_consume_token(RPAREN);
{if (true) return new List(s);}
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
case LPAREN:
jj_consume_token(LPAREN);
s = seq();
jj_consume_token(RPAREN);
{if (true) return new List(s);}
break;
case NIL:
jj_consume_token(NIL);
{if (true) return new List(null);}
break;
default:
jj_la1[1] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
throw new Error("Missing return statement in function");
}
@ -53,6 +66,7 @@ public class Parser implements ParserConstants {
Seq sq; SExp se;
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
case LPAREN:
case NIL:
case NUMB:
case STRG:
case SYMB:
@ -61,7 +75,7 @@ public class Parser implements ParserConstants {
{if (true) return new Seq(se, sq);}
break;
default:
jj_la1[1] = jj_gen;
jj_la1[2] = jj_gen;
;
}
{if (true) return null;}
@ -78,13 +92,13 @@ public class Parser implements ParserConstants {
static public Token jj_nt;
static private int jj_ntk;
static private int jj_gen;
static final private int[] jj_la1 = new int[2];
static final private int[] jj_la1 = new int[3];
static private int[] jj_la1_0;
static {
jj_la1_init_0();
}
private static void jj_la1_init_0() {
jj_la1_0 = new int[] {0x740,0x740,};
jj_la1_0 = new int[] {0x1e80,0x280,0x1e80,};
}
/** Constructor with InputStream. */
@ -105,7 +119,7 @@ public class Parser implements ParserConstants {
token = new Token();
jj_ntk = -1;
jj_gen = 0;
for (int i = 0; i < 2; i++) jj_la1[i] = -1;
for (int i = 0; i < 3; i++) jj_la1[i] = -1;
}
/** Reinitialise. */
@ -119,7 +133,7 @@ public class Parser implements ParserConstants {
token = new Token();
jj_ntk = -1;
jj_gen = 0;
for (int i = 0; i < 2; i++) jj_la1[i] = -1;
for (int i = 0; i < 3; i++) jj_la1[i] = -1;
}
/** Constructor. */
@ -136,7 +150,7 @@ public class Parser implements ParserConstants {
token = new Token();
jj_ntk = -1;
jj_gen = 0;
for (int i = 0; i < 2; i++) jj_la1[i] = -1;
for (int i = 0; i < 3; i++) jj_la1[i] = -1;
}
/** Reinitialise. */
@ -146,7 +160,7 @@ public class Parser implements ParserConstants {
token = new Token();
jj_ntk = -1;
jj_gen = 0;
for (int i = 0; i < 2; i++) jj_la1[i] = -1;
for (int i = 0; i < 3; i++) jj_la1[i] = -1;
}
/** Constructor with generated Token Manager. */
@ -162,7 +176,7 @@ public class Parser implements ParserConstants {
token = new Token();
jj_ntk = -1;
jj_gen = 0;
for (int i = 0; i < 2; i++) jj_la1[i] = -1;
for (int i = 0; i < 3; i++) jj_la1[i] = -1;
}
/** Reinitialise. */
@ -171,7 +185,7 @@ public class Parser implements ParserConstants {
token = new Token();
jj_ntk = -1;
jj_gen = 0;
for (int i = 0; i < 2; i++) jj_la1[i] = -1;
for (int i = 0; i < 3; i++) jj_la1[i] = -1;
}
static private Token jj_consume_token(int kind) throws ParseException {
@ -222,12 +236,12 @@ public class Parser implements ParserConstants {
/** Generate ParseException. */
static public ParseException generateParseException() {
jj_expentries.clear();
boolean[] la1tokens = new boolean[11];
boolean[] la1tokens = new boolean[13];
if (jj_kind >= 0) {
la1tokens[jj_kind] = true;
jj_kind = -1;
}
for (int i = 0; i < 2; i++) {
for (int i = 0; i < 3; i++) {
if (jj_la1[i] == jj_gen) {
for (int j = 0; j < 32; j++) {
if ((jj_la1_0[i] & (1<<j)) != 0) {
@ -236,7 +250,7 @@ public class Parser implements ParserConstants {
}
}
}
for (int i = 0; i < 11; i++) {
for (int i = 0; i < 13; i++) {
if (la1tokens[i]) {
jj_expentry = new int[1];
jj_expentry[0] = i;

View File

@ -11,15 +11,17 @@ public interface ParserConstants {
/** End of File. */
int EOF = 0;
/** RegularExpression Id. */
int LPAREN = 6;
int LPAREN = 7;
/** RegularExpression Id. */
int RPAREN = 7;
int RPAREN = 8;
/** RegularExpression Id. */
int NUMB = 8;
int NIL = 9;
/** RegularExpression Id. */
int STRG = 9;
int NUMB = 10;
/** RegularExpression Id. */
int SYMB = 10;
int STRG = 11;
/** RegularExpression Id. */
int SYMB = 12;
/** Lexical state. */
int DEFAULT = 0;
@ -32,8 +34,10 @@ public interface ParserConstants {
"\"\\t\"",
"\"\\n\"",
"\"\\n\\r\"",
"\";.*$\"",
"\"(\"",
"\")\"",
"<NIL>",
"<NUMB>",
"<STRG>",
"<SYMB>",

View File

@ -36,9 +36,11 @@ static private int jjMoveStringLiteralDfa0_0()
jjmatchedKind = 4;
return jjMoveStringLiteralDfa1_0(0x20L);
case 40:
return jjStopAtPos(0, 6);
case 41:
return jjStopAtPos(0, 7);
case 41:
return jjStopAtPos(0, 8);
case 59:
return jjMoveStringLiteralDfa1_0(0x40L);
default :
return jjMoveNfa_0(0, 0);
}
@ -56,15 +58,55 @@ static private int jjMoveStringLiteralDfa1_0(long active0)
if ((active0 & 0x20L) != 0L)
return jjStopAtPos(1, 5);
break;
case 46:
return jjMoveStringLiteralDfa2_0(active0, 0x40L);
default :
break;
}
return jjStartNfa_0(0, active0);
}
static private int jjMoveStringLiteralDfa2_0(long old0, long active0)
{
if (((active0 &= old0)) == 0L)
return jjStartNfa_0(0, old0);
try { curChar = input_stream.readChar(); }
catch(java.io.IOException e) {
jjStopStringLiteralDfa_0(1, active0);
return 2;
}
switch(curChar)
{
case 42:
return jjMoveStringLiteralDfa3_0(active0, 0x40L);
default :
break;
}
return jjStartNfa_0(1, active0);
}
static private int jjMoveStringLiteralDfa3_0(long old0, long active0)
{
if (((active0 &= old0)) == 0L)
return jjStartNfa_0(1, old0);
try { curChar = input_stream.readChar(); }
catch(java.io.IOException e) {
jjStopStringLiteralDfa_0(2, active0);
return 3;
}
switch(curChar)
{
case 36:
if ((active0 & 0x40L) != 0L)
return jjStopAtPos(3, 6);
break;
default :
break;
}
return jjStartNfa_0(2, active0);
}
static private int jjMoveNfa_0(int startState, int curPos)
{
int startsAt = 0;
jjnewStateCnt = 9;
jjnewStateCnt = 12;
int i = 1;
jjstateSet[0] = startState;
int kind = 0x7fffffff;
@ -82,57 +124,61 @@ static private int jjMoveNfa_0(int startState, int curPos)
case 0:
if ((0x3ff000000000000L & l) != 0L)
{
if (kind > 8)
kind = 8;
jjCheckNAddTwoStates(1, 2);
if (kind > 10)
kind = 10;
jjCheckNAddTwoStates(4, 5);
}
else if ((0x2000ac0000000000L & l) != 0L)
{
if (kind > 10)
kind = 10;
jjCheckNAddTwoStates(7, 8);
if (kind > 12)
kind = 12;
jjCheckNAddTwoStates(10, 11);
}
else if (curChar == 34)
jjAddStates(0, 1);
if ((0x280000000000L & l) != 0L)
jjCheckNAdd(1);
break;
case 1:
if ((0x3ff000000000000L & l) == 0L)
break;
if (kind > 8)
kind = 8;
jjCheckNAddTwoStates(1, 2);
break;
case 2:
if (curChar == 46)
jjCheckNAdd(3);
jjCheckNAdd(4);
break;
case 3:
if ((0x3ff000000000000L & l) == 0L)
break;
if (kind > 8)
kind = 8;
jjCheckNAdd(3);
if ((0x280000000000L & l) != 0L)
jjCheckNAdd(4);
break;
case 4:
if (curChar == 34)
jjAddStates(0, 1);
break;
case 6:
if (curChar == 34 && kind > 9)
kind = 9;
break;
case 7:
if ((0x2000ac0000000000L & l) == 0L)
if ((0x3ff000000000000L & l) == 0L)
break;
if (kind > 10)
kind = 10;
jjCheckNAddTwoStates(7, 8);
jjCheckNAddTwoStates(4, 5);
break;
case 8:
if ((0x23ffac0000000000L & l) != 0L && kind > 10)
case 5:
if (curChar == 46)
jjCheckNAdd(6);
break;
case 6:
if ((0x3ff000000000000L & l) == 0L)
break;
if (kind > 10)
kind = 10;
jjCheckNAdd(6);
break;
case 7:
if (curChar == 34)
jjAddStates(0, 1);
break;
case 9:
if (curChar == 34 && kind > 11)
kind = 11;
break;
case 10:
if ((0x2000ac0000000000L & l) == 0L)
break;
if (kind > 12)
kind = 12;
jjCheckNAddTwoStates(10, 11);
break;
case 11:
if ((0x23ffac0000000000L & l) != 0L && kind > 12)
kind = 12;
break;
default : break;
}
@ -146,20 +192,37 @@ static private int jjMoveNfa_0(int startState, int curPos)
switch(jjstateSet[--i])
{
case 0:
case 7:
if ((0x7fffffe87fffffeL & l) == 0L)
break;
if (kind > 10)
kind = 10;
jjCheckNAddTwoStates(7, 8);
if ((0x7fffffe87fffffeL & l) != 0L)
{
if (kind > 12)
kind = 12;
jjCheckNAddTwoStates(10, 11);
}
if ((0x400000004000L & l) != 0L)
jjstateSet[jjnewStateCnt++] = 1;
break;
case 5:
case 1:
if ((0x20000000200L & l) != 0L)
jjstateSet[jjnewStateCnt++] = 2;
break;
case 2:
if ((0x100000001000L & l) != 0L && kind > 9)
kind = 9;
break;
case 8:
if ((0x7fffffe87fffffeL & l) != 0L)
jjAddStates(0, 1);
break;
case 8:
if ((0x7fffffe87fffffeL & l) != 0L && kind > 10)
kind = 10;
case 10:
if ((0x7fffffe87fffffeL & l) == 0L)
break;
if (kind > 12)
kind = 12;
jjCheckNAddTwoStates(10, 11);
break;
case 11:
if ((0x7fffffe87fffffeL & l) != 0L && kind > 12)
kind = 12;
break;
default : break;
}
@ -184,33 +247,33 @@ static private int jjMoveNfa_0(int startState, int curPos)
kind = 0x7fffffff;
}
++curPos;
if ((i = jjnewStateCnt) == (startsAt = 9 - (jjnewStateCnt = startsAt)))
if ((i = jjnewStateCnt) == (startsAt = 12 - (jjnewStateCnt = startsAt)))
return curPos;
try { curChar = input_stream.readChar(); }
catch(java.io.IOException e) { return curPos; }
}
}
static final int[] jjnextStates = {
5, 6,
8, 9,
};
/** Token literal values. */
public static final String[] jjstrLiteralImages = {
"", null, null, null, null, null, "\50", "\51", null, null, null, };
"", null, null, null, null, null, null, "\50", "\51", null, null, null, null, };
/** Lexer state names. */
public static final String[] lexStateNames = {
"DEFAULT",
};
static final long[] jjtoToken = {
0x7c1L,
0x1f81L,
};
static final long[] jjtoSkip = {
0x3eL,
0x7eL,
};
static protected SimpleCharStream input_stream;
static private final int[] jjrounds = new int[9];
static private final int[] jjstateSet = new int[18];
static private final int[] jjrounds = new int[12];
static private final int[] jjstateSet = new int[24];
static protected char curChar;
/** Constructor. */
public ParserTokenManager(SimpleCharStream stream){
@ -237,7 +300,7 @@ static private void ReInitRounds()
{
int i;
jjround = 0x80000001;
for (i = 9; i-- > 0;)
for (i = 12; i-- > 0;)
jjrounds[i] = 0x80000000;
}

View File

@ -0,0 +1,14 @@
package org.jdbernard.util;
import java.io.OutputStream;
/**
* NullOutputStream
* @author Jonathan Bernard (jdbernard@gmail.com)
* All output directed to this OutputStream is ignored and lost. Writing to
* stream is like writing to /dev/null.
*/
public class NullOutputStream extends OutputStream {
public void write(int b) {};
}

3
todo.txt Normal file
View File

@ -0,0 +1,3 @@
Implement FORMAT
Implement READ and PRINT
Implement IF