-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTaoParser.cs
131 lines (130 loc) · 3.76 KB
/
TaoParser.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
using System.Collections.Generic;
public class TaoParser
{
public Tao parse(string str) {
return tao(new Input(str));
}
Tao tao(Input input) {
var tao = new Tao();
while (true) {
if (input.atBound()) return tao;
var part = tree(input);
if (part.tag == "other") {
part = op(input);
if (part.tag == "other") {
part = note(input);
}
}
tao.push(part);
}
}
Tagged tree(Input input) {
if (input.at('[')) {
input.next();
input.bound(']');
var tree = tao(input);
input.unbound();
input.next();
return new Tree(tree);
}
return new Other();
}
Tagged op(Input input) {
if (input.at('`')) {
input.next();
if (input.done()) input.error("op");
return new Op(input.next());
}
return new Other();
}
Tagged note(Input input) {
if (meta(input)) input.error("note");
string note = "" + input.next();
while (true) {
if (meta(input) || input.done()) return new Note(note);
note += input.next();
}
}
bool meta(Input input) {
return input.at('[') || input.at('`') || input.at(']');
}
public class Tagged {
public string tag {get;}
protected Tagged(string tag) {
this.tag = tag;
}
}
public class Tao: Tagged {
public List<Tagged> parts = new List<Tagged>();
public Tao(): base("tao") {}
public void push(Tagged part) {
parts.Add(part);
}
override public string ToString() {
var str = "";
foreach (Tagged p in parts) {
str += p.ToString();
}
return str;
}
}
public class Tree: Tagged {
public Tao tao {get;}
public Tree(Tao tao): base("tree") {
this.tao = tao;
}
override public string ToString() {
return "[" + tao + "]";
}
}
public class Note: Tagged {
public string note {get;}
public Note(string note): base("note") {
this.note = note;
}
override public string ToString() {
return note;
}
}
public class Op: Tagged {
public char op {get;}
public Op(char op): base("op") {
this.op = op;
}
override public string ToString() {
return "`" + op;
}
}
public class Other: Tagged {
public Other(): base("other") {}
}
class Input {
int length;
int position;
string str;
Stack<(int, char)> bounds = new Stack<(int, char)>();
public Input(string str) {
this.length = str.Length;
this.position = 0;
this.str = str;
}
public bool done() { return position >= length; }
public bool at(char symbol) { return str[position] == symbol; }
public char next() { return str[position++]; }
public void error(string name) {
throw new System.Exception("Error: malformed " + name + " at " + position);
}
public void bound(char symbol) { bounds.Push((position, symbol)); }
public void unbound() { bounds.Pop(); }
public bool atBound() {
if (bounds.Count > 0) {
var (position, symbol) = bounds.Peek();
if (done()) throw new System.Exception(
"ERROR: since " + position + " expected \"" + symbol + "\" before end of input"
);
return at(symbol);
}
return done();
}
}
}