Bug Summary

File:mtx_reader.cc
Warning:line 807, column 3
Value stored to 'val' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name mtx_reader.cc -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/tmp/build/apertium/apertium-3.9.12+g928~04ac90c6/apertium -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/utf8cpp/ -I /usr/local/include -I /usr/include/libxml2 -I /usr/local/include -D PIC -internal-isystem /usr/lib/llvm-16/bin/../include/c++/v1 -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=c++2b -fdeprecated-macro -fdebug-compilation-dir=/tmp/build/apertium/apertium-3.9.12+g928~04ac90c6/apertium -ferror-limit 19 -fgnuc-version=4.2.1 -fno-implicit-modules -fcxx-exceptions -fexceptions -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/build/apertium/scan-build/2024-09-11-155328-205384-1 -x c++ mtx_reader.cc
1/*
2 * Copyright (C) 2005 Universitat d'Alacant / Universidad de Alicante
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <https://www.gnu.org/licenses/>.
16 */
17#include <apertium/mtx_reader.h>
18#include <lttoolbox/xml_parse_util.h>
19#include <lttoolbox/compression.h>
20#include <lttoolbox/string_utils.h>
21#include <apertium/utils.h>
22#include <apertium/tsx_reader.h>
23#include <apertium/perceptron_spec.h>
24
25#include <cstdlib>
26#include <iostream>
27#include <sstream>
28#include <iterator>
29
30// XML parsing function guideline
31// When control is pass to you, you might need to stepToTag
32// When delegating or returning control, step beyond yourself
33
34namespace Apertium {
35MTXReader::MTXReader(VM &spec) :
36 spec(spec), in_global_defn(false),
37 template_slot_counter(0), cur_feat(NULL__null) {}
38
39size_t MTXReader::pushSetConst(std::string &val)
40{
41 size_t set_idx = spec.set_consts.size();
42 std::stringstream val_ss(val);
43 spec.set_consts.push_back(set<std::string>(
44 istream_iterator<std::string>(val_ss),
45 istream_iterator<std::string>()
46 ));
47 return set_idx;
48}
49
50size_t MTXReader::pushStrConst(std::string &val)
51{
52 size_t str_idx = spec.str_consts.size();
53 spec.str_consts.push_back(val);
54 return str_idx;
55}
56
57void MTXReader::emitBytecode(VM::Bytecode bc)
58{
59 cur_feat->push_back(bc.intbyte);
60}
61
62void MTXReader::pokeBytecode(size_t addr, VM::Bytecode bc)
63{
64 (*cur_feat)[addr] = bc.intbyte;
65}
66
67void MTXReader::emitOpcode(VM::Opcode op)
68{
69 emitBytecode((VM::Bytecode){.op = op});
70}
71
72void MTXReader::emitInt(int val)
73{
74 assert(-128 <= val && val < 128)(static_cast <bool> (-128 <= val && val <
128) ? void (0) : __assert_fail ("-128 <= val && val < 128"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
75 emitBytecode((VM::Bytecode){.intbyte = (signed char)val});
76}
77
78void MTXReader::emitUInt(int val)
79{
80 assert(0 <= val && val < 256)(static_cast <bool> (0 <= val && val < 256
) ? void (0) : __assert_fail ("0 <= val && val < 256"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
81 emitBytecode((VM::Bytecode){.uintbyte = (unsigned char)val});
82}
83
84void MTXReader::procCoarseTags()
85{
86 std::string tsx_fn((const char*) xmlTextReaderGetAttribute(reader, (const xmlChar*) "tag"));
87 bool is_abs = ((tsx_fn.size() >= 1 && tsx_fn[0] == '/') ||
88 (tsx_fn.size() >= 2 && tsx_fn[1] == ':'));
89 if (!is_abs) {
90 size_t last_slash_pos = path.rfind("/");
91 if (last_slash_pos != string::npos) {
92 tsx_fn = path.substr(0, last_slash_pos + 1) + tsx_fn;
93 }
94 }
95 TSXReader tsx_reader;
96 tsx_reader.read(tsx_fn);
97 spec.coarse_tags = Optional<TaggerDataPercepCoarseTags>(
98 tsx_reader.getTaggerData());
99 stepPastSelfClosingTag("coarse-tags"_u);
100}
101
102void MTXReader::procSetDef()
103{
104 std::string name = attrib_str("name"_u);
105 stepToNextTag();
106 size_t set_idx = spec.set_consts.size();
107 spec.set_consts.push_back(VMSet());
108 VMSet &vm_set = spec.set_consts.back();
109 while (type != XML_READER_TYPE_END_ELEMENT) {
110 if (name == "set-member") {
111 std::string tag = attrib_str("tag"_u);
112 std::string str = attrib_str("str"_u);
113 vm_set.insert(tag.empty() ? str : tag);
114 } else {
115 parseError("Expected set-member"_u);
116 }
117 stepToNextTag();
118 }
119 set_names[name] = set_idx;
120 assert(name == "def-set")(static_cast <bool> (name == "def-set") ? void (0) : __assert_fail
("name == \"def-set\"", __builtin_FILE (), __builtin_LINE ()
, __extension__ __PRETTY_FUNCTION__))
;
121 stepToNextTag();
122}
123
124void MTXReader::procStrDef()
125{
126 std::string name = attrib_str("name"_u);
127 std::string tag = attrib_str("tag"_u);
128 std::string str = attrib_str("str"_u);
129 str_names[name] = pushStrConst(tag.empty() ? str : tag);
130 stepPastSelfClosingTag("def-str"_u);
131}
132
133void
134MTXReader::procDefns()
135{
136 stepToNextTag();
137 while (type != XML_READER_TYPE_END_ELEMENT) {
138 if (name == "def-set"_u) {
139 procSetDef();
140 } else if (name == "def-str"_u) {
141 procStrDef();
142 } else if (name == "def-macro"_u) {
143 procDefMacro();
144 } else if (name == "#text"_u || name == "#comment"_u) {
145 // skip
146 } else {
147 unexpectedTag();
148 }
149 }
150 assert(name == "defns"_u)(static_cast <bool> (name == "defns"_u) ? void (0) : __assert_fail
("name == \"defns\"_u", __builtin_FILE (), __builtin_LINE ()
, __extension__ __PRETTY_FUNCTION__))
;
151 stepToNextTag();
152}
153
154void
155MTXReader::procGlobalPred()
156{
157 cur_feat = &spec.global_pred;
158 stepToNextTag();
159 procBoolExpr();
160 assert(name == "global-pred"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "global-pred"_u &&
type == XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail
("name == \"global-pred\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
161 stepToNextTag();
162}
163
164void
165MTXReader::emitSetImmOp(VM::Opcode op)
166{
167 emitOpcode(op);
168 getAndEmitSetRef();
169}
170
171void
172MTXReader::emitStrImmOp(VM::Opcode op)
173{
174 emitOpcode(op);
175 getAndEmitStrRef();
176}
177
178void
179MTXReader::procBinCompareOp(VM::Opcode op)
180{
181 procIntExpr();
182 procIntExpr();
183 emitOpcode(op);
184}
185
186void
187MTXReader::procCommBoolOp(VM::Opcode op)
188{
189 int operand_count = 0;
190 while (type != XML_READER_TYPE_END_ELEMENT) {
191 procBoolExpr();
192 operand_count++;
193 }
194 while (--operand_count > 0) {
195 emitOpcode(op);
196 }
197}
198
199bool
200MTXReader::procIntExpr(bool allow_fail)
201{
202 /* Self-closing tags */
203 if (!tryProcArg(INTEXPR, true)
204 && !tryProcVar(VM::INTVAL)) {
205 if (name == "sentlen"_u) {
206 emitOpcode(VM::SENTLENTOK);
207 stepPastSelfClosingTag("sentlen"_u);
208 } else if (name == "pathlen"_u) {
209 emitOpcode(VM::SENTLENWRD);
210 stepPastSelfClosingTag("pathlen"_u);
211 } else if (name == "tokaddr"_u) {
212 emitOpcode(VM::PUSHTOKADDR);
213 stepPastSelfClosingTag("tokaddr"_u);
214 } else if (name == "wrdidx"_u) {
215 emitOpcode(VM::PUSHWRDADDR);
216 stepPastSelfClosingTag("wrdidx"_u);
217 } else if (name == "int"_u) {
218 emitOpcode(VM::PUSHINT);
219 getAndEmitInt();
220 stepPastSelfClosingTag("int"_u);
221 /* Other tags */
222 } else if (name == "add"_u) {
223 stepToNextTag();
224 procIntExpr();
225 procIntExpr();
226 assert(name == "add"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "add"_u && type ==
XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail ("name == \"add\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
227 emitOpcode(VM::ADD);
228 stepToNextTag();
229 } else if (name == "toklen"_u) {
230 procIntExpr();
231 assert(name == "toklen"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "toklen"_u && type
== XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail (
"name == \"toklen\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
232 emitOpcode(VM::TOKLENWRD);
233 stepToNextTag();
234 } else if (name == "strlen"_u) {
235 procStrExpr();
236 assert(name == "strlen"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "strlen"_u && type
== XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail (
"name == \"strlen\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
237 emitOpcode(VM::STRLEN);
238 stepToNextTag();
239 } else if (name == "arrlen"_u) {
240 procStrArrExpr();
241 assert(name == "arrlen"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "arrlen"_u && type
== XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail (
"name == \"arrlen\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
242 procBinCompareOp(VM::ARRLEN);
243 stepToNextTag();
244 } else {
245 if (allow_fail) {
246 return false;
247 }
248 parseError("Expected an integer expression."_u);
249 }
250 }
251 return true;
252}
253
254bool
255MTXReader::procStrArrExpr(bool allow_fail)
256{
257 stepToTag();
258 if (!tryProcArg(STRARREXPR, true)
259 && !tryProcVar(VM::STRARRVAL)
260 && !tryProcSlice(&MTXReader::procStrArrExpr)) {
261 if (name == "ex-tags"_u) {
262 stepToNextTag();
263 procWordoidExpr();
264 assert(type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (type == XML_READER_TYPE_END_ELEMENT
) ? void (0) : __assert_fail ("type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
265 emitOpcode(VM::EXTAGS);
266 } else if (name == "ex-ambgset"_u) {
267 stepToNextTag();
268 procIntExpr();
269 emitOpcode(VM::EXAMBGSET);
270 } else if (name == "for-each"_u) {
271 procForEach(STREXPR);
272 } else {
273 if (allow_fail) {
274 return false;
275 }
276 parseError("Expected a string list expression."_u);
277 }
278 stepToNextTag();
279 }
280 return true;
281}
282
283bool MTXReader::tryProcSubscript(bool (MTXReader::*proc_inner)(bool))
284{
285 if (name == "subscript"_u) {
286 int idx = getInt("idx"_u);
287 stepToNextTag();
288 (this->*proc_inner)(false);
289 emitOpcode(VM::SUBSCRIPT);
290 emitUInt(idx);
291 assert(name == "subscript"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "subscript"_u && type
== XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail (
"name == \"subscript\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
292 stepToNextTag();
293 return true;
294 }
295 return false;
296}
297
298bool MTXReader::tryProcSlice(bool (MTXReader::*proc_inner)(bool))
299{
300 if (name == "slice"_u) {
301 stepToNextTag();
302 (this->*proc_inner)(false);
303 bool exists;
304 emitOpcode(VM::SLICE);
305 int start_lit = getInt("start"_u, exists);
306 if (exists) {
307 emitInt(start_lit);
308 } else {
309 emitInt(0);
310 }
311 int end_lit = getInt("end"_u, exists);
312 if (exists) {
313 emitInt(end_lit);
314 } else {
315 emitInt(0);
316 }
317 assert(name == "slice"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "slice"_u && type ==
XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail ("name == \"slice\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
318 stepToNextTag();
319 return true;
320 }
321 return false;
322}
323
324bool MTXReader::tryProcArg(ExprType expr_type, bool allow_fail)
325{
326 if (name == "var"_u) {
327 std::string var_name = attrib_str("name"_u);
328 if (in_global_defn) {
329 VarNVMap::const_iterator arg_name_it = template_arg_names.find(var_name);
330 if (arg_name_it != template_arg_names.end()) {
331 cur_replacements->push_back(make_pair(arg_name_it->second, expr_type));
332 stepPastSelfClosingTag("var"_u);
333 return true;
334 }
335 if (!allow_fail) {
336 parseError("No such argument " + var_name);
337 }
338 }
339 }
340 return false;
341}
342
343bool MTXReader::tryProcVar(VM::StackValueType svt)
344{
345 if (name == "var"_u) {
346 std::string var_name = attrib_str("name"_u);
347
348 VarNVMap::const_iterator slot_names_it = slot_names.find(var_name);
349 if (slot_names_it != slot_names.end()) {
350 if (slot_types[slot_names_it->second] != svt) {
351 parseError("Variable " + var_name + " has the wrong type");
352 }
353 emitOpcode(VM::GETVAR);
354 emitUInt(slot_names_it->second);
355 stepPastSelfClosingTag("var"_u);
356 return true;
357 }
358
359 parseError("Variable " + var_name + " has not been set.");
360 } else if (!in_global_defn && name == "macro"_u) {
361 // Get template data
362 std::string var_name = attrib_str("name"_u);
363 VarNVMap::const_iterator template_name_it = template_slot_names.find(var_name);
364 if (template_name_it == template_slot_names.end()) {
365 parseError("No such macro " + var_name);
366 }
367 size_t templ_idx = template_name_it->second;
368 if (template_slot_types[templ_idx] != svt) {
369 parseError("Macro " + var_name + " returns the wrong type");
370 }
371 std::pair<VM::FeatureDefn, TemplateReplacements> &templ_defn = template_defns[templ_idx];
372 // Get arg values
373 stepToNextTag();
374 std::vector<VM::FeatureDefn> arg_values;
375 VM::FeatureDefn *saved_feat = cur_feat;
376 TemplateReplacements::const_iterator templ_repl_it = templ_defn.second.begin();
377 for (; templ_repl_it != templ_defn.second.end(); templ_repl_it++) {
378 arg_values.push_back(VM::FeatureDefn());
379 cur_feat = &arg_values.back();
380 procTypeExpr(templ_repl_it->second);
381 }
382 cur_feat = saved_feat;
383 // Check for previous instanciation...
384 InstanciationMap::const_iterator templ_instcia_it =
385 template_instanciations.find(make_pair(templ_idx, arg_values));
386 if (templ_instcia_it == template_instanciations.end()) {
387 // and instanciate if doesn't exist...
388 // by ordering argument defns correctly
389 vector<unsigned int> indices(templ_defn.second.size(), 0);
390 for (size_t i = 0; i < templ_defn.second.size(); i++) {
391 indices[i] = i;
392 }
393 SortByComparer<std::pair<size_t, ExprType>, int> sbc(templ_defn.second);
394 std::sort(indices.begin(), indices.end(), sbc);
395 // And then copying the template defn bits and the argument defn bits into the global defn
396 VM::FeatureDefn::const_iterator src_start_it = templ_defn.first.begin();
397 VM::FeatureDefn::const_iterator src_end_it = templ_defn.first.end();
398 VM::FeatureDefn::const_iterator src_cur_it = src_start_it;
399 spec.global_defns.push_back(VM::FeatureDefn());
400 VM::FeatureDefn &global_defn = spec.global_defns.back();
401 std::back_insert_iterator<VM::FeatureDefn> dest_it(global_defn);
402 for (size_t i = 0; i < indices.size(); i++) {
403 size_t repl_i = indices[i];
404 size_t offset = templ_defn.second[repl_i].first;
405 VM::FeatureDefn &arg_src = arg_values[repl_i];
406 std::copy(src_cur_it, src_cur_it + offset, dest_it);
407 src_cur_it = src_start_it + offset;
408 std::copy(arg_src.begin(), arg_src.end(), dest_it);
409 }
410 std::copy(src_cur_it, src_end_it, dest_it);
411 templ_instcia_it = template_instanciations.insert(
412 make_pair(
413 make_pair(templ_idx, arg_values),
414 spec.global_defns.size() - 1)).first;
415 }
416 // Finally emit a reference to the relevant global
417 emitOpcode(VM::GETGVAR);
418 emitUInt(templ_instcia_it->second);
419 // Step past end
420 assert(name == "macro"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "macro"_u && type ==
XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail ("name == \"macro\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
421 stepToNextTag();
422 return true;
423 }
424 return false;
425}
426
427bool
428MTXReader::procStrExpr(bool allow_fail)
429{
430 if (!tryProcArg(STREXPR, true)
431 && !tryProcVar(VM::STRVAL)
432 && !tryProcSlice(&MTXReader::procStrExpr)
433 && !tryProcSubscript(&MTXReader::procStrArrExpr)) {
434 if (name == "ex-surf"_u) {
435 stepToNextTag();
436 procIntExpr();
437 emitOpcode(VM::EXTOKSURF);
438 } else if (name == "ex-lemma"_u) {
439 stepToNextTag();
440 procWordoidExpr();
441 emitOpcode(VM::EXWRDLEMMA);
442 } else if (name == "ex-coarse"_u) {
443 stepToNextTag();
444 procWordoidExpr();
445 emitOpcode(VM::EXWRDCOARSETAG);
446 } else if (name == "join"_u) {
447 bool has_attr;
448 size_t str_idx = getStrRef(has_attr);
449 if (!has_attr) {
450 str_idx = 255;
451 }
452 stepToNextTag();
453 procStrArrExpr();
454 emitOpcode(VM::JOIN);
455 emitUInt(str_idx);
456 } else {
457 if (allow_fail) {
458 return false;
459 }
460 parseError("Expected a string expression."_u);
461 }
462 assert(type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (type == XML_READER_TYPE_END_ELEMENT
) ? void (0) : __assert_fail ("type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
463 stepToNextTag();
464 }
465 return true;
466}
467
468bool
469MTXReader::procBoolExpr(bool allow_fail)
470{
471 if (!tryProcArg(BEXPR, true)
472 && !tryProcVar(VM::BVAL)) {
473 if (name == "and"_u) {
474 stepToNextTag();
475 procCommBoolOp(VM::AND);
476 assert(name == "and"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "and"_u && type ==
XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail ("name == \"and\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
477 stepToNextTag();
478 } else if (name == "or"_u) {
479 stepToNextTag();
480 procCommBoolOp(VM::OR);
481 assert(name == "or"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "or"_u && type == XML_READER_TYPE_END_ELEMENT
) ? void (0) : __assert_fail ("name == \"or\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
482 stepToNextTag();
483 } else if (name == "not"_u) {
484 stepToNextTag();
485 procBoolExpr();
486 emitOpcode(VM::NOT);
487 assert(name == "not"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "not"_u && type ==
XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail ("name == \"not\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
488 stepToNextTag();
489 } else if (name == "eq"_u) {
490 stepToNextTag();
491 procBinCompareOp(VM::EQ);
492 assert(name == "eq"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "eq"_u && type == XML_READER_TYPE_END_ELEMENT
) ? void (0) : __assert_fail ("name == \"eq\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
493 stepToNextTag();
494 } else if (name == "neq"_u) {
495 stepToNextTag();
496 procBinCompareOp(VM::NEQ);
497 assert(name == "neq"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "neq"_u && type ==
XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail ("name == \"neq\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
498 stepToNextTag();
499 } else if (name == "lt"_u) {
500 stepToNextTag();
501 procBinCompareOp(VM::LT);
502 assert(name == "lt"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "lt"_u && type == XML_READER_TYPE_END_ELEMENT
) ? void (0) : __assert_fail ("name == \"lt\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
503 stepToNextTag();
504 } else if (name == "lte"_u) {
505 stepToNextTag();
506 procBinCompareOp(VM::LTE);
507 assert(name == "lte"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "lte"_u && type ==
XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail ("name == \"lte\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
508 stepToNextTag();
509 } else if (name == "gt"_u) {
510 stepToNextTag();
511 procBinCompareOp(VM::GT);
512 assert(name == "gt"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "gt"_u && type == XML_READER_TYPE_END_ELEMENT
) ? void (0) : __assert_fail ("name == \"gt\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
513 stepToNextTag();
514 } else if (name == "gte"_u) {
515 stepToNextTag();
516 procBinCompareOp(VM::GTE);
517 assert(name == "gte"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "gte"_u && type ==
XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail ("name == \"gte\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
518 stepToNextTag();
519 } else if (name == "streq"_u) {
520 size_t str_ref = getStrRef();
521 stepToNextTag();
522 procStrExpr();
523 emitOpcode(VM::STREQ);
524 emitUInt(str_ref);
525 assert(name == "streq"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "streq"_u && type ==
XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail ("name == \"streq\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
526 stepToNextTag();
527 } else if (name == "strin"_u) {
528 size_t set_ref = getSetRef();
529 stepToNextTag();
530 procStrExpr();
531 emitOpcode(VM::STRIN);
532 emitUInt(set_ref);
533 assert(name == "strin"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "strin"_u && type ==
XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail ("name == \"strin\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
534 stepToNextTag();
535 /* Identical to strin?
536 } else if (name == "sethas"_u) {
537 stepToNextTag();
538 procStrExpr();
539 emitSetImmOp(VM::SETHAS);
540 */
541 } else if (name == "sethasany"_u) {
542 size_t set_ref = getSetRef();
543 stepToNextTag();
544 procStrArrExpr();
545 emitOpcode(VM::SETHASANY);
546 emitUInt(set_ref);
547 assert(name == "sethasany"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "sethasany"_u && type
== XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail (
"name == \"sethasany\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
548 stepToNextTag();
549 } else if (name == "sethasall"_u) {
550 size_t set_ref = getSetRef();
551 stepToNextTag();
552 procStrArrExpr();
553 emitOpcode(VM::SETHASALL);
554 emitUInt(set_ref);
555 assert(name == "sethasall"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "sethasall"_u && type
== XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail (
"name == \"sethasall\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
556 stepToNextTag();
557 } else {
558 if (allow_fail) {
559 return false;
560 }
561 parseError("Expected a boolean expression."_u);
562 }
563 }
564 return true;
565}
566
567void
568MTXReader::procAddrExpr()
569{
570 stepToTag();
571 /* Self-closing tags */
572 if (!tryProcArg(ADDREXPR)) {
573 if (name == "wrdaddr"_u) {
574 emitOpcode(VM::PUSHADDR);
575 stepPastSelfClosingTag("wrdaddr"_u);
576 /* Others */
577 } else if (name == "addr-of-ints"_u) {
578 stepToNextTag();
579 procIntExpr();
580 procIntExpr();
581 assert(name == "addr-of-ints"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "addr-of-ints"_u &&
type == XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail
("name == \"addr-of-ints\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
582 stepToNextTag();
583 } else if (name == "add"_u) {
584 stepToNextTag();
585 procAddrExpr();
586 procAddrExpr();
587 assert(name == "add"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "add"_u && type ==
XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail ("name == \"add\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
588 emitOpcode(VM::ADD2);
589 stepToNextTag();
590 } else if (name == "adjust"_u) {
591 stepToNextTag();
592 procAddrExpr();
593 assert(name == "adjust"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "adjust"_u && type
== XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail (
"name == \"adjust\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
594 emitOpcode(VM::ADJADDR);
595 stepToNextTag();
596 } else if (name == "clamp"_u) {
597 stepToNextTag();
598 procAddrExpr();
599 assert(name == "clamp"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "clamp"_u && type ==
XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail ("name == \"clamp\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
600 emitOpcode(VM::CLAMPADDR);
601 stepToNextTag();
602 } else {
603 parseError("Expected an address expression."_u);
604 }
605 }
606}
607
608bool
609MTXReader::procWordoidArrExpr(bool allow_fail)
610{
611 if (!tryProcArg(WRDARREXPR, true)
612 && !tryProcVar(VM::WRDARRVAL)
613 && !tryProcSlice(&MTXReader::procWordoidArrExpr)) {
614 if (name == "ex-wordoids"_u) {
615 stepToNextTag();
616 procIntExpr();
617 emitOpcode(VM::EXWRDARR);
618 assert(name == "ex-wordoids"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "ex-wordoids"_u &&
type == XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail
("name == \"ex-wordoids\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
619 } else if (name == "for-each"_u) {
620 procForEach(WRDEXPR);
621 } else {
622 if (allow_fail) {
623 return false;
624 }
625 parseError("Expected a wordoid array expression."_u);
626 }
627 stepToNextTag();
628 }
629 return true;
630}
631
632bool
633MTXReader::procWordoidExpr(bool allow_fail)
634{
635 stepToTag();
636 if (!tryProcArg(WRDEXPR, true)
637 && !tryProcVar(VM::WRDVAL)
638 && !tryProcSubscript(&MTXReader::procWordoidArrExpr)) {
639 if (name == "ex-wordoid"_u) {
640 stepToNextTag();
641 procAddrExpr();
642 emitOpcode(VM::GETWRD);
643 } else {
644 if (allow_fail) {
645 return false;
646 }
647 parseError("Expected a wordoid expression."_u);
648 }
649 assert(type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (type == XML_READER_TYPE_END_ELEMENT
) ? void (0) : __assert_fail ("type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
650 stepToNextTag();
651 }
652 return true;
653}
654
655void
656MTXReader::procPred()
657{
658 stepToNextTag();
659 procBoolExpr();
660 assert(name == "pred"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "pred"_u && type ==
XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail ("name == \"pred\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
661 emitOpcode(VM::DIEIFFALSE);
662 stepToNextTag();
663}
664
665size_t
666MTXReader::getConstRef(
667 const UString &ref_attr,
668 const UString &lit_attr,
669 const UString &what,
670 VarNVMap &const_map,
671 size_t (MTXReader::*push_new)(std::string&),
672 bool& exists)
673{
674 std::string const_name = attrib_str(ref_attr);
675 if (!const_name.empty()) {
676 exists = true;
677 VarNVMap::iterator sit = const_map.find(const_name);
678 if (sit == const_map.end()) {
679 parseError("No "_u + what + " named "_u + to_ustring(const_name.c_str()));
680 }
681 return sit->second;
682 }
683 std::string const_lit = attrib_str(lit_attr);
684 if (!const_lit.empty()) {
685 exists = true;
686 return (this->*push_new)(const_lit);
687 }
688 exists = false;
689 return 0;
690}
691
692size_t
693MTXReader::getSetRef(bool& exists)
694{
695 return getConstRef("name"_u, "val"_u, "set"_u, set_names, &MTXReader::pushSetConst, exists);
696}
697
698size_t
699MTXReader::getSetRef()
700{
701 bool has_attr;
702 size_t set_ref = getSetRef(has_attr);
703 if (!has_attr) {
704 parseError("Set required"_u);
705 }
706 return set_ref;
707}
708
709size_t
710MTXReader::getStrRef(bool& exists)
711{
712 return getConstRef("name"_u, "val"_u, "string"_u, str_names, &MTXReader::pushStrConst, exists);
713}
714
715size_t
716MTXReader::getStrRef()
717{
718 bool has_attr;
719 size_t str_ref = getStrRef(has_attr);
720 if (!has_attr) {
721 parseError("String required"_u);
722 }
723 return str_ref;
724}
725
726int
727MTXReader::getInt(const UString& attr_name, bool& exists)
728{
729 std::string int_lit = attrib_str(attr_name);
730 if (!int_lit.empty()) {
731 exists = true;
732 int int_out;
733 stringstream int_ss(int_lit);
734 int_ss >> int_out;
735 return int_out;
736 }
737 exists = false;
738 return 0;
739}
740
741int
742MTXReader::getInt(bool& exists)
743{
744 return getInt("val"_u, exists);
745}
746
747int
748MTXReader::getInt(const UString& attr_name)
749{
750 bool has_attr;
751 int i = getInt(attr_name, has_attr);
752 if (!has_attr) {
753 parseError("String required");
754 }
755 return i;
756}
757
758int
759MTXReader::getInt()
760{
761 return getInt("val"_u);
762}
763
764template<typename GetT, typename EmitT>
765void
766MTXReader::emitAttr(
767 std::string what, GetT (MTXReader::*getter)(bool&), void (MTXReader::*emitter)(EmitT))
768{
769 bool has_attr = false;
770 GetT val = (this->*getter)(has_attr);
771 if (!has_attr) {
772 parseError(what + " required");
773 }
774 (this->*emitter)(val);
775}
776
777void
778MTXReader::getAndEmitStrRef()
779{
780 emitAttr("String", &MTXReader::getStrRef, &MTXReader::emitUInt);
781}
782
783void
784MTXReader::getAndEmitSetRef()
785{
786 emitAttr("Set", &MTXReader::getSetRef, &MTXReader::emitUInt);
787}
788
789void
790MTXReader::getAndEmitInt()
791{
792 emitAttr("Integer", &MTXReader::getInt, &MTXReader::emitInt);
793}
794
795void
796MTXReader::procInst()
797{
798 // XXX: There's no way to tell the difference between an empty and absent
799 // attribute with the current lttoolbox xml code
800 std::string op = attrib_str("opcode"_u);
801 std::transform(op.begin(), op.end(), op.begin(), ::toupper);
802 emitOpcode(VM::opcode_values[op]);
803 int val;
804 bool has_set_ref;
805 val = getSetRef(has_set_ref);
806 bool has_str_ref;
807 val = getStrRef(has_str_ref);
Value stored to 'val' is never read
808 bool has_int_lit;
809 val = getInt(has_int_lit);
810 int num_operands = has_set_ref + has_str_ref + has_int_lit;
811 if (num_operands > 1) {
812 parseError("Opcodes can have at most one operand."_u);
813 } else if (num_operands == 1) {
814 if (has_int_lit) {
815 emitInt(val);
816 } else {
817 emitUInt(val);
818 }
819 }
820}
821
822void
823MTXReader::procOut()
824{
825 bool has_expr = false;
826 stepToNextTag();
827 if (procStrExpr(true)) {
828 emitOpcode(VM::FCATSTR);
829 has_expr = true;
830 }
831 if (!has_expr && procBoolExpr(true)) {
832 emitOpcode(VM::FCATBOOL);
833 has_expr = true;
834 }
835 if (!has_expr && procIntExpr(true)) {
836 emitOpcode(VM::FCATINT);
837 has_expr = true;
838 }
839 if (!has_expr) {
840 parseError("Expected a string, bool or int expression."_u);
841 }
842 stepToTag();
843 assert(name == "out"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "out"_u && type ==
XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail ("name == \"out\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
844 stepToNextTag();
845}
846
847void
848MTXReader::procOutMany()
849{
850 stepToNextTag();
851 procStrArrExpr();
852 emitOpcode(VM::FCATSTRARR);
853 assert(name == "out-many"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "out-many"_u && type
== XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail (
"name == \"out-many\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
854 stepToNextTag();
855}
856
857void
858MTXReader::printTmplDefn(const TemplateDefn &tmpl_defn)
859{
860 PerceptronSpec::printFeature(std::cerr, tmpl_defn.first);
861 if (tmpl_defn.second.size() > 0) {
862 std::cerr << "Replacements:\n"_u;
863 TemplateReplacements::const_iterator it = tmpl_defn.second.begin();
864 for (; it != tmpl_defn.second.end(); it++) {
865 std::cerr << "Index: "_u << it->first << " "_u;
866 printTypeExpr(it->second);
867 std::cerr << "\n"_u;
868 }
869 }
870}
871
872void
873MTXReader::printStackValueType(VM::StackValueType svt)
874{
875 switch (svt) {
876 case VM::INTVAL:
877 std::cerr << "INT";
878 break;
879 case VM::BVAL:
880 std::cerr << "BOOL";
881 break;
882 case VM::STRVAL:
883 std::cerr << "STR";
884 break;
885 case VM::STRARRVAL:
886 std::cerr << "STRARR";
887 break;
888 case VM::WRDVAL:
889 std::cerr << "WRD";
890 break;
891 case VM::WRDARRVAL:
892 std::cerr << "WRDARR";
893 break;
894 default:
895 throw 1;
896 }
897}
898
899void
900MTXReader::printTypeExpr(ExprType expr_type)
901{
902 switch (expr_type) {
903 case VOIDEXPR:
904 std::cerr << "VOID";
905 break;
906 case INTEXPR:
907 std::cerr << "INT";
908 break;
909 case BEXPR:
910 std::cerr << "BOOL";
911 break;
912 case STREXPR:
913 std::cerr << "STR";
914 procStrExpr();
915 break;
916 case STRARREXPR:
917 std::cerr << "STRARR";
918 break;
919 case WRDEXPR:
920 std::cerr << "WRD";
921 break;
922 case WRDARREXPR:
923 std::cerr << "WRDARR";
924 break;
925 case ADDREXPR:
926 std::cerr << "ADDR";
927 break;
928 default:
929 throw 1;
930 }
931}
932
933void
934MTXReader::procTypeExpr(ExprType expr_type)
935{
936 switch (expr_type) {
937 case VOIDEXPR:
938 procVoidExpr();
939 break;
940 case INTEXPR:
941 procIntExpr();
942 break;
943 case BEXPR:
944 procBoolExpr();
945 break;
946 case STREXPR:
947 procStrExpr();
948 break;
949 case STRARREXPR:
950 procStrArrExpr();
951 break;
952 case WRDEXPR:
953 procWordoidExpr();
954 break;
955 case WRDARREXPR:
956 procWordoidArrExpr();
957 break;
958 case ADDREXPR:
959 procAddrExpr();
960 break;
961 default:
962 throw 1;
963 }
964}
965
966void
967MTXReader::procForEach(ExprType expr_type)
968{
969 std::string var_name = attrib_str("as"_u);
970 if (var_name.empty()) {
971 parseError("'as' attribute required for for-each."_u);
972 }
973 size_t slot_idx = slot_counter++;
974 slot_names[var_name] = slot_idx;
975 bool has_expr = false;
976 stepToNextTag();
977 if (procStrArrExpr(true)) {
978 slot_types.push_back(VM::STRVAL);
979 has_expr = true;
980 }
981 if (!has_expr && procWordoidArrExpr(true)) {
982 slot_types.push_back(VM::WRDVAL);
983 has_expr = true;
984 }
985 if (!has_expr) {
986 parseError("Expected a string array or wordoid array expression."_u);
987 }
988
989 emitOpcode(VM::FOREACHINIT);
990 size_t for_each_begin = cur_feat->size();
991 emitOpcode(VM::FOREACH);
992 emitUInt(slot_idx);
993 size_t begin_offset_placeholder = cur_feat->size();
994 emitUInt(0); // offset placeholder
995 size_t for_each_body_begin = cur_feat->size();
996
997 switch (expr_type) {
998 case VOIDEXPR:
999 procVoidExpr();
1000 break;
1001 case STREXPR:
1002 procStrExpr();
1003 break;
1004 case WRDEXPR:
1005 procWordoidExpr();
1006 break;
1007 default:
1008 throw 1;
1009 break;
1010 }
1011 assert(type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (type == XML_READER_TYPE_END_ELEMENT
) ? void (0) : __assert_fail ("type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
1012
1013 size_t end_for_each_addr = cur_feat->size();
1014 emitOpcode(VM::ENDFOREACH);
1015 emitInt(end_for_each_addr + 2 - for_each_begin); // offset
1016 pokeBytecode(begin_offset_placeholder, (VM::Bytecode){
1017 .uintbyte=(unsigned char)(end_for_each_addr + 2 - for_each_body_begin)});
1018}
1019
1020bool
1021MTXReader::procVoidExpr(bool allow_fail)
1022{
1023 stepToTag();
1024 if (name == "pred"_u) {
1025 procPred();
1026 } else if (name == "out"_u) {
1027 procOut();
1028 } else if (name == "out-many"_u) {
1029 procOutMany();
1030 } else if (name == "for-each"_u) {
1031 procForEach(VOIDEXPR);
1032 } else if (name == "inst"_u) {
1033 procInst();
1034 } else {
1035 if (allow_fail) {
1036 return false;
1037 }
1038 parseError("Expected a void expression."_u);
1039 }
1040 return true;
1041}
1042
1043void
1044MTXReader::procDefMacro()
1045{
1046 in_global_defn = true;
1047 slot_counter = 0;
1048 template_defns.push_back(make_pair(VM::FeatureDefn(), TemplateReplacements()));
1049 cur_feat = &template_defns.back().first;
1050 cur_replacements = &template_defns.back().second;
1051
1052 std::string var_name = attrib_str("as"_u);
1053 if (var_name.empty()) {
1054 parseError("'as' attribute required for def-macro."_u);
1055 }
1056 template_slot_names[var_name] = template_slot_counter;
1057
1058 template_arg_names.clear();
1059 std::string args = attrib_str("args"_u);
1060 std::istringstream args_ss(args);
1061 size_t arg_i = 0;
1062 for (; !args_ss.eof(); arg_i++) {
1063 std::string arg_name;
1064 args_ss >> arg_name;
1065 if (arg_name.empty()) {
1066 break;
1067 }
1068 template_arg_names[arg_name] = arg_i;
1069 }
1070 stepToNextTag();
1071
1072 bool has_expr = false;
1073 if (procIntExpr(true)) {
1074 template_slot_types.push_back(VM::INTVAL);
1075 has_expr = true;
1076 }
1077 if (!has_expr && procBoolExpr(true)) {
1078 template_slot_types.push_back(VM::BVAL);
1079 has_expr = true;
1080 }
1081 if (!has_expr && procStrExpr(true)) {
1082 template_slot_types.push_back(VM::STRVAL);
1083 has_expr = true;
1084 }
1085 if (!has_expr && procStrArrExpr(true)) {
1086 template_slot_types.push_back(VM::STRARRVAL);
1087 has_expr = true;
1088 }
1089 if (!has_expr && procWordoidArrExpr(true)) {
1090 template_slot_types.push_back(VM::WRDARRVAL);
1091 has_expr = true;
1092 }
1093 if (!has_expr && procWordoidExpr(true)) {
1094 template_slot_types.push_back(VM::WRDVAL);
1095 has_expr = true;
1096 }
1097 if (!has_expr) {
1098 parseError("Expected a non-void expression."_u);
1099 }
1100 assert(name == "def-macro"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "def-macro"_u && type
== XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail (
"name == \"def-macro\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
1101 stepToNextTag();
1102
1103 template_slot_counter++;
1104 in_global_defn = false;
1105}
1106
1107void
1108MTXReader::procFeat()
1109{
1110 slot_counter = 0;
1111 spec.features.push_back(VM::FeatureDefn());
1112 cur_feat = &spec.features.back();
1113 stepToNextTag();
1114 while (type != XML_READER_TYPE_END_ELEMENT) {
1115 procVoidExpr();
1116 }
1117 assert(name == "feat"_u)(static_cast <bool> (name == "feat"_u) ? void (0) : __assert_fail
("name == \"feat\"_u", __builtin_FILE (), __builtin_LINE (),
__extension__ __PRETTY_FUNCTION__))
;
1118 stepToNextTag();
1119}
1120
1121void
1122MTXReader::procFeats()
1123{
1124 stepToNextTag();
1125 while (type != XML_READER_TYPE_END_ELEMENT) {
1126 if (name == "feat"_u) {
1127 procFeat();
1128 } else {
1129 unexpectedTag();
1130 }
1131 }
1132 assert(name == "feats"_u)(static_cast <bool> (name == "feats"_u) ? void (0) : __assert_fail
("name == \"feats\"_u", __builtin_FILE (), __builtin_LINE ()
, __extension__ __PRETTY_FUNCTION__))
;
1133 stepToNextTag();
1134}
1135
1136void
1137MTXReader::printTmplDefns()
1138{
1139 std::vector<TemplateDefn>::const_iterator it = template_defns.begin();
1140 for (; it != template_defns.end(); it++) {
1141 std::cerr << " Macro " << it - template_defns.begin() << "\n";
1142 printTmplDefn(*it);
1143 }
1144}
1145
1146void
1147MTXReader::parse()
1148{
1149 xmlTextReaderSetParserProp(reader, XML_PARSER_SUBST_ENTITIES, true);
1150 stepToNextTag();
1151 if (type == XML_READER_TYPE_DOCUMENT_TYPE) {
1152 stepToNextTag();
1153 }
1154 if (name != "metatag"_u) {
1155 parseError("expected <metatag> tag"_u);
1156 }
1157 stepToNextTag();
1158 if (name == "coarse-tags"_u) {
1159 procCoarseTags();
1160 }
1161 if (name == "beam-width"_u) {
1162 size_t val;
1163 std::istringstream val_ss(attrib_str("val"_u));
1164 val_ss >> val;
1165 spec.beam_width = val;
1166 } else {
1167 spec.beam_width = 4;
1168 }
1169 if (name == "defns"_u) {
1170 procDefns();
1171 }
1172 if (name == "global-pred"_u) {
1173 procGlobalPred();
1174 }
1175 if (name == "feats"_u) {
1176 procFeats();
1177 }
1178 assert(name == "metatag"_u && type == XML_READER_TYPE_END_ELEMENT)(static_cast <bool> (name == "metatag"_u && type
== XML_READER_TYPE_END_ELEMENT) ? void (0) : __assert_fail (
"name == \"metatag\"_u && type == XML_READER_TYPE_END_ELEMENT"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
1179}
1180}