public abstract class Atom<T extends Token> extends Element implements Topology<T> {
protected abstract Topology<T> top();
+ public abstract String toString();
public Topology toAtom() { return this; }
- /** equality is based on the underlying <tt>Topology</tt> */
- public int hashCode() { return top().hashCode(); }
-
- /** equality is based on the underlying <tt>Topology</tt> */
- public boolean equals(Object o) { return o != null && o instanceof Atom && ((Atom)o).top().equals(top()); }
-
- /** declared abstract to force subclasses to override it in a useful manner */
- public abstract String toString();
-
// Topology Thunks //////////////////////////////////////////////////////////////////////////////
- public Topology<T> unwrap() { return top().unwrap(); }
+ public Topology<T> unwrap() { return top().unwrap(); }
public Topology<T> empty() { return top().empty(); }
public boolean contains(T v) { return top().contains(v); }
public Topology<T> intersect(Topology<T> t) { return top().intersect(t); }
public Topology<T> complement() { return top().complement(); }
public boolean disjoint(Topology<T> t) { return top().disjoint(t); }
public boolean containsAll(Topology<T> t) { return top().containsAll(t); }
+ public int hashCode() { return top().hashCode(); }
+ public boolean equals(Object o) { return o != null && o instanceof Atom && ((Atom)o).top().equals(top()); }
// Subclasses //////////////////////////////////////////////////////////////////////////////
static <T> Forest<T> singleton(Token.Location loc, Sequence creator) { return create(loc, null, new Forest[] { }, creator, false, true); }
static <T> Forest<T> singleton(Token.Location loc, Forest<T> body, Sequence creator) { return create(loc, null, new Forest[] { body }, creator, false, true); }
static <T> Forest<T> leaf(Token.Location loc, T tag, Sequence creator) { return create(loc, tag, null, creator, false, false); }
- static <T> Forest<T> create(Token.Location loc, T tag, Forest<T>[] tokens, Sequence creator, boolean unwrap, boolean singleton) {
+ public static <T> Forest<T> create(Token.Location loc, T tag, Forest<T>[] tokens, Sequence creator, boolean unwrap, boolean singleton) {
return new MultiForest<T>(loc, tag, tokens, creator, unwrap, singleton);
}
}
/** perform all shift operations, adding promoted nodes to <tt>next</tt> */
- public void shift(Phase next) {
+ public void shift(Phase next, Forest result) {
closed = true;
Forest res = null;
boolean ok = false;
if (!n.holder.valid()) continue;
if (token == null) continue;
for(Parser.Table.State st : n.state.getShifts(token)) {
- if (res == null) res = Forest.create(token.getLocation(), token.result(), null, null, false, false);
+ if (res == null) res = result;
next.newNode(n, res, st, true, this);
ok = true;
}
import java.lang.reflect.*;
/** a parser which translates streams of Tokens of type T into a Forest<R> */
-public class Parser<T extends Token, R> {
+public abstract class Parser<T extends Token, R> {
private final Table pt;
if (p.element() != null) reachable(p.element(), h);
}
- //public Parser( Topology top) { this(new Table( top)); }
- //public Parser(String s, Topology top) { this(new Table(s, top)); }
-
/**
* create a parser to parse the grammar with start symbol <tt>u</tt>
- * @param top a "sample" Topology<T> that can be cloned (FIXME, demanding this is lame)
*/
- public Parser(Union u, Topology<T> top) { this(new Table(u, top)); }
+ protected Parser(Union u) { this.pt = new Table(u, top()); }
+ protected Parser(Table pt) { this.pt = pt; }
+
+ public abstract Forest<R> shiftedToken(T t);
+ public abstract Topology<T> top();
- Parser(Table pt) { this.pt = pt; }
/** parse <tt>input</tt> for a exactly one unique result, throwing <tt>Ambiguous</tt> if not unique or <tt>Failed</tt> if none */
public Tree<R> parse1(Token.Stream<T> input) throws IOException, Failed, Ambiguous { return parse(input).expand1(); }
for(;;) {
GSS.Phase next = gss.new Phase(current, input.next());
current.reduce();
- current.shift(next);
+ Forest forest = current.token==null ? null : shiftedToken((T)current.token);
+ current.shift(next, forest);
if (current.isDone()) return (Forest<R>)current.finalResult;
current.checkFailure();
current = next;
// Table //////////////////////////////////////////////////////////////////////////////
+ static class Top extends Union { public Top() { super("0"); } }
+
/** an SLR(1) parse table which may contain conflicts */
static class Table {
private final Union start0 = new Top();
private final Sequence start0seq;
- static class Top extends Union { public Top() { super("0"); } }
public final Walk.Cache cache = new Walk.Cache();
/** a token of input -- note that this represents an <i>actual input token</i> rather than an <tt>Element</tt> which <i>matches</i> a token */
public interface Token {
- // FIXME!!! remove this
- /** converts this <tt>Token</tt> into a standalone result (ie for a non-rewriting pattern) */
- public String result();
-
/** this is declared abstract as a way of forcing subclasses to provide a thoughtful implementation */
public abstract String toString();
eof = false;
cs = cso.empty();
- if (e instanceof Parser.Table.Top) eof = true;
+ if (e instanceof Parser.Top) eof = true;
for(Element x : all) {
boolean matched = false;
- if (x instanceof Parser.Table.Top) walk(x); // because this symbol might not appear in any other Sequence
+ if (x instanceof Parser.Top) walk(x); // because this symbol might not appear in any other Sequence
if (!(x instanceof Sequence)) continue;
Sequence a = (Sequence)x;
Position mp = null;
// Public //////////////////////////////////////////////////////////////////////////////
+ public static class CharToStringParser extends Parser<CharToken,String> {
+ public CharToStringParser(Union u) { super(u); }
+ public Topology<CharToken> top() { return new IntegerTopology<CharToken>(); }
+ public Forest<String> shiftedToken(CharToken ct) {
+ return Forest.create(ct.getLocation(), ct.result(), null, null, false, false);
+ }
+ }
+
public static class CharRange extends Atom<CharToken> {
private String esc(char c) { return StringUtil.escapify(c+"", "[]-~\\\"\'"); }
private Topology<CharToken> t;
}
out.append("\n // DO NOT EDIT STUFF BELOW: IT IS AUTOMATICALLY GENERATED\n");
- new Parser(MetaGrammar.make(), CharToken.top()).parse1(new CharToken.Stream(new InputStreamReader(new FileInputStream(args[0])))).toJava(out);
+ new CharToken.CharToStringParser(MetaGrammar.make()).parse1(new CharToken.Stream(new InputStreamReader(new FileInputStream(args[0])))).toJava(out);
out.append("\n // DO NOT EDIT STUFF ABOVE: IT IS AUTOMATICALLY GENERATED\n");
for(String s = br.readLine(); s != null; s = br.readLine()) out.append(s+"\n");
//MetaGrammar mg0 = new MetaGrammar();
//mg0.walk(MetaGrammar.meta);
//System.out.println(mg0);
- Tree<String> res = new Parser(MetaGrammar.make(), CharToken.top()).parse1(new CharToken.Stream(new InputStreamReader(new FileInputStream(s[0]))));
+ Tree<String> res = new CharToken.CharToStringParser(MetaGrammar.make()).parse1(new CharToken.Stream(new InputStreamReader(new FileInputStream(s[0]))));
MetaGrammar mg = (MetaGrammar)new MetaGrammar().walk(res);
//System.out.println(mg);
Union meta = mg.done();
SequenceInputStream sis = new SequenceInputStream(new FileInputStream(s[0]), new FileInputStream(s[1]));
- res = new Parser(meta, CharToken.top()).parse1(new CharToken.Stream(new InputStreamReader(sis), "parsing " + s[1] + " using " + s[0]));
+ res = new CharToken.CharToStringParser(meta).parse1(new CharToken.Stream(new InputStreamReader(sis), "parsing " + s[1] + " using " + s[0]));
Union testcasegrammar = ((MetaGrammar)new MetaGrammar("ts").walk(res)).done("ts");
if (testcasegrammar==null) return;
CharToken.Stream cs = new CharToken.Stream(new InputStreamReader(new FileInputStream(s[2])), "parsing " + s[2] + " using " + s[1]);
- Parser parser = new Parser(testcasegrammar, CharToken.top());
+ Parser parser = new CharToken.CharToStringParser(testcasegrammar);
if (profile) {
System.out.println("\nready...");
return ret;
}
public boolean execute() throws Exception {
- Forest<String> res = new Parser(grammar, CharToken.top()).parse(inp);
+ Forest<String> res = new CharToken.CharToStringParser(grammar).parse(inp);
Collection<Tree<String>> results = res==null ? new HashSet<Tree<String>>() : res.expand(false);
System.out.print("\r");
if (results.size() == 0 && output.length > 0) {
public static void main(String[] s) throws Exception {
System.out.println("parsing " + s[0]);
- Tree<String> res = new Parser(MetaGrammar.make(), CharToken.top()).parse1(new CharToken.Stream(new FileInputStream(s[0])));
+ Tree<String> res = new CharToken.CharToStringParser(MetaGrammar.make()).parse1(new CharToken.Stream(new FileInputStream(s[0])));
MetaGrammar gram = (MetaGrammar)new Tib.Grammar().walk(res);
//System.out.println(gram);
Union mg = gram.done();
System.out.println("\nparsing " + s[1]);
- res = new Parser(mg, CharToken.top()).parse1(new Tib(new FileInputStream(s[1])));
+ res = new CharToken.CharToStringParser(mg).parse1(new Tib(new FileInputStream(s[1])));
System.out.println(res);
}