blob: 5debe00daf97378879a60d51eac4f354bda6e1bd (
plain)
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
package bjc.dicelang;
import bjc.utils.funcdata.FunctionalList;
import bjc.utils.funcdata.IList;
import bjc.utils.funcutils.ListUtils;
import static bjc.dicelang.Errors.ErrorKey.*;
import bjc.utils.esodata.SingleTape;
import bjc.utils.esodata.Tape;
import bjc.utils.esodata.TapeLibrary;
/**
* Implements multiple interleaved parse streams, as well as a command language
* for the streams.
*
* The idea for the interleaved streams came from the language Oozylbub &
* Murphy, but the command language was my own idea.
*
* @author Ben Culkin
*/
public class StreamEngine {
/*
* The engine we're attached to.
*/
private DiceLangEngine eng;
/*
* Our streams.
*/
private Tape<IList<String>> streams;
private IList<String> currStream;
/*
* Saved streams
*/
private TapeLibrary<IList<String>> savedStreams;
/**
* Create a new stream engine.
*
* @param engine The dice engine we're attached to.
*/
public StreamEngine(DiceLangEngine engine) {
eng = engine;
savedStreams = new TapeLibrary<>();
}
private void init() {
/*
* Reinitialize our list of streams.
*/
streams = new SingleTape<>();
/*
* Create an initial stream.
*/
currStream = new FunctionalList<>();
streams.insertBefore(currStream);
}
/**
* Process a possibly interleaved set of streams from toks into dest.
*
* @param toks The raw token to read streams from.
* @param dest The list to write the final stream to.
*
* @return Whether or not the streams were successfully processed.
*/
public boolean doStreams(String[] toks, IList<String> dest) {
/*
* Initialize per-run state.
*/
init();
/*
* Are we currently quoting things?
*/
boolean quoteMode = false;
/*
* Process each token.
*/
for(String tk : toks) {
/*
* Process stream commands.
*/
if(tk.startsWith("{@S") && !quoteMode) {
if(tk.equals("{@SQ}")) {
quoteMode = true;
} else if(!processCommand(tk)) {
return false;
}
/*
* Command ran correctly, continue
*/
} else {
if(tk.equals("{@SU}")) {
quoteMode = false;
} else if(tk.startsWith("\\") && tk.endsWith("{@SU}")) {
currStream.add(tk.substring(1));
} else {
currStream.add(tk);
}
}
}
for(String tk : currStream) {
dest.add(tk);
}
return true;
}
private boolean processCommand(String tk) {
char[] comms = null;
if(tk.length() > 5) {
comms = tk.substring(3, tk.length() - 1).toCharArray();
} else {
comms = new char[1];
comms[0] = tk.charAt(3);
}
for(char comm : comms) {
switch(comm) {
case '+':
streams.insertAfter(new FunctionalList<>());
break;
case '>':
if(!streams.right()) {
Errors.inst.printError(EK_STRM_NONEX);
return false;
}
currStream = streams.item();
break;
case '<':
if(!streams.left()) {
Errors.inst.printError(EK_STRM_NONEX);
return false;
}
currStream = streams.item();
break;
case '-':
if(streams.size() == 1) {
Errors.inst.printError(EK_STRM_LAST);
return false;
} else {
streams.remove();
currStream = streams.item();
}
break;
case 'S':
if(streams.size() == 1) {
Errors.inst.printError(EK_STRM_LAST);
return false;
} else {
IList<String> stringLit = streams.remove();
currStream = streams.item();
currStream.add(ListUtils.collapseTokens(stringLit, " "));
}
break;
default:
Errors.inst.printError(EK_STRM_INVCOM, tk);
return false;
}
}
return true;
}
}
|