1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtScxml module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #ifndef QSCXMLCOMPILER_P_H |
41 | #define QSCXMLCOMPILER_P_H |
42 | |
43 | // |
44 | // W A R N I N G |
45 | // ------------- |
46 | // |
47 | // This file is not part of the Qt API. It exists purely as an |
48 | // implementation detail. This header file may change from version to |
49 | // version without notice, or even be removed. |
50 | // |
51 | // We mean it. |
52 | // |
53 | |
54 | #include "qscxmlcompiler.h" |
55 | |
56 | #include <QtCore/qdir.h> |
57 | #include <QtCore/qfileinfo.h> |
58 | #include <QtCore/qset.h> |
59 | #include <QtCore/qsharedpointer.h> |
60 | #include <QtCore/qstringlist.h> |
61 | #include <QtCore/qstring.h> |
62 | #include <QtCore/qxmlstream.h> |
63 | |
64 | QT_BEGIN_NAMESPACE |
65 | |
66 | namespace DocumentModel { |
67 | |
68 | struct XmlLocation |
69 | { |
70 | int line; |
71 | int column; |
72 | |
73 | XmlLocation(int theLine, int theColumn): line(theLine), column(theColumn) {} |
74 | }; |
75 | |
76 | struct If; |
77 | struct Send; |
78 | struct Invoke; |
79 | struct Script; |
80 | struct AbstractState; |
81 | struct State; |
82 | struct Transition; |
83 | struct HistoryState; |
84 | struct Scxml; |
85 | class NodeVisitor; |
86 | struct Node { |
87 | XmlLocation xmlLocation; |
88 | |
89 | Node(const XmlLocation &theLocation): xmlLocation(theLocation) {} |
90 | virtual ~Node(); |
91 | virtual void accept(NodeVisitor *visitor) = 0; |
92 | |
93 | virtual If *asIf() { return nullptr; } |
94 | virtual Send *asSend() { return nullptr; } |
95 | virtual Invoke *asInvoke() { return nullptr; } |
96 | virtual Script *asScript() { return nullptr; } |
97 | virtual State *asState() { return nullptr; } |
98 | virtual Transition *asTransition() { return nullptr; } |
99 | virtual HistoryState *asHistoryState() { return nullptr; } |
100 | virtual Scxml *asScxml() { return nullptr; } |
101 | AbstractState *asAbstractState(); |
102 | |
103 | private: |
104 | Q_DISABLE_COPY(Node) |
105 | }; |
106 | |
107 | struct DataElement: public Node |
108 | { |
109 | QString id; |
110 | QString src; |
111 | QString expr; |
112 | QString content; |
113 | |
114 | DataElement(const XmlLocation &xmlLocation): Node(xmlLocation) {} |
115 | void accept(NodeVisitor *visitor) override; |
116 | }; |
117 | |
118 | struct Param: public Node |
119 | { |
120 | QString name; |
121 | QString expr; |
122 | QString location; |
123 | |
124 | Param(const XmlLocation &xmlLocation): Node(xmlLocation) {} |
125 | void accept(NodeVisitor *visitor) override; |
126 | }; |
127 | |
128 | struct DoneData: public Node |
129 | { |
130 | QString contents; |
131 | QString expr; |
132 | QVector<Param *> params; |
133 | |
134 | DoneData(const XmlLocation &xmlLocation): Node(xmlLocation) {} |
135 | void accept(NodeVisitor *visitor) override; |
136 | }; |
137 | |
138 | struct Instruction: public Node |
139 | { |
140 | Instruction(const XmlLocation &xmlLocation): Node(xmlLocation) {} |
141 | virtual ~Instruction() {} |
142 | }; |
143 | |
144 | typedef QVector<Instruction *> InstructionSequence; |
145 | typedef QVector<InstructionSequence *> InstructionSequences; |
146 | |
147 | struct Send: public Instruction |
148 | { |
149 | QString event; |
150 | QString eventexpr; |
151 | QString type; |
152 | QString typeexpr; |
153 | QString target; |
154 | QString targetexpr; |
155 | QString id; |
156 | QString idLocation; |
157 | QString delay; |
158 | QString delayexpr; |
159 | QStringList namelist; |
160 | QVector<Param *> params; |
161 | QString content; |
162 | QString contentexpr; |
163 | |
164 | Send(const XmlLocation &xmlLocation): Instruction(xmlLocation) {} |
165 | Send *asSend() override { return this; } |
166 | void accept(NodeVisitor *visitor) override; |
167 | }; |
168 | |
169 | struct ScxmlDocument; |
170 | struct Invoke: public Instruction |
171 | { |
172 | QString type; |
173 | QString typeexpr; |
174 | QString src; |
175 | QString srcexpr; |
176 | QString id; |
177 | QString idLocation; |
178 | QStringList namelist; |
179 | bool autoforward; |
180 | QVector<Param *> params; |
181 | InstructionSequence finalize; |
182 | |
183 | QSharedPointer<ScxmlDocument> content; |
184 | |
185 | Invoke(const XmlLocation &xmlLocation): Instruction(xmlLocation) {} |
186 | Invoke *asInvoke() override { return this; } |
187 | void accept(NodeVisitor *visitor) override; |
188 | }; |
189 | |
190 | struct Raise: public Instruction |
191 | { |
192 | QString event; |
193 | |
194 | Raise(const XmlLocation &xmlLocation): Instruction(xmlLocation) {} |
195 | void accept(NodeVisitor *visitor) override; |
196 | }; |
197 | |
198 | struct Log: public Instruction |
199 | { |
200 | QString label, expr; |
201 | |
202 | Log(const XmlLocation &xmlLocation): Instruction(xmlLocation) {} |
203 | void accept(NodeVisitor *visitor) override; |
204 | }; |
205 | |
206 | struct Script: public Instruction |
207 | { |
208 | QString src; |
209 | QString content; |
210 | |
211 | Script(const XmlLocation &xmlLocation): Instruction(xmlLocation) {} |
212 | Script *asScript() override { return this; } |
213 | void accept(NodeVisitor *visitor) override; |
214 | }; |
215 | |
216 | struct Assign: public Instruction |
217 | { |
218 | QString location; |
219 | QString expr; |
220 | QString content; |
221 | |
222 | Assign(const XmlLocation &xmlLocation): Instruction(xmlLocation) {} |
223 | void accept(NodeVisitor *visitor) override; |
224 | }; |
225 | |
226 | struct If: public Instruction |
227 | { |
228 | QStringList conditions; |
229 | InstructionSequences blocks; |
230 | |
231 | If(const XmlLocation &xmlLocation): Instruction(xmlLocation) {} |
232 | If *asIf() override { return this; } |
233 | void accept(NodeVisitor *visitor) override; |
234 | }; |
235 | |
236 | struct Foreach: public Instruction |
237 | { |
238 | QString array; |
239 | QString item; |
240 | QString index; |
241 | InstructionSequence block; |
242 | |
243 | Foreach(const XmlLocation &xmlLocation): Instruction(xmlLocation) {} |
244 | void accept(NodeVisitor *visitor) override; |
245 | }; |
246 | |
247 | struct Cancel: public Instruction |
248 | { |
249 | QString sendid; |
250 | QString sendidexpr; |
251 | |
252 | Cancel(const XmlLocation &xmlLocation): Instruction(xmlLocation) {} |
253 | void accept(NodeVisitor *visitor) override; |
254 | }; |
255 | |
256 | struct StateOrTransition: public Node |
257 | { |
258 | StateOrTransition(const XmlLocation &xmlLocation): Node(xmlLocation) {} |
259 | }; |
260 | |
261 | struct StateContainer |
262 | { |
263 | StateContainer() |
264 | : parent(nullptr) |
265 | {} |
266 | |
267 | StateContainer *parent; |
268 | |
269 | virtual ~StateContainer() {} |
270 | virtual void add(StateOrTransition *s) = 0; |
271 | virtual AbstractState *asAbstractState() { return nullptr; } |
272 | virtual State *asState() { return nullptr; } |
273 | virtual Scxml *asScxml() { return nullptr; } |
274 | }; |
275 | |
276 | struct AbstractState: public StateContainer |
277 | { |
278 | QString id; |
279 | |
280 | AbstractState *asAbstractState() override { return this; } |
281 | }; |
282 | |
283 | struct State: public AbstractState, public StateOrTransition |
284 | { |
285 | enum Type { Normal, Parallel, Final }; |
286 | |
287 | QStringList initial; |
288 | QVector<DataElement *> dataElements; |
289 | QVector<StateOrTransition *> children; |
290 | InstructionSequences onEntry; |
291 | InstructionSequences onExit; |
292 | DoneData *doneData; |
293 | QVector<Invoke *> invokes; |
294 | Type type; |
295 | |
296 | Transition *initialTransition; // when not set, it is filled during verification |
297 | |
298 | State(const XmlLocation &xmlLocation) |
299 | : StateOrTransition(xmlLocation) |
300 | , doneData(nullptr) |
301 | , type(Normal) |
302 | , initialTransition(nullptr) |
303 | {} |
304 | |
305 | void add(StateOrTransition *s) override |
306 | { |
307 | Q_ASSERT(s); |
308 | children.append(t: s); |
309 | } |
310 | |
311 | State *asState() override { return this; } |
312 | |
313 | void accept(NodeVisitor *visitor) override; |
314 | }; |
315 | |
316 | struct Transition: public StateOrTransition |
317 | { |
318 | enum Type { Internal, External, Synthetic }; |
319 | QStringList events; |
320 | QScopedPointer<QString> condition; |
321 | QStringList targets; |
322 | InstructionSequence instructionsOnTransition; |
323 | Type type; |
324 | |
325 | QVector<AbstractState *> targetStates; // when not set, it is filled during verification |
326 | |
327 | Transition(const XmlLocation &xmlLocation) |
328 | : StateOrTransition(xmlLocation) |
329 | , type(External) |
330 | {} |
331 | |
332 | Transition *asTransition() override { return this; } |
333 | |
334 | void accept(NodeVisitor *visitor) override; |
335 | }; |
336 | |
337 | struct HistoryState: public AbstractState, public StateOrTransition |
338 | { |
339 | enum Type { Deep, Shallow }; |
340 | Type type; |
341 | QVector<StateOrTransition *> children; |
342 | |
343 | HistoryState(const XmlLocation &xmlLocation) |
344 | : StateOrTransition(xmlLocation) |
345 | , type(Shallow) |
346 | {} |
347 | |
348 | void add(StateOrTransition *s) override |
349 | { |
350 | Q_ASSERT(s); |
351 | children.append(t: s); |
352 | } |
353 | |
354 | Transition *defaultConfiguration() |
355 | { return children.isEmpty() ? nullptr : children.first()->asTransition(); } |
356 | |
357 | HistoryState *asHistoryState() override { return this; } |
358 | void accept(NodeVisitor *visitor) override; |
359 | }; |
360 | |
361 | struct Scxml: public StateContainer, public Node |
362 | { |
363 | enum DataModelType { |
364 | NullDataModel, |
365 | JSDataModel, |
366 | CppDataModel |
367 | }; |
368 | enum BindingMethod { |
369 | EarlyBinding, |
370 | LateBinding |
371 | }; |
372 | |
373 | QStringList initial; |
374 | QString name; |
375 | DataModelType dataModel; |
376 | QString cppDataModelClassName; |
377 | QString ; |
378 | BindingMethod binding; |
379 | QVector<StateOrTransition *> children; |
380 | QVector<DataElement *> dataElements; |
381 | QScopedPointer<Script> script; |
382 | InstructionSequence initialSetup; |
383 | |
384 | Transition *initialTransition; |
385 | |
386 | Scxml(const XmlLocation &xmlLocation) |
387 | : Node(xmlLocation) |
388 | , dataModel(NullDataModel) |
389 | , binding(EarlyBinding) |
390 | , initialTransition(nullptr) |
391 | {} |
392 | |
393 | void add(StateOrTransition *s) override |
394 | { |
395 | Q_ASSERT(s); |
396 | children.append(t: s); |
397 | } |
398 | |
399 | Scxml *asScxml() override { return this; } |
400 | |
401 | void accept(NodeVisitor *visitor) override; |
402 | }; |
403 | |
404 | struct ScxmlDocument |
405 | { |
406 | const QString fileName; |
407 | Scxml *root; |
408 | QVector<AbstractState *> allStates; |
409 | QVector<Transition *> allTransitions; |
410 | QVector<Node *> allNodes; |
411 | QVector<InstructionSequence *> allSequences; |
412 | QVector<ScxmlDocument *> allSubDocuments; // weak pointers |
413 | bool isVerified; |
414 | |
415 | ScxmlDocument(const QString &fileName) |
416 | : fileName(fileName) |
417 | , root(nullptr) |
418 | , isVerified(false) |
419 | {} |
420 | |
421 | ~ScxmlDocument() |
422 | { |
423 | delete root; |
424 | qDeleteAll(c: allNodes); |
425 | qDeleteAll(c: allSequences); |
426 | } |
427 | |
428 | State *newState(StateContainer *parent, State::Type type, const XmlLocation &xmlLocation) |
429 | { |
430 | Q_ASSERT(parent); |
431 | State *s = newNode<State>(xmlLocation); |
432 | s->parent = parent; |
433 | s->type = type; |
434 | allStates.append(t: s); |
435 | parent->add(s); |
436 | return s; |
437 | } |
438 | |
439 | HistoryState *newHistoryState(StateContainer *parent, const XmlLocation &xmlLocation) |
440 | { |
441 | Q_ASSERT(parent); |
442 | HistoryState *s = newNode<HistoryState>(xmlLocation); |
443 | s->parent = parent; |
444 | allStates.append(t: s); |
445 | parent->add(s); |
446 | return s; |
447 | } |
448 | |
449 | Transition *newTransition(StateContainer *parent, const XmlLocation &xmlLocation) |
450 | { |
451 | Transition *t = newNode<Transition>(xmlLocation); |
452 | allTransitions.append(t); |
453 | if (parent != nullptr) { |
454 | parent->add(s: t); |
455 | } |
456 | return t; |
457 | } |
458 | |
459 | template<typename T> |
460 | T *newNode(const XmlLocation &xmlLocation) |
461 | { |
462 | T *node = new T(xmlLocation); |
463 | allNodes.append(node); |
464 | return node; |
465 | } |
466 | |
467 | InstructionSequence *newSequence(InstructionSequences *container) |
468 | { |
469 | Q_ASSERT(container); |
470 | InstructionSequence *is = new InstructionSequence; |
471 | allSequences.append(t: is); |
472 | container->append(t: is); |
473 | return is; |
474 | } |
475 | }; |
476 | |
477 | class Q_SCXML_EXPORT NodeVisitor |
478 | { |
479 | public: |
480 | virtual ~NodeVisitor(); |
481 | |
482 | virtual void visit(DataElement *) {} |
483 | virtual void visit(Param *) {} |
484 | virtual bool visit(DoneData *) { return true; } |
485 | virtual void endVisit(DoneData *) {} |
486 | virtual bool visit(Send *) { return true; } |
487 | virtual void endVisit(Send *) {} |
488 | virtual bool visit(Invoke *) { return true; } |
489 | virtual void endVisit(Invoke *) {} |
490 | virtual void visit(Raise *) {} |
491 | virtual void visit(Log *) {} |
492 | virtual void visit(Script *) {} |
493 | virtual void visit(Assign *) {} |
494 | virtual bool visit(If *) { return true; } |
495 | virtual void endVisit(If *) {} |
496 | virtual bool visit(Foreach *) { return true; } |
497 | virtual void endVisit(Foreach *) {} |
498 | virtual void visit(Cancel *) {} |
499 | virtual bool visit(State *) { return true; } |
500 | virtual void endVisit(State *) {} |
501 | virtual bool visit(Transition *) { return true; } |
502 | virtual void endVisit(Transition *) {} |
503 | virtual bool visit(HistoryState *) { return true; } |
504 | virtual void endVisit(HistoryState *) {} |
505 | virtual bool visit(Scxml *) { return true; } |
506 | virtual void endVisit(Scxml *) {} |
507 | |
508 | void visit(InstructionSequence *sequence) |
509 | { |
510 | Q_ASSERT(sequence); |
511 | for (Instruction *instruction : qAsConst(t&: *sequence)) { |
512 | Q_ASSERT(instruction); |
513 | instruction->accept(visitor: this); |
514 | } |
515 | } |
516 | |
517 | void visit(const QVector<DataElement *> &dataElements) |
518 | { |
519 | for (DataElement *dataElement : dataElements) { |
520 | Q_ASSERT(dataElement); |
521 | dataElement->accept(visitor: this); |
522 | } |
523 | } |
524 | |
525 | void visit(const QVector<StateOrTransition *> &children) |
526 | { |
527 | for (StateOrTransition *child : children) { |
528 | Q_ASSERT(child); |
529 | child->accept(visitor: this); |
530 | } |
531 | } |
532 | |
533 | void visit(const InstructionSequences &sequences) |
534 | { |
535 | for (InstructionSequence *sequence : sequences) { |
536 | Q_ASSERT(sequence); |
537 | visit(sequence); |
538 | } |
539 | } |
540 | |
541 | void visit(const QVector<Param *> ¶ms) |
542 | { |
543 | for (Param *param : params) { |
544 | Q_ASSERT(param); |
545 | param->accept(visitor: this); |
546 | } |
547 | } |
548 | }; |
549 | |
550 | } // DocumentModel namespace |
551 | |
552 | class Q_SCXML_EXPORT QScxmlCompilerPrivate |
553 | { |
554 | public: |
555 | static QScxmlCompilerPrivate *get(QScxmlCompiler *compiler); |
556 | |
557 | QScxmlCompilerPrivate(QXmlStreamReader *reader); |
558 | |
559 | bool verifyDocument(); |
560 | DocumentModel::ScxmlDocument *scxmlDocument() const; |
561 | |
562 | QString fileName() const; |
563 | void setFileName(const QString &fileName); |
564 | |
565 | QScxmlCompiler::Loader *loader() const; |
566 | void setLoader(QScxmlCompiler::Loader *loader); |
567 | |
568 | bool readDocument(); |
569 | void parseSubDocument(DocumentModel::Invoke *parentInvoke, |
570 | QXmlStreamReader *reader, |
571 | const QString &fileName); |
572 | bool parseSubElement(DocumentModel::Invoke *parentInvoke, |
573 | QXmlStreamReader *reader, |
574 | const QString &fileName); |
575 | QByteArray load(const QString &name, bool *ok); |
576 | |
577 | QVector<QScxmlError> errors() const; |
578 | |
579 | void addError(const QString &msg); |
580 | void addError(const DocumentModel::XmlLocation &location, const QString &msg); |
581 | QScxmlStateMachine *instantiateStateMachine() const; |
582 | void instantiateDataModel(QScxmlStateMachine *stateMachine) const; |
583 | |
584 | private: |
585 | DocumentModel::AbstractState *currentParent() const; |
586 | DocumentModel::XmlLocation xmlLocation() const; |
587 | bool maybeId(const QXmlStreamAttributes &attributes, QString *id); |
588 | DocumentModel::If *lastIf(); |
589 | bool checkAttributes(const QXmlStreamAttributes &attributes, |
590 | const QStringList &requiredNames, |
591 | const QStringList &optionalNames); |
592 | |
593 | bool preReadElementScxml(); |
594 | bool preReadElementState(); |
595 | bool preReadElementParallel(); |
596 | bool preReadElementInitial(); |
597 | bool preReadElementTransition(); |
598 | bool preReadElementFinal(); |
599 | bool preReadElementHistory(); |
600 | bool preReadElementOnEntry(); |
601 | bool preReadElementOnExit(); |
602 | bool preReadElementRaise(); |
603 | bool preReadElementIf(); |
604 | bool preReadElementElseIf(); |
605 | bool preReadElementElse(); |
606 | bool preReadElementForeach(); |
607 | bool preReadElementLog(); |
608 | bool preReadElementDataModel(); |
609 | bool preReadElementData(); |
610 | bool preReadElementAssign(); |
611 | bool preReadElementDoneData(); |
612 | bool preReadElementContent(); |
613 | bool preReadElementParam(); |
614 | bool preReadElementScript(); |
615 | bool preReadElementSend(); |
616 | bool preReadElementCancel(); |
617 | bool preReadElementInvoke(); |
618 | bool preReadElementFinalize(); |
619 | |
620 | bool postReadElementScxml(); |
621 | bool postReadElementState(); |
622 | bool postReadElementParallel(); |
623 | bool postReadElementInitial(); |
624 | bool postReadElementTransition(); |
625 | bool postReadElementFinal(); |
626 | bool postReadElementHistory(); |
627 | bool postReadElementOnEntry(); |
628 | bool postReadElementOnExit(); |
629 | bool postReadElementRaise(); |
630 | bool postReadElementIf(); |
631 | bool postReadElementElseIf(); |
632 | bool postReadElementElse(); |
633 | bool postReadElementForeach(); |
634 | bool postReadElementLog(); |
635 | bool postReadElementDataModel(); |
636 | bool postReadElementData(); |
637 | bool postReadElementAssign(); |
638 | bool postReadElementDoneData(); |
639 | bool postReadElementContent(); |
640 | bool postReadElementParam(); |
641 | bool postReadElementScript(); |
642 | bool postReadElementSend(); |
643 | bool postReadElementCancel(); |
644 | bool postReadElementInvoke(); |
645 | bool postReadElementFinalize(); |
646 | |
647 | bool readElement(); |
648 | |
649 | void resetDocument(); |
650 | void currentStateUp(); |
651 | bool flushInstruction(); |
652 | |
653 | private: |
654 | struct ParserState { |
655 | enum Kind { |
656 | Scxml, |
657 | State, |
658 | Parallel, |
659 | Transition, |
660 | Initial, |
661 | Final, |
662 | OnEntry, |
663 | OnExit, |
664 | History, |
665 | Raise, |
666 | If, |
667 | ElseIf, |
668 | Else, |
669 | Foreach, |
670 | Log, |
671 | DataModel, |
672 | Data, |
673 | Assign, |
674 | DoneData, |
675 | Content, |
676 | Param, |
677 | Script, |
678 | Send, |
679 | Cancel, |
680 | Invoke, |
681 | Finalize, |
682 | None |
683 | }; |
684 | Kind kind; |
685 | QString chars; |
686 | DocumentModel::Instruction *instruction; |
687 | DocumentModel::InstructionSequence *instructionContainer; |
688 | |
689 | bool collectChars(); |
690 | |
691 | ParserState(Kind someKind = None); |
692 | ~ParserState() { } |
693 | |
694 | bool validChild(ParserState::Kind child) const; |
695 | static bool validChild(ParserState::Kind parent, ParserState::Kind child); |
696 | static bool isExecutableContent(ParserState::Kind kind); |
697 | static Kind nameToParserStateKind(const QStringRef &name); |
698 | static QStringList requiredAttributes(Kind kind); |
699 | static QStringList optionalAttributes(Kind kind); |
700 | }; |
701 | |
702 | public: |
703 | class DefaultLoader: public QScxmlCompiler::Loader |
704 | { |
705 | public: |
706 | DefaultLoader(); |
707 | QByteArray load(const QString &name, |
708 | const QString &baseDir, |
709 | QStringList *errors) override final; |
710 | }; |
711 | |
712 | private: |
713 | bool checkAttributes(const QXmlStreamAttributes &attributes, QScxmlCompilerPrivate::ParserState::Kind kind); |
714 | ParserState ¤t(); |
715 | ParserState &previous(); |
716 | bool hasPrevious() const; |
717 | |
718 | private: |
719 | QString m_fileName; |
720 | QSet<QString> m_allIds; |
721 | |
722 | QScopedPointer<DocumentModel::ScxmlDocument> m_doc; |
723 | DocumentModel::StateContainer *m_currentState; |
724 | DefaultLoader m_defaultLoader; |
725 | QScxmlCompiler::Loader *m_loader; |
726 | |
727 | QXmlStreamReader *m_reader; |
728 | QVector<ParserState> m_stack; |
729 | QVector<QScxmlError> m_errors; |
730 | }; |
731 | |
732 | QT_END_NAMESPACE |
733 | |
734 | #endif // QSCXMLCOMPILER_P_H |
735 | |