54 |
54 |
55 int g_NumStates = 0; |
55 int g_NumStates = 0; |
56 int g_NumEvents = 0; |
56 int g_NumEvents = 0; |
57 int g_CurMode = MODE_TOPLEVEL; |
57 int g_CurMode = MODE_TOPLEVEL; |
58 str g_CurState = ""; |
58 str g_CurState = ""; |
|
59 bool g_stateSpawnDefined = false; |
59 |
60 |
60 void ScriptReader::BeginParse (ObjWriter* w) { |
61 void ScriptReader::BeginParse (ObjWriter* w) { |
|
62 bool gotMainLoop = false; |
61 while (Next()) { |
63 while (Next()) { |
62 // printf ("got token %s\n", token.chars()); |
64 // printf ("got token %s\n", token.chars()); |
63 if (!token.compare ("#include")) { |
65 if (!token.compare ("#include")) { |
64 MustString (); |
66 MustString (); |
65 |
67 |
76 MustString (); |
78 MustString (); |
77 |
79 |
78 // State name must be a word. |
80 // State name must be a word. |
79 if (token.first (" ") != token.len()) |
81 if (token.first (" ") != token.len()) |
80 ParserError ("state name must be a single word! got `%s`", token.chars()); |
82 ParserError ("state name must be a single word! got `%s`", token.chars()); |
|
83 str statename = token; |
|
84 |
|
85 // stateSpawn is special - it *must* be defined. If we |
|
86 // encountered it, then mark down that we have it. |
|
87 if (!token.icompare ("stateSpawn")) |
|
88 g_stateSpawnDefined = true; |
81 |
89 |
82 // Must end in a colon |
90 // Must end in a colon |
83 MustNext (":"); |
91 MustNext (":"); |
84 |
92 |
|
93 // If the previous state did not define a mainloop, |
|
94 // define a dummy one now, since one has to be present. |
|
95 if (g_CurState.compare ("") != 0 && !gotMainLoop) { |
|
96 w->Write (DH_MAINLOOP); |
|
97 w->Write (DH_ENDMAINLOOP); |
|
98 } |
|
99 |
85 w->Write (DH_STATENAME); |
100 w->Write (DH_STATENAME); |
86 w->Write (token.len()); |
101 w->Write (statename.len()); |
87 w->WriteString (token); |
102 w->WriteString (statename); |
88 w->Write (DH_STATEIDX); |
103 w->Write (DH_STATEIDX); |
89 w->Write (g_NumStates); |
104 w->Write (g_NumStates); |
90 |
105 |
91 g_NumStates++; |
106 g_NumStates++; |
92 g_CurState = token; |
107 g_CurState = token; |
|
108 gotMainLoop = false; |
93 } else if (!token.compare ("event")) { |
109 } else if (!token.compare ("event")) { |
94 MUST_TOPLEVEL |
110 MUST_TOPLEVEL |
95 |
111 |
96 // Event definition |
112 // Event definition |
97 MustString (); |
113 MustString (); |
105 g_CurMode = MODE_EVENT; |
121 g_CurMode = MODE_EVENT; |
106 |
122 |
107 w->Write (DH_EVENT); |
123 w->Write (DH_EVENT); |
108 w->Write<long> (e->number); |
124 w->Write<long> (e->number); |
109 g_NumEvents++; |
125 g_NumEvents++; |
|
126 } else if (!token.compare ("mainloop")) { |
|
127 MUST_TOPLEVEL |
|
128 MustNext ("{"); |
|
129 g_CurMode = MODE_MAINLOOP; |
|
130 w->Write (DH_MAINLOOP); |
|
131 gotMainLoop = true; |
|
132 } else if (!token.compare ("onenter") || !token.compare ("onexit")) { |
|
133 MUST_TOPLEVEL |
|
134 bool onenter = !token.compare ("onenter"); |
|
135 |
|
136 MustNext ("{"); |
|
137 g_CurMode = onenter ? MODE_ONENTER : MODE_ONEXIT; |
|
138 w->Write (onenter ? DH_ONENTER : DH_ONEXIT); |
110 } else if (!token.compare ("}")) { |
139 } else if (!token.compare ("}")) { |
|
140 // Closing brace |
|
141 int dataheader = (g_CurMode == MODE_EVENT) ? DH_ENDEVENT : |
|
142 (g_CurMode == MODE_MAINLOOP) ? DH_ENDMAINLOOP : |
|
143 (g_CurMode == MODE_ONENTER) ? DH_ENDONENTER : |
|
144 (g_CurMode == MODE_ONEXIT) ? DH_ENDONEXIT : -1; |
|
145 |
|
146 if (dataheader == -1) |
|
147 ParserError ("unexpected `}`"); |
|
148 |
111 // Closing brace.. |
149 // Closing brace.. |
112 switch (g_CurMode) { |
150 w->Write (dataheader); |
113 case MODE_EVENT: |
151 g_CurMode = MODE_TOPLEVEL; |
114 // Brace closes event. |
|
115 w->Write (DH_ENDEVENT); |
|
116 g_CurMode = MODE_TOPLEVEL; |
|
117 break; |
|
118 default: |
|
119 ParserError ("unexpected `}`"); |
|
120 } |
|
121 } else { |
152 } else { |
122 // Check if it's a command. |
153 // Check if it's a command. |
123 CommandDef* comm = GetCommandByName (token); |
154 CommandDef* comm = GetCommandByName (token); |
124 if (comm) |
155 if (comm) |
125 ParseCommand (comm, w); |
156 ParseCommand (comm, w); |
127 ParserError ("unknown keyword `%s`!", token.chars()); |
158 ParserError ("unknown keyword `%s`!", token.chars()); |
128 } |
159 } |
129 } |
160 } |
130 |
161 |
131 if (g_CurMode != MODE_TOPLEVEL) |
162 if (g_CurMode != MODE_TOPLEVEL) |
132 ParserError ("script did not end at top level! did you forget a `}`?\n"); |
163 ParserError ("script did not end at top level! did you forget a `}`?"); |
|
164 |
|
165 // stateSpawn must be defined! |
|
166 if (!g_stateSpawnDefined) |
|
167 ParserError ("script must have a state named `stateSpawn`!"); |
133 |
168 |
134 /* |
169 /* |
135 // State |
170 // State |
136 w->WriteState ("stateSpawn"); |
171 w->WriteState ("stateSpawn"); |
137 |
172 |
149 w->Write (DH_ENDEVENT); |
184 w->Write (DH_ENDEVENT); |
150 */ |
185 */ |
151 } |
186 } |
152 |
187 |
153 void ScriptReader::ParseCommand (CommandDef* comm, ObjWriter* w) { |
188 void ScriptReader::ParseCommand (CommandDef* comm, ObjWriter* w) { |
|
189 // If this was defined at top-level, we stop right at square one! |
|
190 if (g_CurMode == MODE_TOPLEVEL) |
|
191 ParserError ("no commands allowed at top level!"); |
|
192 |
154 w->Write<long> (DH_COMMAND); |
193 w->Write<long> (DH_COMMAND); |
155 w->Write<long> (comm->number); |
194 w->Write<long> (comm->number); |
156 w->Write<long> (comm->maxargs); |
195 w->Write<long> (comm->maxargs); |
157 MustNext ("("); |
196 MustNext ("("); |
158 int curarg = 0; |
197 int curarg = 0; |