57 int g_NumStates = 0; |
57 int g_NumStates = 0; |
58 int g_NumEvents = 0; |
58 int g_NumEvents = 0; |
59 int g_CurMode = MODE_TOPLEVEL; |
59 int g_CurMode = MODE_TOPLEVEL; |
60 str g_CurState = ""; |
60 str g_CurState = ""; |
61 bool g_stateSpawnDefined = false; |
61 bool g_stateSpawnDefined = false; |
|
62 bool g_GotMainLoop = false; |
62 |
63 |
63 void ScriptReader::BeginParse (ObjWriter* w) { |
64 void ScriptReader::BeginParse (ObjWriter* w) { |
64 bool gotMainLoop = false; |
|
65 while (Next()) { |
65 while (Next()) { |
66 // printf ("got token %s\n", token.chars()); |
66 // printf ("got token %s\n", token.chars()); |
67 if (!token.icompare ("#include")) { |
67 if (!token.icompare ("#include")) { |
68 MustString (); |
68 MustString (); |
69 |
69 |
93 g_stateSpawnDefined = true; |
93 g_stateSpawnDefined = true; |
94 |
94 |
95 // Must end in a colon |
95 // Must end in a colon |
96 MustNext (":"); |
96 MustNext (":"); |
97 |
97 |
98 // If the previous state did not define a mainloop, |
98 // Write the previous state's onenter and |
99 // define a dummy one now, since one has to be present. |
99 // mainloop buffers to file now |
100 if (g_CurState.len() && !gotMainLoop) { |
100 if (g_CurState.len()) |
101 w->Write (DH_MAINLOOP); |
101 w->WriteBuffers(); |
102 w->Write (DH_ENDMAINLOOP); |
|
103 } |
|
104 |
102 |
105 w->Write (DH_STATENAME); |
103 w->Write (DH_STATENAME); |
106 w->WriteString (statename); |
104 w->WriteString (statename); |
107 w->Write (DH_STATEIDX); |
105 w->Write (DH_STATEIDX); |
108 w->Write (g_NumStates); |
106 w->Write (g_NumStates); |
109 |
107 |
110 g_NumStates++; |
108 g_NumStates++; |
111 g_CurState = token; |
109 g_CurState = token; |
112 gotMainLoop = false; |
110 g_GotMainLoop = false; |
113 continue; |
111 continue; |
114 } |
112 } |
115 |
113 |
116 if (!token.icompare ("event")) { |
114 if (!token.icompare ("event")) { |
117 MUST_TOPLEVEL |
115 MUST_TOPLEVEL |
134 } |
132 } |
135 |
133 |
136 if (!token.icompare ("mainloop")) { |
134 if (!token.icompare ("mainloop")) { |
137 MUST_TOPLEVEL |
135 MUST_TOPLEVEL |
138 MustNext ("{"); |
136 MustNext ("{"); |
|
137 |
|
138 // Mode must be set before dataheader is written here! |
139 g_CurMode = MODE_MAINLOOP; |
139 g_CurMode = MODE_MAINLOOP; |
140 w->Write (DH_MAINLOOP); |
140 w->Write (DH_MAINLOOP); |
141 gotMainLoop = true; |
|
142 continue; |
141 continue; |
143 } |
142 } |
144 |
143 |
145 if (!token.icompare ("onenter") || !token.icompare ("onexit")) { |
144 if (!token.icompare ("onenter") || !token.icompare ("onexit")) { |
146 MUST_TOPLEVEL |
145 MUST_TOPLEVEL |
147 bool onenter = !token.compare ("onenter"); |
146 bool onenter = !token.compare ("onenter"); |
148 |
|
149 MustNext ("{"); |
147 MustNext ("{"); |
|
148 |
|
149 // Mode must be set before dataheader is written here, |
|
150 // because onenter goes to a separate buffer. |
150 g_CurMode = onenter ? MODE_ONENTER : MODE_ONEXIT; |
151 g_CurMode = onenter ? MODE_ONENTER : MODE_ONEXIT; |
151 w->Write (onenter ? DH_ONENTER : DH_ONEXIT); |
152 w->Write (onenter ? DH_ONENTER : DH_ONEXIT); |
152 continue; |
153 continue; |
153 } |
154 } |
154 |
155 |
182 (g_CurMode == MODE_ONEXIT) ? DH_ENDONEXIT : -1; |
183 (g_CurMode == MODE_ONEXIT) ? DH_ENDONEXIT : -1; |
183 |
184 |
184 if (dataheader == -1) |
185 if (dataheader == -1) |
185 ParserError ("unexpected `}`"); |
186 ParserError ("unexpected `}`"); |
186 |
187 |
187 // Closing brace.. |
188 // Data header must be written before mode is changed because |
|
189 // onenter and mainloop go into buffers, and we want the closing |
|
190 // data headers into said buffers too. |
188 w->Write (dataheader); |
191 w->Write (dataheader); |
189 g_CurMode = MODE_TOPLEVEL; |
192 g_CurMode = MODE_TOPLEVEL; |
190 |
193 |
191 MustNext (";"); |
194 MustNext (";"); |
192 continue; |
195 continue; |
196 if (g) { |
199 if (g) { |
197 // Not in top level, unfortunately.. |
200 // Not in top level, unfortunately.. |
198 if (g_CurMode == MODE_TOPLEVEL) |
201 if (g_CurMode == MODE_TOPLEVEL) |
199 ParserError ("can't alter variables at top level"); |
202 ParserError ("can't alter variables at top level"); |
200 |
203 |
201 // Only addition for now.. |
|
202 MustNext (); |
|
203 |
|
204 // Build operator string. Only '=' is one |
204 // Build operator string. Only '=' is one |
205 // character, others are two. |
205 // character, others are two. |
|
206 MustNext (); |
206 str oper = token; |
207 str oper = token; |
207 if (token.compare ("=") != 0) { |
208 if (token.compare ("=") != 0) { |
208 MustNext (); |
209 MustNext (); |
209 oper += token; |
210 oper += token; |
210 } |
211 } |
259 |
260 |
260 // stateSpawn must be defined! |
261 // stateSpawn must be defined! |
261 if (!g_stateSpawnDefined) |
262 if (!g_stateSpawnDefined) |
262 ParserError ("script must have a state named `stateSpawn`!"); |
263 ParserError ("script must have a state named `stateSpawn`!"); |
263 |
264 |
264 // If the last state did not have a main loop, define a dummy one now. |
265 |
265 if (!gotMainLoop) { |
266 |
266 w->Write (DH_MAINLOOP); |
267 // Dump the last state's onenter and mainloop |
267 w->Write (DH_ENDMAINLOOP); |
268 w->WriteBuffers(); |
268 } |
|
269 |
269 |
270 // If we added strings here, we need to write a list of them. |
270 // If we added strings here, we need to write a list of them. |
271 unsigned int stringcount = CountStringTable (); |
271 unsigned int stringcount = CountStringTable (); |
272 if (stringcount) { |
272 if (stringcount) { |
273 w->Write<long> (DH_STRINGLIST); |
273 w->Write<long> (DH_STRINGLIST); |