Finished initial version of AbstractSyntax
This commit is contained in:
parent
577ffcdcb3
commit
9a165a2131
@ -41,7 +41,9 @@
|
|||||||
<javac
|
<javac
|
||||||
srcdir="${src.dir}"
|
srcdir="${src.dir}"
|
||||||
destdir="${build.dir}"
|
destdir="${build.dir}"
|
||||||
classpathref="javac.path"/>
|
classpathref="javac.path"
|
||||||
|
debug="on"
|
||||||
|
debuglevel="source,vars,lines"/>
|
||||||
|
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
@ -1,11 +1,81 @@
|
|||||||
package edu.utexas.cs345.jdblisp;
|
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)
|
* @author Jonathan Bernard (jdbernard@gmail.com)
|
||||||
*/
|
*/
|
||||||
public class Lisp {
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
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)
|
PARSER_BEGIN(Parser)
|
||||||
package edu.utexas.cs345.jdblisp.parser;
|
package edu.utexas.cs345.jdblisp.parser;
|
||||||
|
|
||||||
import edu.utexas.cs345.jdblisp.data.*;
|
import edu.utexas.cs345.jdblisp.*;
|
||||||
public class Parser {
|
public class Parser {
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -44,9 +44,9 @@ TOKEN : /* LITERALS & SYMBOLS */
|
|||||||
SExp sexp():
|
SExp sexp():
|
||||||
{ SExp s = null; Token t;
|
{ SExp s = null; Token t;
|
||||||
}
|
}
|
||||||
{ t = <SYMB> { return new Symbol(t); }
|
{ t = <SYMB> { return new Symbol(t.image.toUpperCase()); }
|
||||||
| t = <STRG> { return new Str(t); }
|
| t = <STRG> { return new Str(t.image); }
|
||||||
| t = <NUMB> { return new Num(t); }
|
| t = <NUMB> { return new Num(t.image); }
|
||||||
| s = list() { return s; }
|
| s = list() { return s; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ SExp sexp():
|
|||||||
List list():
|
List list():
|
||||||
{ Seq s;
|
{ 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)
|
* @author Jonathan Bernard (jdbernard@gmail.com)
|
||||||
*/
|
*/
|
||||||
@ -9,8 +10,13 @@ public class Symbol implements SExp {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SExp eval(SExp sexp, SymbolTable table) {
|
/** {@inheritdoc}*/
|
||||||
|
public SymbolTable eval(SymbolTable table) {
|
||||||
// TODO
|
// TODO
|
||||||
return null;
|
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 */
|
/* Generated By:JavaCC: Do not edit this line. Parser.java */
|
||||||
package edu.utexas.cs345.jdblisp.parser;
|
package edu.utexas.cs345.jdblisp.parser;
|
||||||
|
|
||||||
import edu.utexas.cs345.jdblisp.data.*;
|
import edu.utexas.cs345.jdblisp.*;
|
||||||
public class Parser implements ParserConstants {
|
public class Parser implements ParserConstants {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -12,15 +12,15 @@ public class Parser implements ParserConstants {
|
|||||||
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
|
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
|
||||||
case SYMB:
|
case SYMB:
|
||||||
t = jj_consume_token(SYMB);
|
t = jj_consume_token(SYMB);
|
||||||
{if (true) return new Symbol(t);}
|
{if (true) return new Symbol(t.image.toUpperCase());}
|
||||||
break;
|
break;
|
||||||
case STRG:
|
case STRG:
|
||||||
t = jj_consume_token(STRG);
|
t = jj_consume_token(STRG);
|
||||||
{if (true) return new Str(t);}
|
{if (true) return new Str(t.image);}
|
||||||
break;
|
break;
|
||||||
case NUMB:
|
case NUMB:
|
||||||
t = jj_consume_token(NUMB);
|
t = jj_consume_token(NUMB);
|
||||||
{if (true) return new Num(t);}
|
{if (true) return new Num(t.image);}
|
||||||
break;
|
break;
|
||||||
case LPAREN:
|
case LPAREN:
|
||||||
s = list();
|
s = list();
|
||||||
@ -42,7 +42,7 @@ public class Parser implements ParserConstants {
|
|||||||
jj_consume_token(LPAREN);
|
jj_consume_token(LPAREN);
|
||||||
s = seq();
|
s = seq();
|
||||||
jj_consume_token(RPAREN);
|
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");
|
throw new Error("Missing return statement in function");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* Generated By:JavaCC: Do not edit this line. ParserTokenManager.java */
|
/* Generated By:JavaCC: Do not edit this line. ParserTokenManager.java */
|
||||||
package edu.utexas.cs345.jdblisp.parser;
|
package edu.utexas.cs345.jdblisp.parser;
|
||||||
import edu.utexas.cs345.jdblisp.data.*;
|
import edu.utexas.cs345.jdblisp.*;
|
||||||
|
|
||||||
/** Token Manager. */
|
/** Token Manager. */
|
||||||
public class ParserTokenManager implements ParserConstants
|
public class ParserTokenManager implements ParserConstants
|
||||||
|
Loading…
x
Reference in New Issue
Block a user