1 /* |
|
2 Copyright 2012-2014 Santeri Piippo |
|
3 All rights reserved. |
|
4 |
|
5 Redistribution and use in source and binary forms, with or without |
|
6 modification, are permitted provided that the following conditions |
|
7 are met: |
|
8 |
|
9 1. Redistributions of source code must retain the above copyright |
|
10 notice, this list of conditions and the following disclaimer. |
|
11 2. Redistributions in binary form must reproduce the above copyright |
|
12 notice, this list of conditions and the following disclaimer in the |
|
13 documentation and/or other materials provided with the distribution. |
|
14 3. The name of the author may not be used to endorse or promote products |
|
15 derived from this software without specific prior written permission. |
|
16 |
|
17 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
|
18 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
|
19 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
|
20 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
|
21 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
|
22 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
23 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
|
26 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
27 */ |
|
28 |
|
29 #ifndef BOTC_PARSER_H |
|
30 #define BOTC_PARSER_H |
|
31 |
|
32 #include <stdio.h> |
|
33 #include "main.h" |
|
34 #include "commands.h" |
|
35 #include "lexer_scanner.h" |
|
36 #include "tokens.h" |
|
37 |
|
38 #define MAX_SCOPE 32 |
|
39 #define MAX_CASE 64 |
|
40 #define MAX_MARKS 512 // TODO: get rid of this |
|
41 |
|
42 class data_buffer; |
|
43 class lexer; |
|
44 class script_variable; |
|
45 |
|
46 struct undefined_label |
|
47 { |
|
48 string name; |
|
49 byte_mark* target; |
|
50 }; |
|
51 |
|
52 // ============================================================================ |
|
53 // Operators |
|
54 // |
|
55 enum operator_e |
|
56 { |
|
57 OPER_ADD, |
|
58 OPER_SUBTRACT, |
|
59 OPER_MULTIPLY, |
|
60 OPER_DIVIDE, |
|
61 OPER_MODULUS, |
|
62 OPER_ASSIGN, |
|
63 OPER_ASSIGNADD, |
|
64 OPER_ASSIGNSUB, |
|
65 OPER_ASSIGNMUL, |
|
66 OPER_ASSIGNDIV, |
|
67 OPER_ASSIGNMOD, // -- 10 |
|
68 OPER_EQUALS, |
|
69 OPER_NOTEQUALS, |
|
70 OPER_LESSTHAN, |
|
71 OPER_GREATERTHAN, |
|
72 OPER_LESSTHANEQUALS, |
|
73 OPER_GREATERTHANEQUALS, |
|
74 OPER_LEFTSHIFT, |
|
75 OPER_RIGHTSHIFT, |
|
76 OPER_ASSIGNLEFTSHIFT, |
|
77 OPER_ASSIGNRIGHTSHIFT, // -- 20 |
|
78 OPER_OR, |
|
79 OPER_AND, |
|
80 OPER_BITWISEOR, |
|
81 OPER_BITWISEAND, |
|
82 OPER_BITWISEEOR, |
|
83 OPER_TERNARY, |
|
84 OPER_STRLEN, |
|
85 }; |
|
86 |
|
87 // ============================================================================ |
|
88 // |
|
89 struct operator_info |
|
90 { |
|
91 operator_e opercode; |
|
92 e_data_header dataheader; |
|
93 e_token token; |
|
94 }; |
|
95 |
|
96 // ============================================================================ |
|
97 // Mark types |
|
98 // |
|
99 enum marktype_e |
|
100 { |
|
101 e_label_mark, |
|
102 e_if_mark, |
|
103 e_internal_mark, // internal structures |
|
104 }; |
|
105 |
|
106 // ============================================================================ |
|
107 // Scope types |
|
108 // |
|
109 enum scopetype_e |
|
110 { |
|
111 e_unknown_scope, |
|
112 e_if_scope, |
|
113 e_while_scope, |
|
114 e_for_scope, |
|
115 e_do_scope, |
|
116 e_switch_scope, |
|
117 e_else_scope, |
|
118 }; |
|
119 |
|
120 // ============================================================================ |
|
121 // Meta-data about scopes |
|
122 // |
|
123 struct ScopeInfo |
|
124 { |
|
125 byte_mark* mark1; |
|
126 byte_mark* mark2; |
|
127 scopetype_e type; |
|
128 data_buffer* buffer1; |
|
129 |
|
130 // switch-related stuff |
|
131 // Which case are we at? |
|
132 int casecursor; |
|
133 |
|
134 // Marks to case-blocks |
|
135 byte_mark* casemarks[MAX_CASE]; |
|
136 |
|
137 // Numbers of the case labels |
|
138 int casenumbers[MAX_CASE]; |
|
139 |
|
140 // actual case blocks |
|
141 data_buffer* casebuffers[MAX_CASE]; |
|
142 |
|
143 // What is the current buffer of the block? |
|
144 data_buffer* recordbuffer; |
|
145 }; |
|
146 |
|
147 // ============================================================================ |
|
148 // |
|
149 struct constant_info |
|
150 { |
|
151 string name; |
|
152 type_e type; |
|
153 string val; |
|
154 }; |
|
155 |
|
156 // ============================================================================ |
|
157 // |
|
158 class botscript_parser |
|
159 { |
|
160 public: |
|
161 // ==================================================================== |
|
162 // METHODS |
|
163 botscript_parser(); |
|
164 ~botscript_parser(); |
|
165 void parse_botscript (string file_name); |
|
166 data_buffer* parse_command (command_info* comm); |
|
167 data_buffer* parse_expression (type_e reqtype); |
|
168 data_buffer* parse_assignment (script_variable* var); |
|
169 int parse_operator (bool peek = false); |
|
170 data_buffer* parse_expr_value (type_e reqtype); |
|
171 string parse_float(); |
|
172 void push_scope(); |
|
173 data_buffer* parse_statement(); |
|
174 void add_switch_case (data_buffer* b); |
|
175 void check_toplevel(); |
|
176 void check_not_toplevel(); |
|
177 bool token_is (e_token a); |
|
178 string token_string(); |
|
179 string describe_position() const; |
|
180 void write_to_file (string outfile); |
|
181 |
|
182 inline int get_num_events() const |
|
183 { |
|
184 return m_num_events; |
|
185 } |
|
186 |
|
187 inline int get_num_states() const |
|
188 { |
|
189 return m_num_states; |
|
190 } |
|
191 |
|
192 private: |
|
193 // The lexer we're using. |
|
194 lexer* m_lx; |
|
195 |
|
196 // The main buffer - the contents of this is what we |
|
197 // write to file after parsing is complete |
|
198 data_buffer* m_main_buffer; |
|
199 |
|
200 // onenter buffer - the contents of the onenter{} block |
|
201 // is buffered here and is merged further at the end of state |
|
202 data_buffer* m_on_enter_buffer; |
|
203 |
|
204 // Mainloop buffer - the contents of the mainloop{} block |
|
205 // is buffered here and is merged further at the end of state |
|
206 data_buffer* m_main_loop_buffer; |
|
207 |
|
208 // Switch buffer - switch case data is recorded to this |
|
209 // buffer initially, instead of into main buffer. |
|
210 data_buffer* m_switch_buffer; |
|
211 |
|
212 int m_num_states; |
|
213 int m_num_events; |
|
214 parsermode_e m_current_mode; |
|
215 string m_current_state; |
|
216 bool m_state_spawn_defined; |
|
217 bool m_got_main_loop; |
|
218 int m_scope_cursor; |
|
219 data_buffer* m_if_expression; |
|
220 bool m_can_else; |
|
221 list<undefined_label> m_undefined_labels; |
|
222 list<constant_info> m_constants; |
|
223 |
|
224 // How many bytes have we written to file? |
|
225 int m_num_written_bytes; |
|
226 |
|
227 // Scope data |
|
228 // TODO: make a list |
|
229 ScopeInfo m_scope_stack[MAX_SCOPE]; |
|
230 |
|
231 data_buffer* buffer(); |
|
232 constant_info* find_constant (const string& tok); |
|
233 void parse_state_block(); |
|
234 void parse_event_block(); |
|
235 void parse_mainloop(); |
|
236 void parse_on_enter_exit(); |
|
237 void parse_variable_declaration(); |
|
238 void parse_goto(); |
|
239 void parse_if(); |
|
240 void parse_else(); |
|
241 void parse_while_block(); |
|
242 void parse_for_block(); |
|
243 void parse_do_block(); |
|
244 void parse_switch_block(); |
|
245 void parse_switch_case(); |
|
246 void parse_switch_default(); |
|
247 void parse_break(); |
|
248 void parse_continue(); |
|
249 void parse_block_end(); |
|
250 void parse_const(); |
|
251 void parse_label(); |
|
252 void parse_eventdef(); |
|
253 void parse_funcdef(); |
|
254 void write_member_buffers(); |
|
255 void write_string_table(); |
|
256 }; |
|
257 |
|
258 constant_info* find_constant (const string& tok); |
|
259 |
|
260 #endif // BOTC_PARSER_H |
|