Finished initial version of AbstractSyntax

This commit is contained in:
Jonathan Bernard 2009-11-19 09:56:52 -06:00
parent 577ffcdcb3
commit 9a165a2131
17 changed files with 317 additions and 97 deletions

View File

@ -41,7 +41,9 @@
<javac
srcdir="${src.dir}"
destdir="${build.dir}"
classpathref="javac.path"/>
classpathref="javac.path"
debug="on"
debuglevel="source,vars,lines"/>
</target>

View File

@ -1,11 +1,81 @@
package edu.utexas.cs345.jdblisp;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
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 Lisp {
public static void main(String[] args) {
private Parser parser;
private SymbolTable globalSymbolTable;
private boolean interactive = true;
public Lisp() {
this(true);
}
public Lisp(boolean interactive) {
this.interactive = interactive;
Parser parser = new Parser(new ByteArrayInputStream(new byte[]{}));
}
public static void main(String[] args) {
Lisp lisp = new Lisp();
lisp.repl(System.in, System.out);
globalSymbolTable = SpecialForms.createSymbolTable();
}
public void repl(InputStream is, OutputStream os) {
// wrap input and output in more friendly objects
Scanner in = new Scanner(is);
PrintWriter out = new PrintWriter(os);
// print prompt if applicable
if (interactive) {
out.print("> ");
out.flush();
}
// read each line of input
while(in.hasNextLine()) {
// get line
String line = in.nextLine();
// stuff it into an input buffer for the parser
ByteArrayInputStream bin = new ByteArrayInputStream(line.getBytes());
// re-init the parser with the new stream
parser.ReInit(bin);
// parse the line
SExp sexp;
try { sexp = parser.sexp(); }
catch (ParseException pe) {
// TODO
out.println(pe.getLocalizedMessage());
continue;
}
out.println(sexp.display(" "));
out.println(sexp.eval(globalSymbolTable).car.body);
// print prompt if applicable
if (interactive) {
out.print("> ");
out.flush();
}
}
}
}

View File

@ -0,0 +1,15 @@
package edu.utexas.cs345.jdblisp;
/**
* LispException
*/
public class LispException extends Exception {
public LispException(String message) {
this(message, null);
}
public LispException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -0,0 +1,58 @@
package edu.utexas.cs345.jdblisp;
/**
* @author Jonathan Bernard (jdbernard@gmail.com)
*/
public class List implements SExp {
public final Seq seq;
public List(Seq seq) {
this.seq = seq;
}
/** {@inheritdoc}*/
public SymbolTable eval(SymbolTable table) throws LispException {
// if the car of the sequence is a symbol,
if (seq.car instanceof Symbol) {
// then that symbol is the name of an operator
// Depending on the funciton binding of the operator in the
// current lexical environment the form is either:
// a special form
// a macro form or
// a function form
// look up in the symbol table
TableEntry functionEntry = table.findFunction((Symbol) seq.car);
// check parameter length
if (functionEntry.parameters.length != seq.cdr.length())
throw new LispException("Invalid number of parameters: "
+ seq.cdr.length());
// create a new SymbolTable and bind arguments to parameters
SymbolTable newTable = table;
Seq nextArg = seq.cdr;
for (Symbol parameter : functionEntry.parameters) {
TableEntry newEntry = new TableEntry(parameter, null, nextArg.car);
newTable = new SymbolTable(newEntry, newTable);
nextArg = nextArg.cdr;
}
// call function
return functionEntry.body.eval(newTable);
}
return null;
}
public String display(String offset) {
StringBuilder sb = new StringBuilder();
sb.append(offset);
sb.append("List: \n");
if (seq == null) sb.append(offset + " NIL\n");
else sb.append(seq.display(offset + " "));
return sb.toString();
}
}

View File

@ -0,0 +1,54 @@
package edu.utexas.cs345.jdblisp;
import java.math.BigDecimal;
import java.math.BigInteger;
/**
* @author Jonathan Bernard (jdbernard@gmail.com)
*/
public class Num implements SExp {
private Number n;
public Num(String string) {
try { n = Short.parseShort(string); return; }
catch (NumberFormatException nfe) {}
try { n = Integer.parseInt(string); return; }
catch (NumberFormatException nfe) {}
try { n = Long.parseLong(string); return; }
catch (NumberFormatException nfe) {}
try { n = new BigInteger(string); return; }
catch (NumberFormatException nfe) {}
try { n = Float.parseFloat(string); return; }
catch (NumberFormatException nfe) {}
try { n = Double.parseDouble(string); return; }
catch (NumberFormatException nfe) {}
try { n = new BigDecimal(string); return; }
catch (NumberFormatException nfe) {
throw new LispException("Cannot parse number: " + string);
}
}
/** {@inheritdoc} */
public SymbolTable eval(SymbolTable table) {
return new SymbolTable(
new TableEntry(
new Symbol("RETURN-VAL"),
null,
this));
}
public String display(String offset) {
return offset + "Num: " + n.toString() + "\n";
}
public String toString() {
return n.toString();
}
}

View File

@ -8,7 +8,7 @@ options {
PARSER_BEGIN(Parser)
package edu.utexas.cs345.jdblisp.parser;
import edu.utexas.cs345.jdblisp.data.*;
import edu.utexas.cs345.jdblisp.*;
public class Parser {
}
@ -44,9 +44,9 @@ TOKEN : /* LITERALS & SYMBOLS */
SExp sexp():
{ SExp s = null; Token t;
}
{ t = <SYMB> { return new Symbol(t); }
| t = <STRG> { return new Str(t); }
| t = <NUMB> { return new Num(t); }
{ t = <SYMB> { return new Symbol(t.image.toUpperCase()); }
| t = <STRG> { return new Str(t.image); }
| t = <NUMB> { return new Num(t.image); }
| s = list() { return s; }
}
@ -56,7 +56,7 @@ SExp sexp():
List list():
{ Seq s;
}
{ <LPAREN> s = seq() <RPAREN> { return (s == null) ? null : new List(s); }
{ <LPAREN> s = seq() <RPAREN> { return new List(s); }
}
/**

View File

@ -0,0 +1,18 @@
package edu.utexas.cs345.jdblisp;
/**
* SExp
* @author Jonathan Bernard (jdbernard@gmail.com)
*/
public interface SExp {
/**
* Evaluate this SExp within the context of the given SymbolTable.
* @param table The SymbolTable context for this scope.
* @return A SymbolTable containing the reutrn value.
*/
SymbolTable eval(SymbolTable table) throws LispException;
String display(String offset);
}

View File

@ -0,0 +1,49 @@
package edu.utexas.cs345.jdblisp;
/**
* Seq
* @author Jonathan Bernard (jdbernard@gmail.com)
*/
public class Seq implements SExp {
public final SExp car;
public final Seq cdr;
public Seq(SExp car, Seq cdr) {
assert (car != null);
this.car = car;
this.cdr = cdr;
}
public Seq(SExp... elements) {
int idx = elements.length;
Seq last = null;
while (idx > 1) last = new Seq(elements[--idx], last);
this.car = elements[0];
this.cdr = last;
}
/** {@inheritdoc}*/
public SymbolTable eval(SymbolTable table) {
assert(false) : "Attempted to eval() a Seq.";
throw new UnsupportedOperationException("Attempted to eval a Seq.");
}
public int length() {
if (cdr == null) return 1;
return 1 + cdr.length();
}
public String display(String offset) {
StringBuilder sb = new StringBuilder();
sb.append(offset);
sb.append("Seq: \n");
sb.append(car.display(offset + " "));
if (cdr != null) sb.append(cdr.display(offset));
return sb.toString();
}
}

View File

@ -0,0 +1,30 @@
package edu.utexas.cs345.jdblisp;
/**
* @author Jonathan Bernard (jdbernard@gmail.com)
*/
public class Str implements SExp {
public final String value;
public Str(String value) {
this.value = value;
}
/** {@inheritdoc}*/
public SymbolTable eval(SymbolTable table) {
return new SymbolTable(
new TableEntry(
"RETURN-VAL",
null,
this));
}
public String display(String offset) {
return offset + "Str: " + value + "\n";
}
public String toString() {
return value;
}
}

View File

@ -1,4 +1,5 @@
package edu.utexas.cs345.jdblisp.data;
package edu.utexas.cs345.jdblisp;
/**
* @author Jonathan Bernard (jdbernard@gmail.com)
*/
@ -9,8 +10,13 @@ public class Symbol implements SExp {
this.name = name;
}
public SExp eval(SExp sexp, SymbolTable table) {
/** {@inheritdoc}*/
public SymbolTable eval(SymbolTable table) {
// TODO
return null;
}
public String display(String offset) {
return offset + "Symbol: " + name + "\n";
}
}

View File

@ -1,17 +0,0 @@
package edu.utexas.cs345.jdblisp.data;
/**
* @author Jonathan Bernard (jdbernard@gmail.com)
*/
public class List implements SExp {
public final Seq<SExp> seq;
public List(Seq<SExp> seq) {
this.seq = seq;
}
public SExp eval(SExp sexp, SymbolTable table) {
// TODO
return null;
}
}

View File

@ -1,16 +0,0 @@
package edu.utexas.cs345.jdblisp.data;
/**
* @author Jonathan Bernard (jdbernard@gmail.com)
*/
public class Num implements SExp {
public Num(String n) {
// TODO
}
public SExp eval(SExp sexp, SymbolTable table) {
// TODO
return null;
}
}

View File

@ -1,9 +0,0 @@
package edu.utexas.cs345.jdblisp.data;
/**
* SExp
* @author Jonathan Bernard (jdbernard@gmail.com)
*/
public interface SExp {
SymbolTable eval(SExp sexp, SymbolTable table);
}

View File

@ -1,29 +0,0 @@
package edu.utexas.cs345.jdblisp.data;
/**
* Seq
* @author Jonathan Bernard (jdbernard@gmail.com)
*/
public class Seq<T extends SExp> implements SExp {
public final T car;
public final Seq<T> cdr;
public Seq(T car, Seq<T> cdr) {
this.car = car;
this.cdr = cdr;
}
public Seq(T... elements) {
int idx = elements.length;
Seq last = null;
while (idx > 1) last = new Seq(elements[--idx], last);
this.car = elements[0];
this.cdr = last;
}
public SExp eval(SExp sexp, SymbolTable table) {
// TODO
return null;
}
}

View File

@ -1,11 +0,0 @@
package edu.utexas.cs345.jdblisp.data;
/**
* @author Jonathan Bernard (jdbernard@gmail.com)
*/
public class Str implements SExp {
public SExp eval(SExp sexp, SymbolTable table) {
// TODO
return null;
}
}

View File

@ -1,7 +1,7 @@
/* Generated By:JavaCC: Do not edit this line. Parser.java */
package edu.utexas.cs345.jdblisp.parser;
import edu.utexas.cs345.jdblisp.data.*;
import edu.utexas.cs345.jdblisp.*;
public class Parser implements ParserConstants {
/**
@ -12,15 +12,15 @@ public class Parser implements ParserConstants {
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
case SYMB:
t = jj_consume_token(SYMB);
{if (true) return new Symbol(t);}
{if (true) return new Symbol(t.image.toUpperCase());}
break;
case STRG:
t = jj_consume_token(STRG);
{if (true) return new Str(t);}
{if (true) return new Str(t.image);}
break;
case NUMB:
t = jj_consume_token(NUMB);
{if (true) return new Num(t);}
{if (true) return new Num(t.image);}
break;
case LPAREN:
s = list();
@ -42,7 +42,7 @@ public class Parser implements ParserConstants {
jj_consume_token(LPAREN);
s = seq();
jj_consume_token(RPAREN);
{if (true) return (s == null) ? null : new List(s);}
{if (true) return new List(s);}
throw new Error("Missing return statement in function");
}

View File

@ -1,6 +1,6 @@
/* Generated By:JavaCC: Do not edit this line. ParserTokenManager.java */
package edu.utexas.cs345.jdblisp.parser;
import edu.utexas.cs345.jdblisp.data.*;
import edu.utexas.cs345.jdblisp.*;
/** Token Manager. */
public class ParserTokenManager implements ParserConstants