Finished initial version of AbstractSyntax
This commit is contained in:
parent
577ffcdcb3
commit
9a165a2131
@ -41,7 +41,9 @@
|
||||
<javac
|
||||
srcdir="${src.dir}"
|
||||
destdir="${build.dir}"
|
||||
classpathref="javac.path"/>
|
||||
classpathref="javac.path"
|
||||
debug="on"
|
||||
debuglevel="source,vars,lines"/>
|
||||
|
||||
</target>
|
||||
|
||||
|
@ -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 {
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
15
src/edu/utexas/cs345/jdblisp/LispException.java
Normal file
15
src/edu/utexas/cs345/jdblisp/LispException.java
Normal 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);
|
||||
}
|
||||
}
|
58
src/edu/utexas/cs345/jdblisp/List.java
Normal file
58
src/edu/utexas/cs345/jdblisp/List.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
54
src/edu/utexas/cs345/jdblisp/Num.java
Normal file
54
src/edu/utexas/cs345/jdblisp/Num.java
Normal 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();
|
||||
}
|
||||
}
|
@ -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); }
|
||||
}
|
||||
|
||||
/**
|
||||
|
18
src/edu/utexas/cs345/jdblisp/SExp.java
Normal file
18
src/edu/utexas/cs345/jdblisp/SExp.java
Normal 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);
|
||||
|
||||
}
|
49
src/edu/utexas/cs345/jdblisp/Seq.java
Normal file
49
src/edu/utexas/cs345/jdblisp/Seq.java
Normal 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();
|
||||
}
|
||||
}
|
30
src/edu/utexas/cs345/jdblisp/Str.java
Normal file
30
src/edu/utexas/cs345/jdblisp/Str.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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";
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user