created mirror

This commit is contained in:
whatever
2026-09-14 20:19:29 -04:00
commit 6764738d92
600 changed files with 87187 additions and 0 deletions

View File

@@ -0,0 +1,111 @@
<html>
<head>
<title>The zaubertrank applitude</title>
</head>
<body>
<h1>
The zaubertrank applitude</h1>
<div align=right><i>by Benjamin Fallenstein (<a href="mailto:b.fallenstein@gmx.de">b.fallenstein@gmx.de</a>)</i></div>
<h2>
Name issues</h2>
The zaubertrank is pronounced TSAU-ber-trunk. The name means "magic potion"
in German.
<h2>
Raison d'&ecirc;tre</h2>
"Programming for people." As
<a href="http://www.erasmatazz.com/team_bios/chris.html">Chris
Crawford</a> argues in his book
<i><a href="http://www.erasmatazz.com/book.html">Understanding
Interactivity</a></i> (2000), computers can expand our capabilities of
thought as much as the written word, but in a different direction: while
writing improved our sequential thinking (thinking in complex chains of
ideas), computers can improve what Chris calls subjunctive thinking (thinking
in many different possibilities). While the book allowed us to bring together
many different ideas, the computer program allows us to explore the countless
permutations resulting from a fixed set of rules. Instead of explaining
the effects of every single possible action to a recipient, we can write
a simulation they can experiment with.
<p>Write a simulation? We need to be able to program for that, right?
<p>The zaubertrank aims to be what the alphabet was (following Chris' line
of thought) for the Greeks: the very tool that made writing easy to learn,
that was the necessary prerequisite for a culture in which 'everybody'
(every free grown-up male) was supposed to be able to read and write. Before
the alphabet, there were thousands and thousands of signs which one needed
to know by heart in order to produce a written text, or even understand
one. Scribes where a very special class of people who had gotten a lot
of training. The alphabet reduced these signs to a small number which,
once learned, resembled the spoken language. Something people already knew.
<p>So what does the zaubertrank do? In a way, the same. The complex world
of signs and abbrevations programming languages consist of is translated
into natural language (albeit not everyday language). Sentences like "Put
the selected card on top of the stack the user clicked on" replace cryptic
formulas like "selected.put(clickStack)," formulas which need time to understand
and more time to actively write. The user doesn't enter these sentences;
that would require a natural language parser far beyond our reach. Rather,
they put it together from fragments functionally equivalent to the tokens
of a programming language: "Put (which card?) on (which stack?)," "the
selected card," and "the stack the user clicked on." This putting together
with menus and mouses also ensures that there can't be any syntax errors:
the computer won't allow the user to enter anything wrong.
<p>Will this make computer programming trivial? No, unfortunately not.
Creating a program will still be a complex task needing some thought. But
hopefully, the barriers will be lowered, the learning curve will be better,
and a program won't look as cryptic to non-programmers.
<h2>
My aim right now</h2>
In 2001, I will be teaching a course on Interactive Storytelling, which
uses the computer for interactive literary narrative. The interaction here
is not between author and reader or even different authors; rather, it's
between the reader and their computer. Stories take the form of interactive
simulations. Ever read a <i>Choose Your Own Adventure</i> book? Well, if
you imagine a more intelligent behind-the-scenes system than "flip to a
different page," you have the idea of what we'll be dealing with at first.
<p>As the people in this course won't be computer science students, I need
some good way to teach them programming easily without wasting <i>too</i>
much time on it.
<p>So right now, I'm working on a first version of the zaubertrank, which
shall be suitable for the needs of my course. The goals are: user interaction
in "turns;" relative freedom in the internal workings of the literary simulation;
easy to use for some simple structures, without the need of understanding
the internals right off; an interface showing some text and some possible
reactions (which you can click on). Of course, I need some good editing
tools for the programs, too.
<p>I want to realize this as a <a href="http://www.gzigzag.org">GZigZag</a>
applitude or <i>zone of functionality.</i> ZigZag(tm) is a new "world"
for computing, designed by
<a href="http://www.sfc.keio.ac.jp/~ted/">Ted Nelson</a>,
the inventor of computer-based hypertext. It aims to be a replacement for
the file system, for the common user interfaces, for confining structures
like lists, tables, and hierarchies, and for many other things most people
take for granted in their everyday computer use. GZigZag is a free implementation
of the system, lead by Tuomas Lukka at the University of Jyv&auml;skyl&auml;,
Finland. An applitude is to ZigZag what an application is to the common
computer world, with the difference that applitudes are combinable -- that
is, they live in the same bigger structure and can share parts of their
substructures. One way to look at applitudes is to say they're a way to
interpret a part of the structure. Applitudes can contain custom views,
that is views of the structure which look (somewhat) like the text editors
or other programs we know so well. At the same time, the underlying structure
can be viewed in generic views, which show the "bare metal" in useful ways,
so that it's easy to see how things are stored.
<p>Why, you ask, would anyone choose a completely different computer world
they have trouble explaining as the basis for a new system of computer
programming which shall function as the core of a new form of literature
they have even more trouble explaining? Well, because the trouble with
today's programming languages is not only in their cryptic syntax, but
also in the non-visibility of their inner workings. A whole mental model
needs to be build of variables, objects and so on, which can never be shown
on the screen (or only with sophisticated tools written for the classroom).
ZigZag makes this simple. If the underlying design is right, it will be
easy to show what's going on when a program is executed. Besides, once
the ZigZag model is learned, modeling otherwise complex structures in programs
will be easy, because the ZigZag model makes them easy: that's why Tuomas,
the technical leader of the GZigZag project, calls it a "hyperstructure
kit," a toolkit for creating structures beyond lists, tables, and hierarchies.
<h2>
Components I need</h2>
</body>
</html>

View File

@@ -0,0 +1,65 @@
/*
TokenTextCellView.zob
*
* Copyright (c) 2001, Benja Fallenstein
*
* You may use and distribute under the terms of either the GNU Lesser
* General Public License, either version 2 of the license or,
* at your choice, any later version. Alternatively, you may use and
* distribute under the terms of the XPL.
*
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
* the licenses.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README
* file for more details.
*
*/
/*
* Written by Benja Fallenstein
*/
package org.gzigzag;
import java.util.*;
import java.awt.*;
/** A cell view for showing (and editing) the text of a zaubertrank token.
* (This is to be used with ideosyncratic, not as the main cell view for a
* window.) The text for a token is connected to the token poswards on
* d.zt-text. Variables are recognized by them being clones. Their names are
* simply the content of the cloned cell. Thus, clones are shown with a
* different background/foreground; that's all we do to distinguish variables.
*/
public class TokenTextCellView extends FTextCellView {
public static final String rcsid = "$Id: TokenTextCellView.java,v 1.1 2001/04/01 17:45:17 bfallenstein Exp $";
public static boolean dbg = false;
private static void p(String s) { if(dbg) ZZLogger.log(s); }
private static void pa(String s) { ZZLogger.log(s); }
public static String zttext = "d.zt-text";
public static Color varbg = Color.darkGray;
public static Color varfg = Color.gray;
/** Get the FText for this cell at the given scale.
* scale == fract * 1000.
*/
protected FText getFText(ZZCell c0, int scale) {
ZZCell cells[] = c0.readRank(zttext, 1, false);
FText.Part parts[] = new FText.Part[cells.length];
for(int i=0; i<cells.length; i++) {
ZZCell c = cells[i];
if(c.getRootclone().equals(c))
parts[i] = new FText.CellPart(c, 0, -1, f(scale), fm(scale),
null, null);
else
parts[i] = new FText.CellPart(c, 0, -1, f(scale), fm(scale),
varbg, varfg);
}
return new FText(parts);
}
}

View File

@@ -0,0 +1,141 @@
/*
ZaubertrankCellView.zob
*
* Copyright (c) 2001, Benja Fallenstein
*
* You may use and distribute under the terms of either the GNU Lesser
* General Public License, either version 2 of the license or,
* at your choice, any later version. Alternatively, you may use and
* distribute under the terms of the XPL.
*
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
* the licenses.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README
* file for more details.
*
*/
/*
* Written by Benja Fallenstein
*/
package org.gzigzag;
import java.util.*;
import java.awt.*;
/** A cell view for showing one zaubertrank statement/entity/sentence etc.
* This is assembled from a number of tokens.
*/
public class ZaubertrankCellView extends FTextCellView {
public static final String rcsid = "$Id: ZaubertrankCellView.java,v 1.1 2001/04/02 20:23:13 bfallenstein Exp $";
public static boolean dbg = false;
private static void p(String s) { if(dbg) ZZLogger.log(s); }
private static void pa(String s) { ZZLogger.log(s); }
public static String zttext = "d.zt-text";
public static String ztparams = "d.zt-params", ztvalue = "d.zt-value";
public static String zttype = "d.zt-type";
/** Add the FText parts for the token at c0 to the vector. */
final void addToken(Vector v, ZZCell c0, Color bg, int scale) {
p("add token "+c0);
/** The background color to pass on to subordinate tokens.
* The background of an accursed token is the color of the cursor;
* the backgrounds of the subordinate tokens are lighter.
*/
Color newBg = bg;
// See whether there's a cursor accursing the token, and take its color.
Color col = ZZCursorReal.getAccursedColor(c0);
/* This looks awkward when the cell the cellview's called with is used.
if(col == null) {
ZZCell parcell = c0.s(ztvalue, -1);
if(parcell != null)
col = ZZCursorReal.getAccursedColor(parcell);
}
*/
if(col != null) {
bg = col;
newBg = col.brighter();
}
// Add the token's text.
for(ZZCell c = c0.getRootclone().s(zttext); c != null; c = c.s(zttext)) {
if(c.getRootclone().equals(c))
addCellPart(v, c, bg, scale);
else
addSubordinateToken(v, c0, c, newBg, scale);
}
}
final void addSubordinateToken(Vector v, ZZCell c0, ZZCell c,
Color bg, int scale) {
p("add subtoken "+c0+" "+c);
ZZCell root0 = c0.getRootclone(), root = c.getRootclone();
/** The distance between root and root0 on d.zt-params.
*/
int n = 0;
for(ZZCell d = root; d != root0; d = d.s(ztparams, -1)) {
if(d == null)
throw new SyntaxError("Found a param in a token's text which "
+ "is not on the token's params list. Token: " + c0
+ ", param: " + c);
n++;
}
ZZCell param = c0.s(ztparams, n), val = null;
if(param != null) val = param.s(ztvalue);
if(val != null)
addToken(v, val, bg, scale);
else
addTypeQuestion(v, root, param, bg, scale);
}
final void addTypeQuestion(Vector v, ZZCell root, ZZCell param,
Color bg, int scale) {
p("add type question "+root+" "+param);
if(param != null) {
Color col = ZZCursorReal.getAccursedColor(param);
if(col != null) bg = col;
}
ZZCell type = root.h(zttype, true);
if(type == null)
throw new SyntaxError("No type assigned to param: " + param);
addCellPart(v, type, bg, scale);
}
/** Get the FText for this cell at the given scale.
* scale == fract * 1000.
*/
protected FText getFText(ZZCell c0, int scale) {
ZZCell c = c0.s(ztvalue);
if(c == null) return new FText(new FText.Part[0]);
Vector v = new Vector();
addToken(v, c, null, scale);
return new FText(v);
}
/** Add a cell part to the vector of FText parts. */
final void addCellPart(Vector v, ZZCell c, Color bg, int scale) {
v.addElement(new FText.CellPart(c, 0, -1, f(scale), fm(scale),
bg, null));
}
}

View File

@@ -0,0 +1,256 @@
/*
Actions.java
*
* Copyright (c) 2000, Benjamin Fallenstein
*
* You may use and distribute under the terms of either the GNU Lesser
* General Public License, either version 2 of the license or,
* at your choice, any later version. Alternatively, you may use and
* distribute under the terms of the XPL.
*
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
* the licenses.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README
* file for more details.
*
*/
/*
* Written by Benjamin Fallenstein
*/
package org.zaubertrank;
import org.gzigzag.*;
/** Primitive actions for the Zaubertrank applitude.
*/
public class Actions {
public static final String rcsid = "$Id: Actions.java,v 1.1 2001/04/02 20:29:05 bfallenstein Exp $";
public static boolean dbg = false;
static final void p(String s) { if(dbg) System.out.println(s); }
static final void pa(String s) { System.out.println(s); }
static ZZCell getDim(ZZCell any, String id) {
return getDim(any.getSpace(), id);
}
static ZZCell getDim(ZZSpace sp, String id) {
ZZCell c = ZZDefaultSpace.findOnSystemlist(sp, "DimLists", false);
c = c.s("d.1");
if(c.t().equals(id)) return c;
ZZCell res = c.findText("d.2", 1, id);
if(res == null) { res = c.N("d.2", -1); res.setText(id); }
return res;
}
static void setDims(ZZCell win, String[] id) {
ZZSpace sp = win.getSpace();
ZZCell[] cells = new ZZCell[id.length];
for(int i=0; i<id.length; i++)
cells[i] = getDim(sp, id[i]);
ZZDefaultSpace.setDims(win, cells);
}
static ZZCell grammarCurs(ZZSpace sp) {
ZZCell c = ZZDefaultSpace.findOnSystemlist(sp, "Zaubertrank", true);
c = c.getOrNewCell("d.1");
return c;
}
static void setGrammarNode(ZZCell win) {
ZZCell curs = grammarCurs(win.getSpace());
ZZCursorReal.set(curs, ZZCursorReal.get(win));
}
static void gotoGrammarNode(ZZCell win) {
ZZCell c = grammarCurs(win.getSpace());
c = ZZCursorReal.get(c);
if(c == null) {
pa("org.zaubertrank.Actions.gotoGrammarNode failed: ");
pa("--- no grammar node set");
} else {
ZZCursorReal.set(win, c);
}
}
static ZZCell typeCurs(ZZSpace sp) {
ZZCell c = ZZDefaultSpace.findOnSystemlist(sp, "Zaubertrank", true);
c = c.getOrNewCell("d.1");
c = c.getOrNewCell("d.2");
return c;
}
static void setTypeNode(ZZCell win) {
ZZCell curs = typeCurs(win.getSpace());
ZZCursorReal.set(curs, ZZCursorReal.get(win));
}
static void gotoTypeNode(ZZCell win) {
ZZCell c = typeCurs(win.getSpace());
c = ZZCursorReal.get(c);
if(c == null) {
pa("org.zaubertrank.Actions.gotoTypeNode failed: ");
pa("--- no type node set");
} else {
ZZCursorReal.set(win, c);
}
}
static public void viewGrammarNodes(ZZCell win) {
gotoGrammarNode(win);
setDims(win, new String[] {
Parser.grammardim,
Parser.textgrammardim,
Parser.textrankdim
});
}
static public void viewTexts(ZZCell win) {
setDims(win, new String[] {
Parser.textdim,
Parser.textrankdim,
Parser.textgrammardim
});
}
static public void viewTypeNode(ZZCell win) {
setDims(win, new String[] {
Parser.textdim,
Parser.decdim,
Parser.paramdim
});
}
static public void viewDecNode(ZZCell win) {
setDims(win, new String[] {
Parser.valuedim,
Parser.paramdim,
Parser.decdim
});
}
static public void viewExpNode(ZZCell win) {
setDims(win, new String[] {
Parser.valuedim,
Parser.paramdim,
Parser.sequencedim
});
}
static public void viewSequence(ZZCell win) {
setDims(win, new String[] {
Parser.paramdim,
Parser.sequencedim,
Parser.valuedim
});
}
static public void stdView(ZZCell win) {
ZZCell home = win.getSpace().getHomeCell();
ZZCell defDims = ZZDefaultSpace.findDefaultDimlist(home);
ZZDefaultSpace.setDimsFromList(win, defDims, true);
}
static public void mkGrammarNode(ZZCell win) {
Parser.GrammarNode gn = new Parser.GrammarNode(win.getSpace());
ZZCursorReal.set(grammarCurs(win.getSpace()), gn.c);
viewGrammarNodes(win);
}
static public void mkText(ZZCell win) {
ZZCell c = ZZCursorReal.get(win);
ZZCell res = ZZCursorReal.get(grammarCurs(win.getSpace())).zzclone();
ZZCursorReal.get(win).insert(Parser.textdim, 1, res);
ZZCursorReal.set(win, res);
}
static public void mkTypeNode(ZZCell win) {
ZZCell c = ZZCursorReal.get(win).N("d.2");
ZZCursorReal.set(win, c);
ZZCursorReal.set(typeCurs(win.getSpace()), c);
}
static public void mkDecNode(ZZCell win) {
ZZCell c = ZZCursorReal.get(typeCurs(win.getSpace()));
Parser.TypeNode tn = new Parser.TypeNode(c);
Parser.DecNode dn = new Parser.DecNode(tn, "", new Parser.TypeNode[0]);
ZZCursorReal.get(win).insert("d.1", 1, dn.c);
ZZCursorReal.set(win, dn.c);
}
static public void mkExpNode(ZZCell win) {
Parser.DecNode dn = new Parser.DecNode(ZZCursorReal.get(win));
Parser.ExpNode en = new Parser.ExpNode(dn, new Parser.ExpNode[0]);
ZZCursorReal.set(win, en.c);
}
static public void mkDecRef(ZZCell win) {
ZZCell c = ZZCursorReal.get(win);
c = c.N(Parser.textrankdim);
c.setText("0");
c.connect(Parser.textgrammardim, 1,
ZZCursorReal.get(grammarCurs(win.getSpace())).zzclone());
ZZCursorReal.set(win, c);
}
static public void twoWinExp(ZZCell win) {
ZZCell other = win.s("d.ctrlview");
if(other == null) other = win.s("d.ctrlview", -1);
Parser.DecNode dn = new Parser.DecNode(ZZCursorReal.get(other));
Parser.ExpNode en = new Parser.ExpNode(dn, new Parser.ExpNode[0]);
ZZCursorReal.get(win).insert(Parser.valuedim, 1, en.c);
}
static public void remove(ZZCell win) {
ZZCell c = ZZCursorReal.get(win);
c = c.h(Parser.valuedim);
ZZCursorReal.set(win, c);
if(c.s(Parser.valuedim) != null) c.disconnect(Parser.valuedim, 1);
}
static public void move(ZZCell win, int dir) {
ZZCell c = ZZCursorReal.get(win);
if(c.s(Parser.paramdim, -1) == null) return;
c = c.s(Parser.paramdim, dir);
if(c.s(Parser.paramdim, -1) != null) ZZCursorReal.set(win, c);
}
static public void movein(ZZCell win) {
ZZCell c = ZZCursorReal.get(win);
c = c.h(Parser.valuedim, 1);
c = c.s(Parser.paramdim, 1);
if(c != null) ZZCursorReal.set(win, c);
}
static public void moveout(ZZCell win) {
ZZCell c = ZZCursorReal.get(win);
c = c.h(Parser.valuedim);
c = c.h(Parser.paramdim);
c = c.h(Parser.valuedim);
ZZCursorReal.set(win, c);
}
static public void click(ZZCell win, Flob f) {
if( !(f instanceof TokenFlob)) { p("No TkFlob"); return; }
TokenFlob tk = (TokenFlob)f;
if(tk.tkHandle == null) { p("No handle in TkFlob"); return; }
ZZCursorReal.set(win, tk.tkHandle);
}
static public void action(ZZCell win, String id, Flob f) {
if(id.equals("SETGRAMMAR")) setGrammarNode(win);
else if(id.equals("GOTOGRAMMAR")) gotoGrammarNode(win);
else if(id.equals("SETTYPE")) setTypeNode(win);
else if(id.equals("GOTOTYPE")) gotoTypeNode(win);
else if(id.equals("VIEWGRAMMAR")) viewGrammarNodes(win);
else if(id.equals("VIEWTEXTS")) viewTexts(win);
else if(id.equals("VIEWTYPE")) viewTypeNode(win);
else if(id.equals("VIEWDEC")) viewDecNode(win);
else if(id.equals("VIEWEXP")) viewExpNode(win);
else if(id.equals("VIEWSEQ")) viewSequence(win);
else if(id.equals("STDVIEW")) stdView(win);
else if(id.equals("MKGRAMMAR")) mkGrammarNode(win);
else if(id.equals("MKTEXT")) mkText(win);
else if(id.equals("MKTYPE")) mkTypeNode(win);
else if(id.equals("MKDEC")) mkDecNode(win);
else if(id.equals("MKDECREF")) mkDecRef(win);
else if(id.equals("MKEXP")) mkExpNode(win);
else if(id.equals("TWOWINEXP")) twoWinExp(win);
else if(id.equals("REMOVE")) remove(win);
else if(id.equals("MOVELEFT")) move(win, -1);
else if(id.equals("MOVERIGHT")) move(win, 1);
else if(id.equals("MOVEIN")) movein(win);
else if(id.equals("MOVEOUT")) moveout(win);
else if(id.equals("CLICK")) click(win, f);
else throw new ZZError("Unknown Zaubertrank action "+id);
}
}

View File

@@ -0,0 +1,93 @@
/*
Evaluator.java
*
* Copyright (c) 2000, Benjamin Fallenstein
*
* You may use and distribute under the terms of either the GNU Lesser
* General Public License, either version 2 of the license or,
* at your choice, any later version. Alternatively, you may use and
* distribute under the terms of the XPL.
*
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
* the licenses.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README
* file for more details.
*
*/
/*
* Written by Benjamin Fallenstein
*/
package org.zaubertrank;
import org.gzigzag.*;
import java.util.*;
/** An evaluator for zaubertrank expressions.
*/
public class Evaluator {
public static final String rcsid = "$Id: Evaluator.java,v 1.1 2001/04/02 20:29:05 bfallenstein Exp $";
public static boolean dbg = false;
static final void p(String s) { if(dbg) System.out.println(s); }
static final void pa(String s) { System.out.println(s); }
// XXX should be able to store the following in the structure for debugging
public Stack data = new Stack();
public Stack returns = new Stack();
public Stack frames = new Stack();
public Data frame;
public ZZCell pos;
public boolean failed = false;
public Evaluator(ZZCell what, Data args) {
pos = what.h("zaubertrank:rpn");
frame = args;
}
public void step() {
ZZCell root = pos.getRootclone();
Primitive p = PrimitiveSet.findPrimitive(root);
if(root == null) { // RETURN STEP -- XXX return cell in ztpart
if(returns.empty()) return;
pos = (ZZCell)returns.pop();
frame = (Data)frames.pop();
} else if(p != null) {
Object[] args = new Object[p.args()];
for(int i=args.length-1; i>=0; i--) args[i] = data.pop();
data.push(p.eval(new Data(args)));
} else if(root.s("d.zt-arg") != null) {
int nr = Data.i(root.s("d.zt-arg"));
data.push(frame.o(nr));
} else { // FUNCTION CALL! (XXX need argument reads)
throw new ZZError("Function calls aren't working yet!");
/*
Parser.DecNode dn = new Parser.DecNode(root);
Object[] args = new Object[dn.params.length];
for(int i=args.length-1; i>=0; i--) args[i] = data.pop();
returns.push(pos);
frames.push(frame);
frame = new Data(args);
pos = dn.c.h("zaubertrank:rpn"); // XXX fix
*/
}
pos = pos.s(Parser.sequencedim);
}
static public Object eval(ZZCell what, Data args) {
Evaluator e = new Evaluator(what, args);
while(e.running()) e.step();
if(e.failed) return null;
return e.data.pop();
}
public boolean running() {
return (!failed && pos != null);
}
public boolean finished() {
return (!failed && pos == null);
}
}

View File

@@ -0,0 +1,209 @@
/*
ParsedView.zob
*
* Copyright (c) 2000, Benjamin Fallenstein
*
* You may use and distribute under the terms of either the GNU Lesser
* General Public License, either version 2 of the license or,
* at your choice, any later version. Alternatively, you may use and
* distribute under the terms of the XPL.
*
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
* the licenses.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README
* file for more details.
*
*/
/*
* Written by Benjamin Fallenstein
*/
package org.zaubertrank;
import org.gzigzag.*;
import java.awt.*;
import java.util.*;
/** A view for the zaubertrank using the Parser class.
*/
public class ParsedView implements FlobView, ZOb {
public static boolean dbg = false;
static final void p(String s) { if(dbg) System.out.println(s); }
static final void pa(String s) { System.out.println(s); }
STRUCTPARAMS {
/** The font to use. */
Font font
= new Font("SansSerif", Font.PLAIN, 16);
ZOb ftextlayouter
= new FTextLayouter();
/** Whether to mark the accursed part. */
boolean mark
= false;
int xmargin
= 8;
int ymargin
= 2;
int yspace
= 10;
}
FontMetrics fm;
INITIALIZE {
fm = FONTMETRICS(font);
}
static class TokenPart extends FText.CellPart {
int tkNumber;
ZZCell tkHandle;
public TokenPart(ZZCell c, int offs, int n, Font f, FontMetrics fm,
Color bg, Color fg, int tkNumber, ZZCell tkHandle) {
super(c, offs, n, f, fm, bg, fg);
this.tkNumber = tkNumber;
this.tkHandle = tkHandle;
}
public FText.Part subpart(int first, int last) {
return new TokenPart(c, offs+first, last-first, f, this.fm,
bg, fg, tkNumber, tkHandle);
}
public Renderable rend(int x, int y, int d, Renderable prev0) {
TokenFlob prev = null, parent = null, res;
p("SimpleView.TokenPart.rend prev "+prev0);
if(prev0 instanceof TokenFlob) {
prev = (TokenFlob)prev0;
if(prev.c != this.c) prev = null;
else if(prev.parent != null) parent = (TokenFlob)prev.parent;
else parent = prev;
}
p("SimpleView.TokenPart.rend found prev "+prev+" -- parent "+parent);
res = new TokenFlob(x, y, d, width(), height(),
c, s, f, this.fm, parent, offs, n, bg, tkHandle);
if(prev != null) res.setPrev(prev);
if(parent == null) res.tkNumber = tkNumber;
p("SimpleView.TokenPart nr "+tkNumber+" has nr "+res.tkNumber+" rend: "+res);
return res;
}
}
FText.Part make(ZZCell c, int number, ZZCell tkHandle,
ZZCell view) {
Color bg = null;
if(mark && tkHandle.equals(ZZCursorReal.get(view)))
bg = ZZCursorReal.getColor(view);
Color fg = Color.black;
return new TokenPart(c, 0, -1, font, fm, bg, fg, number, tkHandle);
}
FText.Part make(String s) {
return new FText.StringPart(s, font, fm, null, Color.black);
}
void getParts(Vector v, Parser.TypeRef tr, TokenGrouper g, int parent,
ZZCell tkHandle, ZZCell view) {
int number = g.addToken(parent);
ZZCell[] text = tr.getText();
if(text == null) { v.addElement(make("<type without text>")); return; }
v.addElement(make("["));
for(int i=0; i<text.length; i++)
v.addElement(make(text[i], number, tkHandle, view));
v.addElement(make("?]"));
}
void getParts(Vector v, Parser.ExpRef er, TokenGrouper g, int parent,
ZZCell view) {
int number = g.addToken(parent);
Object[] text = er.getText();
for(int i=0; i<text.length; i++) {
Object o = text[i];
if(o instanceof ZZCell) {
v.addElement(make((ZZCell)o, number, er.e.c, view));
} else if(o instanceof Parser.ExpRef) {
Parser.ExpRef sub_er = (Parser.ExpRef)o;
ZZCell sub_c = sub_er.e.c;
getParts(v, sub_er, g, number, view);
} else if(o instanceof Parser.TypeRef) {
getParts(v, (Parser.TypeRef)o, g, number, er.e.c, view); // XXX tkHandle
} else
throw new ZZError("ARGH! strange type in ExpRef.getText");
}
}
public void place(FlobSet into, Parser.ExpNode en, Rectangle rect,
TokenGrouper grp, Parser.GrammarNode gn, int dir,
ZZCell view, int[] inits) {
int number = grp.addToken(-1);
Vector parts = new Vector();
Parser.ExpRef er = new Parser.ExpRef(en, gn);
getParts(parts, er, grp, -1, view);
parts.addElement(make(". "));
FText ftxt = new FText(parts);
boolean[] beginningSentence = new boolean[2];
beginningSentence[0] = true;
beginningSentence[1] = false;
int starty;
if(dir <= 0) starty = inits[0];
else starty = inits[1];
Rectangle res =
((FTextLayouter)ftextlayouter).place(into, ftxt, rect, 1,
dir, starty,
FText.Part.len(ftxt.parts)/2,
false, beginningSentence);
int xm = xmargin+3, ym = ymargin+3;
into.add(new CellBgFlob(res.x-xm, res.y-ym, 2, res.width+xm+xm,
res.height+ym+ym, en.c));
if(dir <= 0) inits[0] = res.y - 2*ym - yspace - 6;
if(dir >= 0) inits[1] = res.y + res.height + 2*ym + yspace + 6;
}
public void raster(FlobSet into, FlobFactory fact,
ZZCell view, String[] dims, ZZCell accursed) {
ZZCell c = accursed;
while(c.h(Parser.paramdim) != c ||
c.h(Parser.valuedim) != c) {
c = c.h(Parser.paramdim);
c = c.h(Parser.valuedim);
}
TokenGrouper grp = new TokenGrouper();
Parser.GrammarNode gn = new Parser.GrammarNode(
view.getSpace().getHomeCell().s(Parser.grammardim));
Parser.ExpNode en = new Parser.ExpNode(c);
Dimension size = into.getSize();
Rectangle rect = new Rectangle(xmargin, ymargin, size.width-2*xmargin,
size.height-2*ymargin);
int[] inits = new int[2];
inits[0] = (inits[1] = rect.y + rect.height/2);
place(into, en, rect, grp, gn, 0, view, inits);
for(Parser.ExpNode en0 = en.step(-1);
en0 != null && inits[0] > rect.y;
en0 = en0.step(-1)) {
place(into, en0, rect, grp, gn, -1, view, inits);
}
for(Parser.ExpNode en1 = en.step(1);
en1 != null && inits[1] < rect.y+rect.height;
en1 = en1.step(1)) {
place(into, en1, rect, grp, gn, 1, view, inits);
}
grp.group(into);
}
}
// vim: set syntax=java :

View File

@@ -0,0 +1,275 @@
/*
Parser.java
*
* Copyright (c) 2000, Benjamin Fallenstein
*
* You may use and distribute under the terms of either the GNU Lesser
* General Public License, either version 2 of the license or,
* at your choice, any later version. Alternatively, you may use and
* distribute under the terms of the XPL.
*
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
* the licenses.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README
* file for more details.
*
*/
/*
* Written by Benjamin Fallenstein
*/
package org.zaubertrank;
import org.gzigzag.*;
import java.util.*;
/** A parser for zaubertrank programs.
* Currently micro-level: the biggest structure recognized is one statement.
*/
public class Parser {
public static final String rcsid = "$Id: Parser.java,v 1.1 2001/04/02 20:29:05 bfallenstein Exp $";
public static boolean dbg = false;
static final void p(String s) { if(dbg) System.out.println(s); }
static final void pa(String s) { System.out.println(s); }
static Object NULL = new Object();
static public final String paramdim = "d.2"; // parameter list dim
static public final String valuedim = "d.1";
static public final String recorddim = "d.1";
static public final String sequencedim = "d.zaubertrank-list";
static public final String textdim = "d.zaubertrank-txt-alt";
static public final String textrankdim = "d.2";
static public final String textgrammardim = "d.1";
static public final String grammardim = "d.zaubertrank-grammar-list";
static public final String decdim = "d.zaubertrank-declarations";
/** A reference to an ExpNode param in a certain grammatical form. */
static public final class DecRef {
int i;
GrammarNode g;
public DecRef(int i, GrammarNode g) { this.i = i; this.g = g; }
}
/** A reference to a certain ExpNode in a certain grammatical form.
* The difference to DecRef is that DecRef contains only a param number
* and a GrammarNode; additionally, an ExpNode is needed to read the
* actual text.
*/
static public final class ExpRef {
ExpNode e;
GrammarNode g;
public ExpRef(ExpNode e, GrammarNode g) { this.e = e; this.g = g; }
public Object[] getText() { return e.getText(g); }
}
static public final class TypeRef {
TypeNode t;
GrammarNode g;
public TypeRef(TypeNode t, GrammarNode g) { this.t = t; this.g = g; }
public ZZCell[] getText() { return t.getText(g); }
}
static public class Node {
public ZZCell c;
public boolean equals(Node other) { return c.equals(other.c); }
}
/** A node declaring a grammatical way to utter a type.
* Example: English noun ("the person" // "which person?")
* Example: English statement ("the ball is red" // "what is true?")
* Example: English genitive ("the person's" // "whose?")
* etc.
*/
static public class GrammarNode extends Node {
public GrammarNode(ZZCell c) {
this.c = c.getRootclone();
if(!this.c.h(grammardim).equals(this.c.getSpace().getHomeCell()))
throw new ZZError("Attempt to create GrammarNode from " +
"non-grammar cell "+this.c);
}
public GrammarNode(ZZSpace sp) {
this.c = sp.getHomeCell().N(grammardim, 1);
}
}
static ZZCell[] readText(ZZCell c, GrammarNode g) {
ZZCell root = c.intersect(textdim, 1, g.c, "d.clone", 1);
p("Parse intersect "+c+" and "+g.c+" gives "+root);
if(root == null) return null;
return root.readRank(textrankdim, 1, false);
}
static void writeText(ZZCell c, GrammarNode g, ZZCell[] tc) {
ZZCell here = g.c.zzclone();
c.insert(textdim, 1, here);
for(int i=0; i<tc.length; i++) {
here.insert(textrankdim, 1, tc[i]);
here = tc[i];
}
}
/** A node declaring a data type. */
static public class TypeNode extends Node {
public TypeNode(ZZCell c) { this.c = c.getRootclone(); }
public TypeNode(ZZSpace sp) { this.c = sp.getHomeCell().N(); }
public ZZCell[] getText(GrammarNode g) {
return readText(c, g);
}
public void setText(GrammarNode g, ZZCell[] tc) {
writeText(c, g, tc);
}
}
/** A node declaring a variable or a function of a data type. */
static public class DecNode extends Node {
TypeNode type;
TypeNode[] params;
/** Create from structure */
public DecNode(ZZCell c) {
this.c = c;
type = new TypeNode(c.h(decdim));
ZZCell[] pcells = c.readRank(paramdim, 1, false);
params = new TypeNode[pcells.length];
for(int i=0; i<pcells.length; i++)
params[i] = new TypeNode(pcells[i]);
}
/** Create anew, to put into the structure */
public DecNode(TypeNode type, String title, TypeNode params[]) {
this.type = type;
c = type.c.N(decdim);
if(title != null) c.setText(title);
ZZCell here = c;
for(int i=0; i<params.length; i++) {
ZZCell there = params[i].c.zzclone();
here.insert(paramdim, 1, there);
here = there;
}
}
/** Read the text for a given GrammarNode.
* Returns an Object[] array where the Objects are either ZZCells
* (which contain a piece of the text) or DecRef instances containing
* an int and a GrammarNode as reference to a param.
*/
public Object[] getText(GrammarNode g) {
ZZCell[] rank = readText(c, g);
if(rank == null) return null;
Object[] res = new Object[rank.length];
for(int i=0; i<rank.length; i++) {
ZZCell gr = rank[i].s(textgrammardim, 1);
if(gr == null) res[i] = rank[i];
else res[i] = new DecRef(Integer.parseInt(rank[i].t()),
new GrammarNode(gr));
}
return res;
}
/** Write the text for a given GrammarNode.
* Returns an Object[] array where the Objects are either ZZCells
* (which contain a piece of the text) or DecRef instances containing
* an int and a GrammarNode as reference to a param.
*/
public void setText(GrammarNode g, Object[] text) {
ZZCell[] rank = new ZZCell[text.length];
for(int i=0; i<text.length; i++) {
if(text[i] instanceof ZZCell) rank[i] = (ZZCell)text[i];
else if(text[i] instanceof DecRef) {
DecRef ref = (DecRef)text[i];
rank[i] = c.N();
rank[i].setText(""+ref.i);
rank[i].connect(textgrammardim, 1, ref.g.c.zzclone());
} else
throw new ZZError("Strange object: "+text[i]);
}
writeText(c, g, rank);
}
}
/** A node representing an expression.
* An expression consists of a reference to a DecNode (which references
* a data type), and references to ExpNodes as parameters.
*/
static class ExpNode extends Node {
public ExpNode[] params;
public DecNode dec;
/** Create from structure */
public ExpNode(ZZCell c) {
this.c = c;
dec = new DecNode(c.getRootclone());
int i = 0;
for(ZZCell var=c.s(paramdim); var!=null; var=var.s(paramdim)) {
i++;
}
params = new ExpNode[i];
i = 0;
for(ZZCell var=c.s(paramdim); var!=null; var=var.s(paramdim)) {
ZZCell val = var.s(valuedim);
if(val != null) params[i] = new ExpNode(val);
i++;
}
}
/** Create anew, to put into the structure */
public ExpNode(DecNode dec, ExpNode[] params) {
this.dec = dec;
this.params = new ExpNode[dec.params.length];
System.arraycopy(params, 0, this.params, 0, params.length);
c = dec.c.zzclone();
ZZCell here = c;
for(int i=0; i<dec.params.length; i++) {
here = here.N(paramdim);
if(i >= params.length || params[i] == null) continue;
if(params[i].c.s(valuedim, -1) != null)
params[i].c.disconnect(valuedim, -1);
here.connect(valuedim, 1, params[i].c);
}
}
/** Change a param in the structure. */
public void setParam(int nr, ExpNode val) {
ZZCell var = c.getOrNewCell(paramdim, nr+1);
if(var.s(valuedim) != null) var.disconnect(valuedim, 1);
if(val.c.s(valuedim, -1) != null) val.c.disconnect(valuedim, -1);
var.connect(valuedim, 1, val.c);
}
/** Read the text for a given GrammarNode.
* Returns an Object[] array where the Objects are ZZCells
* (which contain a piece of the text) ExpRef objects, or TypeRef
* objects.
* <br>
* NOTE: there is no corresponding setText function because the
* text is deducted from params[] and dec.getText().
*/
public Object[] getText(GrammarNode g) {
Object[] res = dec.getText(g);
if(res == null) return null;
for(int i=0; i<res.length; i++) {
if(res[i] instanceof DecRef) {
DecRef ref = (DecRef)res[i];
if(params[ref.i] != null)
res[i] = new ExpRef(params[ref.i], ref.g);
else
res[i] = new TypeRef(dec.params[ref.i], ref.g);
}
}
return res;
}
/** Step through a sequence (list) of expression nodes. */
public ExpNode step(int steps) {
ZZCell c0 = c.s(sequencedim, steps);
if(c0 == null) return null;
return new ExpNode(c0);
}
}
}

View File

@@ -0,0 +1,43 @@
/*
Primitive.java
*
* Copyright (c) 2000, Ted Nelson and Tuomas Lukka
* Copyright (c) 2000-2001, Benjamin Fallenstein
*
* You may use and distribute under the terms of either the GNU Lesser
* General Public License, either version 2 of the license or,
* at your choice, any later version. Alternatively, you may use and
* distribute under the terms of the XPL.
*
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
* the licenses.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README
* file for more details.
*
*/
/*
* Written by Benjamin Fallenstein
*/
package org.zaubertrank;
import org.gzigzag.*;
/** A primitive for use in the zaubertrank.
*/
public abstract class Primitive {
String rcsid = "$Id: Primitive.java,v 1.1 2001/04/02 20:29:05 bfallenstein Exp $";
// In subclasses, override one of the following two:
protected Object eval(Data params) { return null; }
public Object eval(Data params, ZZSpace space) {
return eval(params);
}
public abstract int args();
}

View File

@@ -0,0 +1,78 @@
/*
PrimitiveSet.java
*
* Copyright (c) 2000, Ted Nelson and Tuomas Lukka
* Copyright (c) 2001, Benjamin Fallenstein
*
* You may use and distribute under the terms of either the GNU Lesser
* General Public License, either version 2 of the license or,
* at your choice, any later version. Alternatively, you may use and
* distribute under the terms of the XPL.
*
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
* the licenses.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README
* file for more details.
*
*/
/*
* Written by Tuomas Lukka (for Heraclitus Clang)
*/
package org.zaubertrank;
import org.gzigzag.*;
import java.util.*;
/** A set of Zaubertrank primitives.
*/
public abstract class PrimitiveSet {
String rcsid = "$Id: PrimitiveSet.java,v 1.1 2001/04/02 20:29:05 bfallenstein Exp $";
public abstract Primitive get(String id);
static Hashtable pss = new Hashtable();
static PrimitiveSet findPrimitiveSet(String set) {
Object o = pss.get(set);
if(o != null) return (PrimitiveSet)o;
try {
o = Class.forName("org.gzigzag.flowing."+set).newInstance();
} catch(Exception e) {
ZZLogger.exc(e);
return null;
}
if(!(o instanceof PrimitiveSet)) return null;
pss.put(set, o);
return (PrimitiveSet)o;
}
static Hashtable prims = new Hashtable();
static Primitive findPrimitive(String s) {
Object o = prims.get(s);
if(o != null) return (Primitive)o;
int ind = s.indexOf(".");
if(ind < 0) return null;
String set = s.substring(0, ind);
String id = s.substring(ind+1);
PrimitiveSet ps = findPrimitiveSet(set);
Primitive prim = ps.get(id);
if(prim != null)
prims.put(id, prim);
return prim;
}
public static Primitive findPrimitive(ZZCell c0) {
ZZCell c = c0.getRootclone();
c = c.s("d.zaubertrank-primitive-binding");
if(c == null) return null;
if(!c.h("d.zaubertrank-primitives").equals(
c.getSpace().getHomeCell()))
throw new ZZError("Zaubertrank primitive not enumerated on " +
"d.zaubertrank-primitives rank from home cell!");
return findPrimitive(c.t());
}
}

View File

@@ -0,0 +1,137 @@
/*
SimpleView.java
*
* Copyright (c) 2000, Benjamin Fallenstein
*
* You may use and distribute under the terms of either the GNU Lesser
* General Public License, either version 2 of the license or,
* at your choice, any later version. Alternatively, you may use and
* distribute under the terms of the XPL.
*
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
* the licenses.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README
* file for more details.
*
*/
/*
* Written by Benjamin Fallenstein
*/
package org.zaubertrank;
import org.gzigzag.*;
import java.awt.*;
import java.util.*;
/** A simple view just showing a structure as text.
*/
public class SimpleView implements FlobView, ZOb {
public static boolean dbg = true;
static final void p(String s) { if(dbg) System.out.println(s); }
static final void pa(String s) { System.out.println(s); }
STRUCTPARAMS {
/** The font to use. */
Font font
= new Font("SansSerif", Font.PLAIN, 16);
ZOb ftextlayouter
= new FTextLayouter();
}
FontMetrics fm;
INITIALIZE {
fm = FONTMETRICS(font);
}
static class TokenPart extends FText.CellPart {
int tkNumber;
public TokenPart(ZZCell c, int offs, int n, Font f, FontMetrics fm,
Color bg, Color fg, int tkNumber) {
super(c, offs, n, f, fm, bg, fg);
this.tkNumber = tkNumber;
}
public FText.Part subpart(int first, int last) {
return new TokenPart(c, offs+first, last-first, f, this.fm,
bg, fg, tkNumber);
}
public Renderable rend(int x, int y, int d, Renderable prev0) {
TokenFlob prev = null, parent = null, res;
p("SimpleView.TokenPart.rend prev "+prev0);
if(prev0 instanceof TokenFlob) {
prev = (TokenFlob)prev0;
if(prev.c != this.c) prev = null;
else if(prev.parent != null) parent = (TokenFlob)prev.parent;
else parent = prev;
}
p("SimpleView.TokenPart.rend found prev "+prev+" -- parent "+parent);
res = new TokenFlob(x, y, d, width(), height(),
c, s, f, this.fm, parent, offs, n, bg, c);
if(prev != null) res.setPrev(prev);
if(parent == null) res.tkNumber = tkNumber;
p("SimpleView.TokenPart nr "+tkNumber+" has nr "+res.tkNumber+" rend: "+res);
return res;
}
}
FText.Part make(ZZCell c, int number) {
return new TokenPart(c, 0, -1, font, fm, null, Color.black, number);
}
FText.Part make(String s) {
return new FText.StringPart(s, font, fm, null, Color.black);
}
Vector getPart(ZZCell c, TokenGrouper g, int parent) {
Vector v = new Vector();
ZZCell tx = c.getRootclone(), var = c.s("d.2");
if(tx.equals(c)) {
v.addElement(make(c, g.addToken(parent)));
return v;
}
int number = g.addToken(parent);
for(tx = tx.s("d.2"); tx != null; tx = tx.s("d.2")) {
ZZCell type = tx.getRootclone();
if(type.equals(tx))
v.addElement(make(tx, number));
else {
ZZCell val;
if(var == null || (val=var.s("d.1")) == null) {
v.addElement(make("["));
v.addElement(make(type.s("d.2"), g.addToken(number)));
v.addElement(make("?]"));
} else {
v.addElement(make("("));
Vector w = getPart(val, g, number);
for(Enumeration e = w.elements();
e.hasMoreElements();) {
v.addElement(e.nextElement());
}
v.addElement(make(")"));
}
if(var != null) var = var.s("d.2");
}
}
return v;
}
public void raster(FlobSet into, FlobFactory fact,
ZZCell view, String[] dims, ZZCell accursed) {
TokenGrouper grp = new TokenGrouper();
FText ftxt = new FText(getPart(accursed, grp, -1));
Dimension size = into.getSize();
Rectangle rect = new Rectangle(0, 0, size.width, size.height);
((FTextLayouter)ftextlayouter).place(into, ftxt, rect,
0, rect.y+rect.height/2,
FText.Part.len(ftxt.parts)/2,
false, null); // XXX use firstcap
grp.group(into);
}
}
// vim: set syntax=java :

View File

@@ -0,0 +1,78 @@
/*
TokenFlob.java
*
* Copyright (c) 2000, Benjamin Fallenstein
*
* You may use and distribute under the terms of either the GNU Lesser
* General Public License, either version 2 of the license or,
* at your choice, any later version. Alternatively, you may use and
* distribute under the terms of the XPL.
*
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
* the licenses.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README
* file for more details.
*
*/
/*
* Written by Benjamin Fallenstein
*/
package org.zaubertrank;
import org.gzigzag.*;
import java.awt.*;
/** A SplitCellFlob1 showing a Zaubertrank token.
* This is an own class in order to get the XOR highlighting right.
*/
public class TokenFlob extends SplitCellFlob1 {
public static final String rcsid = "$Id: TokenFlob.java,v 1.1 2001/04/02 20:29:05 bfallenstein Exp $";
public static boolean dbg = false;
static final void p(String s) { if(dbg) System.out.println(s); }
static final void pa(String s) { System.out.println(s); }
// tk for 'token.'
public TokenFlob tkParent, tkFirstChild, tkNextChild;
public TokenFlob tkNextPart, tkFirstPart;
public int tkNumber = -1;
public ZZCell tkHandle;
public void setTkParent(TokenFlob parent) {
tkParent = parent;
tkNextChild = parent.tkFirstChild;
parent.tkFirstChild = this;
}
public void setTkFirstPart(TokenFlob first) {
tkFirstPart = first;
tkNextPart = first.tkNextPart;
first.tkNextPart = this;
}
TokenFlob(int x, int y, int d, int w, int h, ZZCell c, String txt, Font f,
FontMetrics fm, SplitCellFlob1 parent, int start, int n, Color bg,
ZZCell tkHandle) {
super(x, y, d, w, h, c, txt, f, fm, parent, start, n, bg);
this.bg = bg;
this.tkHandle = tkHandle;
tkFirstPart = this;
}
public void renderChildrenXOR(Graphics g) {
for(TokenFlob tk = tkFirstChild; tk != null; tk = tk.tkNextChild) {
tk.renderXORFrame(g, false, false);
tk.renderChildrenXOR(g);
}
}
public boolean renderXOR(Graphics g, int cx, int cy) {
if(!insideRect(cx, cy)) return false;
tkFirstPart.renderChildrenXOR(g);
for(TokenFlob tk = tkFirstPart; tk != null; tk = tk.tkNextPart)
tk.renderXORSolid(g);
return true;
}
}

View File

@@ -0,0 +1,81 @@
/*
TokenGrouper.java
*
* Copyright (c) 2000, Benjamin Fallenstein
*
* You may use and distribute under the terms of either the GNU Lesser
* General Public License, either version 2 of the license or,
* at your choice, any later version. Alternatively, you may use and
* distribute under the terms of the XPL.
*
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
* the licenses.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README
* file for more details.
*
*/
/*
* Written by Benjamin Fallenstein
*/
package org.zaubertrank;
import org.gzigzag.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
/** A class to group TokenFlobs into their hierarchies.
*/
public class TokenGrouper {
public static final String rcsid = "$Id: TokenGrouper.java,v 1.1 2001/04/02 20:29:05 bfallenstein Exp $";
public static boolean dbg = false;
static final void p(String s) { if(dbg) System.out.println(s); }
static final void pa(String s) { System.out.println(s); }
private int ntoks = 0;
private Vector parents = new Vector();
public int addToken(int parent) {
parents.addElement(new Integer(parent));
p("TokenGroup cur "+ntoks+" parent "+parent);
return ntoks++; // i.e., return ntoks and after, increment one
}
public void group(final FlobSet into) {
final TokenFlob[] toks = new TokenFlob[ntoks];
if(dbg) into.dump();
into.iterDepth(new FlobSet.DepthIter() {
public void act(Flob[] flobs, int start, int n) {
for(int f = start; f<start+n; f++) {
Flob cur = flobs[f];
p("TokenGroup found flob "+cur);
if(!(cur instanceof TokenFlob)) continue;
TokenFlob tf = (TokenFlob)cur;
if(tf.tkNumber >= 0) {
if(toks[tf.tkNumber] == null)
toks[tf.tkNumber] = tf;
else
tf.setTkFirstPart(toks[tf.tkNumber]);
}
p("...is TokenFlob "+tf.tkNumber);
}
}}, false);
int child = 0;
for(Enumeration e = parents.elements(); e.hasMoreElements();) {
int parent = ((Integer)e.nextElement()).intValue();
p("TokenGroup connect parent "+parent+" child "+child);
if(parent >= 0 && toks[child] != null && toks[parent] != null)
toks[child].setTkParent(toks[parent]);
child++;
}
}
}
// vim: set syntax=java :

View File

@@ -0,0 +1,54 @@
/*
Zaubertrank.java
*
* Copyright (c) 2000, Benjamin Fallenstein
*
* You may use and distribute under the terms of either the GNU Lesser
* General Public License, either version 2 of the license or,
* at your choice, any later version. Alternatively, you may use and
* distribute under the terms of the XPL.
*
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
* the licenses.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README
* file for more details.
*
*/
/*
* Written by Benjamin Fallenstein
*/
package org.gzigzag.module;
import org.gzigzag.*;
import java.awt.*;
/** The module for the Zaubertrank applitude.
*/
public class Zaubertrank {
public static final String rcsid = "$Id: Zaubertrank.java,v 1.1 2001/04/02 20:29:05 bfallenstein Exp $";
public static boolean dbg = false;
static final void p(String s) { if(dbg) System.out.println(s); }
static final void pa(String s) { System.out.println(s); }
static public ZZModule module = new ZZModule() {
public void action(String id,
ZZCell code,
ZZCell target,
ZZView view, ZZView cview, String key, Point pt, ZZScene xi) {
Flob[] flob = new Flob[1];
if(pt != null) ((FlobSet)xi).getObjectAt(pt.x, pt.y, flob);
org.zaubertrank.Actions.action(view.getViewcell(), id, flob[0]);
}
public ZOb newZOb(String id) {
if(id.equals("Simple"))
return new org.zaubertrank.SimpleView();
else if(id.equals("Parsed"))
return new org.zaubertrank.ParsedView();
return null;
}
};
}

View File

@@ -0,0 +1,216 @@
/*
ZaubertrankPart.java
*
* Copyright (c) 2000, Benjamin Fallenstein
*
* You may use and distribute under the terms of either the GNU Lesser
* General Public License, either version 2 of the license or,
* at your choice, any later version. Alternatively, you may use and
* distribute under the terms of the XPL.
*
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
* the licenses.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README
* file for more details.
*
*/
/*
* Written by Benjamin Fallenstein
*/
package org.zaubertrank;
import org.gzigzag.*;
import java.util.*;
/** A spacepart for the zaubertrank.
* Currently connects tokens in Reverse Polish Notation, and has cells whose
* content is the computed result of a Zaubertrank function.
*/
public class ZaubertrankPart extends ZZROSpacePart {
public static final String rcsid = "$Id: ZaubertrankPart.java,v 1.1 2001/04/02 20:29:05 bfallenstein Exp $";
public static boolean dbg = false;
private static final void p(String s) { if(dbg) System.out.println(s); }
private static final void pa(String s) { System.out.println(s); }
public ZaubertrankPart(ZZSpace space, String id) {
super(space, id);
}
public static class Result {
String codeID;
int nr;
public Result(String c, int nr) { codeID = c; this.nr = nr; }
}
public Object parseIDPart(String idPart) {
if(idPart.substring(0, 7).equals("result-")) {
String rest = idPart.substring(7);
int idx = rest.indexOf("-");
if(idx < 0 || idx+1 == rest.length()) return null;
String nr = rest.substring(0, idx);
String codeID = rest.substring(idx+1);
try {
return new Result(codeID, Integer.parseInt(nr));
} catch(NumberFormatException e) {
return null;
}
} else
return null;
}
public String generateIDPart(Object parsed) {
if(parsed instanceof Result) {
Result r = (Result)parsed;
return "result-" + r.nr + "-" + r.codeID;
} else
throw new ZZError("Not a ZaubertrankPart parsed ID object!");
}
public String getText(ZZCellHandle c) {
if(c.parsedID instanceof Result) {
Result r = (Result)c.parsedID;
ZZCell code = space.getCellByID(r.codeID);
pa("code "+code);
Object res;
try {
res = Evaluator.eval(code, new Data(c));
} catch(Throwable t) {
// ZZLogger.exc(t);
return t.getMessage();
}
return Data.s(res);
} else
return "";
}
public ZZDimension getDim(String name) {
if(name.equals("result")) return new ResultDimension();
else if(name.equals("rpn")) return new ReversePolishNotation();
return null;
}
public class ResultDimension extends ZZRODimension {
public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) {
Result r = null;
if(c.parsedID instanceof Result) r = (Result)c.parsedID;
if(r == null) {
if(steps <= 0) return null;
r = new Result(c.getID(), steps);
return (ZZCellHandle)space.getCellByID(ZaubertrankPart.this,
generateID(r), r);
} else {
r = new Result(r.codeID, r.nr + steps);
if(r.nr < 0) return null;
else if(r.nr == 0)
return (ZZCellHandle)space.getCellByID(r.codeID);
else
return (ZZCellHandle)space.getCellByID(ZaubertrankPart.this,
generateID(r), r);
}
}
}
public static ZZCell parent(ZZCell c, ZZObs o) throws SyntaxError {
c = c.s(Parser.valuedim, -1, o);
if(c == null) return null;
c = c.h(Parser.paramdim, -1, true, o);
if(c == null) throw new SyntaxError("Not connected to parent!");
return c;
}
private static ZZCell sibling(ZZCell c, int dir, ZZObs o)
throws SyntaxError {
c = c.s(Parser.valuedim, -1, o);
if(c == null) return null; // XXX syntax error? has no siblings at all!
c = c.s(Parser.paramdim, dir, o);
if(dir < 0 && c == null) throw new SyntaxError("was parent already");
else if(dir > 0 && c == null) return null;
// i.e., this was the last sibling
else if(dir < 0 && c.s(Parser.paramdim, -1, o) == null) return null;
// i.e., this was the first sibling
c = c.s(Parser.valuedim, 1, o);
if(c == null) throw new MissingTermError("Term's missing");
return c;
}
public static ZZCell prevSibling(ZZCell c, ZZObs o) throws SyntaxError {
return sibling(c, -1, o);
}
public static ZZCell nextSibling(ZZCell c, ZZObs o) throws SyntaxError {
return sibling(c, 1, o);
}
public static ZZCell firstChild(ZZCell c, ZZObs o) throws SyntaxError {
c = c.s(Parser.paramdim, 1, o);
if(c == null) return null;
c = c.s(Parser.valuedim, 1, o);
if(c == null) throw new MissingTermError("Term's missing");
return c;
}
public static ZZCell lastChild(ZZCell c, ZZObs o) throws SyntaxError {
c = c.h(Parser.paramdim, 1, true, o);
if(c == null) return null;
c = c.s(Parser.valuedim, 1, o);
if(c == null) throw new MissingTermError("Term's missing");
return c;
}
public static ZZCell firstDescendant(ZZCell c, ZZObs o) throws SyntaxError {
LoopDetector l = new LoopDetector();
ZZCell d = c;
while(true) {
d = firstChild(c, o);
if(d == null) return c;
c = d;
l.detect(c);
}
}
public static ZZCell rpnPrev(ZZCell c, ZZObs o) throws SyntaxError {
ZZCell d = lastChild(c, o);
if(d != null) return d;
LoopDetector l = new LoopDetector();
while(true) {
d = prevSibling(c, o);
if(d != null) return d;
l.detect(c);
c = parent(c, o);
if(c == null) return null;
}
}
public static ZZCell rpnNext(ZZCell c, ZZObs o) throws SyntaxError {
ZZCell d = nextSibling(c, o);
if(d == null) return parent(c, o);
else return firstDescendant(d, o);
}
public class ReversePolishNotation extends ZZRODimension {
public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) {
// Sanity check: can this be a tree node?
if(c.s(Parser.valuedim, 1, o) != null) return null;
if(c.s(Parser.paramdim, -1, o) != null) return null;
// Until we have syntax error cells, let the errors be throws.
// try {
if(steps > 0)
for(int i=0; i<steps; i++)
c = (ZZCellHandle)rpnNext(c, o);
else
for(int i=0; i>steps; i--)
c = (ZZCellHandle)rpnPrev(c, o);
// Another sanity check
if(c != null && (c.s(Parser.valuedim, 1, o) != null ||
c.s(Parser.paramdim, -1, o) != null))
throw new SyntaxError("Target not a tree node!");
return c;
// } catch(SyntaxError e) {
// ZZLogger.exc(e);
// return null;
// }
}
}
}