1 module pry.grammar.printer;
2 
3 import pry.grammar.ast;
4 import std.stdio, std.conv, std.format;
5 
6 class PrettyPrinter : Visitor {
7 	string modToString(Modifier mod) {
8 		if(mod.min == 1 && mod.max == 1)
9 			return "";
10 		if(mod.min == 0 && mod.max == 1)
11 			return "?";
12 		if(mod.min == 0 && mod.max == uint.max)
13 			return "*";
14 		if(mod.min == 1 && mod.max == uint.max)
15 			return "+";
16 		return format("{%d,%d}", mod.min, mod.max);
17 	}
18 
19 	override void visit(Grammar grammar) {
20 		writefln("%s:", grammar.name);
21 		foreach(d; grammar.defs)
22 			d.accept(this);
23 	}
24 
25 	override void visit(Definition def) {
26 		string type = def.type == "" ? "" : format(": %s", def.type);
27 		writef("%s %s <- ", def.name, type);
28 		def.ast.accept(this);
29 		writeln();
30 	}
31 
32 	override void visit(Sequence seq) {
33 		foreach(ast; seq.seq) ast.accept(this);
34 	}
35 
36 	override void visit(Alternative alt) {
37 		writef("%s(", alt.ignored ? ":" : "");
38 		foreach(i, ast; alt.alt) {
39 			if(i != 0) write(" / ");
40 			ast.accept(this);
41 		}
42 		writef(")%s", modToString(alt.mod));
43 	}
44 
45 	override void visit(Map map) {
46 		map.ast.accept(this);
47 		writef("%s", map.code);
48 	}
49 
50 	override void visit(NegativeLookahead neg) {
51 		write("!");
52 		neg.ast.accept(this);
53 	}
54 
55 	override void visit(PositiveLookahead pos) {
56 		write("&");
57 		pos.ast.accept(this);
58 	}
59 
60 	override void visit(SimpleSequence seq) {
61 		writef("%s", seq.ignored ? ":" : "");
62 		foreach(ast; seq.seq)
63 			ast.accept(this);
64 	}
65 
66 	override void visit(CharClass charClass) {
67 		writef("%s%s%s", charClass.ignored ? ":" : "",
68 			to!string(charClass.set), modToString(charClass.mod));
69 	}
70 
71 	override void visit(Literal literal) {
72 		writef("%s'%s'%s", literal.ignored ?  "^" : "", literal.lit,
73 			modToString(literal.mod));
74 	}
75 
76 	override void visit(Reference reference) {
77 		writef("%s%s%s", reference.ignored ?  ":" : "", reference.name,
78 			modToString(reference.mod));
79 	}
80 
81 	override void visit(Combinator combinator) {
82 		writef("$%s(", combinator.combinator);
83 		foreach(i, arg; combinator.args) {
84 			if(i != 0) write(",");
85 			arg.accept(this);
86 		}
87 		write(")");
88 	}
89 }
90 
91 void prettyPrint(Grammar grammar) {
92 	auto pp = new PrettyPrinter();
93 	grammar.accept(pp);
94 }