Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
cxfa_fmparser.cpp
Go to the documentation of this file.
1// Copyright 2014 The PDFium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7#include "xfa/fxfa/formcalc/cxfa_fmparser.h"
8
9#include <utility>
10#include <vector>
11
12#include "core/fxcrt/autorestorer.h"
13#include "v8/include/cppgc/heap.h"
14
15namespace {
16
17constexpr unsigned int kMaxParseDepth = 1250;
18constexpr unsigned int kMaxPostExpressions = 256;
19constexpr unsigned int kMaxExpressionListSize = 10000;
20
21} // namespace
22
24 : m_heap(pHeap), m_lexer(pLexer), m_max_parse_depth(kMaxParseDepth) {}
25
26CXFA_FMParser::~CXFA_FMParser() = default;
27
29 m_token = m_lexer->NextToken();
30 if (HasError())
31 return nullptr;
32
33 auto expressions = ParseExpressionList();
34 if (HasError())
35 return nullptr;
36
37 // We failed to parse all of the input so something has gone wrong.
38 if (!m_lexer->IsComplete())
39 return nullptr;
40
41 return cppgc::MakeGarbageCollected<CXFA_FMAST>(m_heap->GetAllocationHandle(),
42 std::move(expressions));
43}
44
45bool CXFA_FMParser::NextToken() {
46 if (HasError())
47 return false;
48
49 m_token = m_lexer->NextToken();
50 while (!HasError() && m_token.GetType() == TOKreserver)
51 m_token = m_lexer->NextToken();
52 return !HasError();
53}
54
55bool CXFA_FMParser::CheckThenNext(XFA_FM_TOKEN op) {
56 if (HasError())
57 return false;
58
59 if (m_token.GetType() != op) {
60 m_error = true;
61 return false;
62 }
63 return NextToken();
64}
65
66bool CXFA_FMParser::IncrementParseDepthAndCheck() {
67 return ++m_parse_depth < m_max_parse_depth;
68}
69
70std::vector<cppgc::Member<CXFA_FMExpression>>
71CXFA_FMParser::ParseExpressionList() {
72 AutoRestorer<unsigned long> restorer(&m_parse_depth);
73 if (HasError() || !IncrementParseDepthAndCheck())
74 return std::vector<cppgc::Member<CXFA_FMExpression>>();
75
76 std::vector<cppgc::Member<CXFA_FMExpression>> expressions;
77 while (!HasError()) {
78 if (m_token.GetType() == TOKeof || m_token.GetType() == TOKendfunc ||
79 m_token.GetType() == TOKendif || m_token.GetType() == TOKelseif ||
80 m_token.GetType() == TOKelse || m_token.GetType() == TOKendwhile ||
81 m_token.GetType() == TOKendfor || m_token.GetType() == TOKend ||
82 m_token.GetType() == TOKendfunc || m_token.GetType() == TOKreserver) {
83 break;
84 }
85
86 CXFA_FMExpression* expr =
87 m_token.GetType() == TOKfunc ? ParseFunction() : ParseExpression();
88 if (!expr) {
89 m_error = true;
90 return std::vector<cppgc::Member<CXFA_FMExpression>>();
91 }
92 if (expressions.size() >= kMaxExpressionListSize) {
93 m_error = true;
94 return std::vector<cppgc::Member<CXFA_FMExpression>>();
95 }
96 expressions.push_back(expr);
97 }
98 return expressions;
99}
100
101// Func := 'func' Identifier '(' ParameterList ')' do ExpressionList 'endfunc'
102// ParamterList := (Not actually defined in the grammar) .....
103// (Identifier (',' Identifier)*)?
104CXFA_FMExpression* CXFA_FMParser::ParseFunction() {
105 AutoRestorer<unsigned long> restorer(&m_parse_depth);
106 if (HasError() || !IncrementParseDepthAndCheck())
107 return nullptr;
108 if (!CheckThenNext(TOKfunc))
109 return nullptr;
110 if (m_token.GetType() != TOKidentifier)
111 return nullptr;
112
113 WideString ident(m_token.GetString());
114 if (!NextToken())
115 return nullptr;
116 if (!CheckThenNext(TOKlparen))
117 return nullptr;
118
119 std::vector<WideString> arguments;
120 bool last_was_comma = false;
121 while (true) {
122 if (m_token.GetType() == TOKrparen)
123 break;
124 if (m_token.GetType() != TOKidentifier)
125 return nullptr;
126
127 last_was_comma = false;
128
129 arguments.emplace_back(m_token.GetString());
130 if (!NextToken())
131 return nullptr;
132 if (m_token.GetType() != TOKcomma)
133 continue;
134
135 last_was_comma = true;
136 if (!NextToken())
137 return nullptr;
138 }
139 if (last_was_comma || !CheckThenNext(TOKrparen))
140 return nullptr;
141 if (!CheckThenNext(TOKdo))
142 return nullptr;
143
144 std::vector<cppgc::Member<CXFA_FMExpression>> expressions;
145 if (m_token.GetType() != TOKendfunc)
146 expressions = ParseExpressionList();
147
148 if (!CheckThenNext(TOKendfunc))
149 return nullptr;
150
151 return cppgc::MakeGarbageCollected<CXFA_FMFunctionDefinition>(
152 m_heap->GetAllocationHandle(), std::move(ident), std::move(arguments),
153 std::move(expressions));
154}
155
156// Expression := IfExpression | WhileExpression | ForExpression |
157// ForEachExpression | AssignmentExpression |
158// DeclarationExpression | SimpleExpression
159CXFA_FMExpression* CXFA_FMParser::ParseExpression() {
160 AutoRestorer<unsigned long> restorer(&m_parse_depth);
161 if (HasError() || !IncrementParseDepthAndCheck())
162 return nullptr;
163
164 CXFA_FMExpression* expr = nullptr;
165 switch (m_token.GetType()) {
166 case TOKvar:
167 expr = ParseDeclarationExpression();
168 break;
169 case TOKnull:
170 case TOKnumber:
171 case TOKstring:
172 case TOKplus:
173 case TOKminus:
174 case TOKksnot:
175 case TOKidentifier:
176 case TOKlparen:
177 expr = ParseExpExpression();
178 break;
179 case TOKif:
180 expr = ParseIfExpression();
181 break;
182 case TOKwhile:
183 expr = ParseWhileExpression();
184 break;
185 case TOKfor:
186 expr = ParseForExpression();
187 break;
188 case TOKforeach:
189 expr = ParseForeachExpression();
190 break;
191 case TOKdo:
192 expr = ParseDoExpression();
193 break;
194 case TOKbreak:
195 expr = cppgc::MakeGarbageCollected<CXFA_FMBreakExpression>(
196 m_heap->GetAllocationHandle());
197 if (!NextToken())
198 return nullptr;
199 break;
200 case TOKcontinue:
201 expr = cppgc::MakeGarbageCollected<CXFA_FMContinueExpression>(
202 m_heap->GetAllocationHandle());
203 if (!NextToken())
204 return nullptr;
205 break;
206 default:
207 return nullptr;
208 }
209 return expr;
210}
211
212// Declaration := 'var' Variable | 'var' Variable '=' SimpleExpression |
213// 'Func' Identifier '(' ParameterList ')' do ExpressionList 'EndFunc'
214// TODO(dsinclair): We appear to be handling the 'func' case elsewhere.
215CXFA_FMExpression* CXFA_FMParser::ParseDeclarationExpression() {
216 AutoRestorer<unsigned long> restorer(&m_parse_depth);
217 if (HasError() || !IncrementParseDepthAndCheck())
218 return nullptr;
219
220 if (!NextToken() || m_token.GetType() != TOKidentifier)
221 return nullptr;
222
223 WideString ident(m_token.GetString());
224 if (!NextToken())
225 return nullptr;
226
227 CXFA_FMSimpleExpression* expr = nullptr;
228 if (m_token.GetType() == TOKassign) {
229 if (!NextToken())
230 return nullptr;
231
232 expr = ParseSimpleExpression();
233 if (!expr)
234 return nullptr;
235 }
236
237 return cppgc::MakeGarbageCollected<CXFA_FMVarExpression>(
238 m_heap->GetAllocationHandle(), std::move(ident), expr);
239}
240
241// SimpleExpression := LogicalOrExpression
242CXFA_FMSimpleExpression* CXFA_FMParser::ParseSimpleExpression() {
243 if (HasError())
244 return nullptr;
245
246 return ParseLogicalOrExpression();
247}
248
249// Exp := SimpleExpression ( '=' SimpleExpression )?
250CXFA_FMExpression* CXFA_FMParser::ParseExpExpression() {
251 AutoRestorer<unsigned long> restorer(&m_parse_depth);
252 if (HasError() || !IncrementParseDepthAndCheck())
253 return nullptr;
254
255 CXFA_FMSimpleExpression* pExp1 = ParseSimpleExpression();
256 if (!pExp1)
257 return nullptr;
258
259 if (m_token.GetType() == TOKassign) {
260 if (!NextToken())
261 return nullptr;
262
263 CXFA_FMSimpleExpression* pExp2 = ParseSimpleExpression();
264 if (!pExp2)
265 return nullptr;
266
267 pExp1 = cppgc::MakeGarbageCollected<CXFA_FMAssignExpression>(
268 m_heap->GetAllocationHandle(), TOKassign, pExp1, pExp2);
269 }
270 return cppgc::MakeGarbageCollected<CXFA_FMExpExpression>(
271 m_heap->GetAllocationHandle(), pExp1);
272}
273
274// LogicalOr := LogicalAndExpression |
275// LogicalOrExpression LogicalOrOperator LogicalAndExpression
276CXFA_FMSimpleExpression* CXFA_FMParser::ParseLogicalOrExpression() {
277 AutoRestorer<unsigned long> restorer(&m_parse_depth);
278 if (HasError() || !IncrementParseDepthAndCheck())
279 return nullptr;
280
281 CXFA_FMSimpleExpression* e1 = ParseLogicalAndExpression();
282 if (!e1)
283 return nullptr;
284
285 while (true) {
286 if (!IncrementParseDepthAndCheck())
287 return nullptr;
288
289 switch (m_token.GetType()) {
290 case TOKor:
291 case TOKksor: {
292 if (!NextToken())
293 return nullptr;
294 CXFA_FMSimpleExpression* e2 = ParseLogicalAndExpression();
295 if (!e2)
296 return nullptr;
297 e1 = cppgc::MakeGarbageCollected<CXFA_FMLogicalOrExpression>(
298 m_heap->GetAllocationHandle(), TOKor, e1, e2);
299 break;
300 }
301 default:
302 return e1;
303 }
304 }
305}
306
307// LogicalAnd := EqualityExpression |
308// LogicalAndExpression LogicalAndOperator EqualityExpression
309CXFA_FMSimpleExpression* CXFA_FMParser::ParseLogicalAndExpression() {
310 AutoRestorer<unsigned long> restorer(&m_parse_depth);
311 if (HasError() || !IncrementParseDepthAndCheck())
312 return nullptr;
313
314 CXFA_FMSimpleExpression* e1 = ParseEqualityExpression();
315 if (!e1)
316 return nullptr;
317
318 while (true) {
319 if (!IncrementParseDepthAndCheck())
320 return nullptr;
321
322 switch (m_token.GetType()) {
323 case TOKand:
324 case TOKksand: {
325 if (!NextToken())
326 return nullptr;
327 CXFA_FMSimpleExpression* e2 = ParseEqualityExpression();
328 if (!e2)
329 return nullptr;
330 e1 = cppgc::MakeGarbageCollected<CXFA_FMLogicalAndExpression>(
331 m_heap->GetAllocationHandle(), TOKand, e1, e2);
332 break;
333 }
334 default:
335 return e1;
336 }
337 }
338}
339
340// Equality := RelationExpression |
341// EqualityExpression EqulaityOperator RelationalExpression
342CXFA_FMSimpleExpression* CXFA_FMParser::ParseEqualityExpression() {
343 AutoRestorer<unsigned long> restorer(&m_parse_depth);
344 if (HasError() || !IncrementParseDepthAndCheck())
345 return nullptr;
346
347 CXFA_FMSimpleExpression* e1 = ParseRelationalExpression();
348 if (!e1)
349 return nullptr;
350
351 while (true) {
352 if (!IncrementParseDepthAndCheck())
353 return nullptr;
354
355 switch (m_token.GetType()) {
356 case TOKeq:
357 case TOKkseq: {
358 if (!NextToken())
359 return nullptr;
360 CXFA_FMSimpleExpression* e2 = ParseRelationalExpression();
361 if (!e2)
362 return nullptr;
363 e1 = cppgc::MakeGarbageCollected<CXFA_FMEqualExpression>(
364 m_heap->GetAllocationHandle(), TOKeq, e1, e2);
365 break;
366 }
367 case TOKne:
368 case TOKksne: {
369 if (!NextToken())
370 return nullptr;
371 CXFA_FMSimpleExpression* e2 = ParseRelationalExpression();
372 if (!e2)
373 return nullptr;
374 e1 = cppgc::MakeGarbageCollected<CXFA_FMNotEqualExpression>(
375 m_heap->GetAllocationHandle(), TOKne, e1, e2);
376 break;
377 }
378 default:
379 return e1;
380 }
381 }
382}
383
384// Relational := AdditiveExpression |
385// RelationalExpression RelationalOperator AdditiveExpression
386CXFA_FMSimpleExpression* CXFA_FMParser::ParseRelationalExpression() {
387 AutoRestorer<unsigned long> restorer(&m_parse_depth);
388 if (HasError() || !IncrementParseDepthAndCheck())
389 return nullptr;
390
391 CXFA_FMSimpleExpression* e1 = ParseAdditiveExpression();
392 if (!e1)
393 return nullptr;
394
395 while (true) {
396 if (!IncrementParseDepthAndCheck())
397 return nullptr;
398
399 switch (m_token.GetType()) {
400 case TOKlt:
401 case TOKkslt: {
402 if (!NextToken())
403 return nullptr;
404 CXFA_FMSimpleExpression* e2 = ParseAdditiveExpression();
405 if (!e2)
406 return nullptr;
407 e1 = cppgc::MakeGarbageCollected<CXFA_FMLtExpression>(
408 m_heap->GetAllocationHandle(), TOKlt, e1, e2);
409 break;
410 }
411 case TOKgt:
412 case TOKksgt: {
413 if (!NextToken())
414 return nullptr;
415 CXFA_FMSimpleExpression* e2 = ParseAdditiveExpression();
416 if (!e2)
417 return nullptr;
418 e1 = cppgc::MakeGarbageCollected<CXFA_FMGtExpression>(
419 m_heap->GetAllocationHandle(), TOKgt, e1, e2);
420 break;
421 }
422 case TOKle:
423 case TOKksle: {
424 if (!NextToken())
425 return nullptr;
426 CXFA_FMSimpleExpression* e2 = ParseAdditiveExpression();
427 if (!e2)
428 return nullptr;
429 e1 = cppgc::MakeGarbageCollected<CXFA_FMLeExpression>(
430 m_heap->GetAllocationHandle(), TOKle, e1, e2);
431 break;
432 }
433 case TOKge:
434 case TOKksge: {
435 if (!NextToken())
436 return nullptr;
437 CXFA_FMSimpleExpression* e2 = ParseAdditiveExpression();
438 if (!e2)
439 return nullptr;
440 e1 = cppgc::MakeGarbageCollected<CXFA_FMGeExpression>(
441 m_heap->GetAllocationHandle(), TOKge, e1, e2);
442 break;
443 }
444 default:
445 return e1;
446 }
447 }
448}
449
450// Additive := MultiplicativeExpression |
451// AdditiveExpression AdditiveOperator MultiplicativeExpression
452CXFA_FMSimpleExpression* CXFA_FMParser::ParseAdditiveExpression() {
453 AutoRestorer<unsigned long> restorer(&m_parse_depth);
454 if (HasError() || !IncrementParseDepthAndCheck())
455 return nullptr;
456
457 CXFA_FMSimpleExpression* e1 = ParseMultiplicativeExpression();
458 if (!e1)
459 return nullptr;
460
461 while (true) {
462 if (!IncrementParseDepthAndCheck())
463 return nullptr;
464
465 switch (m_token.GetType()) {
466 case TOKplus: {
467 if (!NextToken())
468 return nullptr;
469 CXFA_FMSimpleExpression* e2 = ParseMultiplicativeExpression();
470 if (!e2)
471 return nullptr;
472 e1 = cppgc::MakeGarbageCollected<CXFA_FMPlusExpression>(
473 m_heap->GetAllocationHandle(), TOKplus, e1, e2);
474 break;
475 }
476 case TOKminus: {
477 if (!NextToken())
478 return nullptr;
479 CXFA_FMSimpleExpression* e2 = ParseMultiplicativeExpression();
480 if (!e2)
481 return nullptr;
482 e1 = cppgc::MakeGarbageCollected<CXFA_FMMinusExpression>(
483 m_heap->GetAllocationHandle(), TOKminus, e1, e2);
484 break;
485 }
486 default:
487 return e1;
488 }
489 }
490}
491
492// Multiplicative := UnaryExpression |
493// MultiplicateExpression MultiplicativeOperator UnaryExpression
494CXFA_FMSimpleExpression* CXFA_FMParser::ParseMultiplicativeExpression() {
495 AutoRestorer<unsigned long> restorer(&m_parse_depth);
496 if (HasError() || !IncrementParseDepthAndCheck())
497 return nullptr;
498
499 CXFA_FMSimpleExpression* e1 = ParseUnaryExpression();
500 if (!e1)
501 return nullptr;
502
503 while (true) {
504 if (!IncrementParseDepthAndCheck())
505 return nullptr;
506
507 switch (m_token.GetType()) {
508 case TOKmul: {
509 if (!NextToken())
510 return nullptr;
511 CXFA_FMSimpleExpression* e2 = ParseUnaryExpression();
512 if (!e2)
513 return nullptr;
514 e1 = cppgc::MakeGarbageCollected<CXFA_FMMulExpression>(
515 m_heap->GetAllocationHandle(), TOKmul, e1, e2);
516 break;
517 }
518 case TOKdiv: {
519 if (!NextToken())
520 return nullptr;
521 CXFA_FMSimpleExpression* e2 = ParseUnaryExpression();
522 if (!e2)
523 return nullptr;
524 e1 = cppgc::MakeGarbageCollected<CXFA_FMDivExpression>(
525 m_heap->GetAllocationHandle(), TOKdiv, e1, e2);
526 break;
527 }
528 default:
529 return e1;
530 }
531 }
532}
533
534// Unary := PrimaryExpression | UnaryOperator UnaryExpression
535CXFA_FMSimpleExpression* CXFA_FMParser::ParseUnaryExpression() {
536 AutoRestorer<unsigned long> restorer(&m_parse_depth);
537 if (HasError() || !IncrementParseDepthAndCheck())
538 return nullptr;
539
540 switch (m_token.GetType()) {
541 case TOKplus: {
542 if (!NextToken())
543 return nullptr;
544 CXFA_FMSimpleExpression* expr = ParseUnaryExpression();
545 if (!expr)
546 return nullptr;
547 return cppgc::MakeGarbageCollected<CXFA_FMPosExpression>(
548 m_heap->GetAllocationHandle(), expr);
549 }
550 case TOKminus: {
551 if (!NextToken())
552 return nullptr;
553 CXFA_FMSimpleExpression* expr = ParseUnaryExpression();
554 if (!expr)
555 return nullptr;
556 return cppgc::MakeGarbageCollected<CXFA_FMNegExpression>(
557 m_heap->GetAllocationHandle(), expr);
558 }
559 case TOKksnot: {
560 if (!NextToken())
561 return nullptr;
562 CXFA_FMSimpleExpression* expr = ParseUnaryExpression();
563 if (!expr)
564 return nullptr;
565 return cppgc::MakeGarbageCollected<CXFA_FMNotExpression>(
566 m_heap->GetAllocationHandle(), expr);
567 }
568 default:
569 return ParsePrimaryExpression();
570 }
571}
572
573// Primary := Literal | FunctionCall | Accessor ('.*' )? |
574// '(' SimpleExpression ')'
575CXFA_FMSimpleExpression* CXFA_FMParser::ParsePrimaryExpression() {
576 AutoRestorer<unsigned long> restorer(&m_parse_depth);
577 if (HasError() || !IncrementParseDepthAndCheck())
578 return nullptr;
579
580 CXFA_FMSimpleExpression* expr = ParseLiteral();
581 if (expr)
582 return NextToken() ? expr : nullptr;
583
584 switch (m_token.GetType()) {
585 case TOKidentifier: {
586 WideString wsIdentifier(m_token.GetString());
587 if (!NextToken())
588 return nullptr;
589 if (m_token.GetType() == TOKlbracket) {
590 CXFA_FMSimpleExpression* s = ParseIndexExpression();
591 if (!s)
592 return nullptr;
593 expr = cppgc::MakeGarbageCollected<CXFA_FMDotAccessorExpression>(
594 m_heap->GetAllocationHandle(), nullptr, TOKdot,
595 std::move(wsIdentifier), s);
596 if (!expr)
597 return nullptr;
598 if (!NextToken())
599 return nullptr;
600 } else {
601 expr = cppgc::MakeGarbageCollected<CXFA_FMIdentifierExpression>(
602 m_heap->GetAllocationHandle(), wsIdentifier);
603 }
604 break;
605 }
606 case TOKlparen: {
607 expr = ParseParenExpression();
608 if (!expr)
609 return nullptr;
610 break;
611 }
612 default:
613 return nullptr;
614 }
615 return ParsePostExpression(expr);
616}
617
618// Literal := String | Number | Null
619CXFA_FMSimpleExpression* CXFA_FMParser::ParseLiteral() {
620 switch (m_token.GetType()) {
621 case TOKnumber:
622 return cppgc::MakeGarbageCollected<CXFA_FMNumberExpression>(
623 m_heap->GetAllocationHandle(), WideString(m_token.GetString()));
624 case TOKstring:
625 return cppgc::MakeGarbageCollected<CXFA_FMStringExpression>(
626 m_heap->GetAllocationHandle(), WideString(m_token.GetString()));
627 case TOKnull:
628 return cppgc::MakeGarbageCollected<CXFA_FMNullExpression>(
629 m_heap->GetAllocationHandle());
630 default:
631 return nullptr;
632 }
633}
634
635// TODO(dsinclair): Make this match up to the grammar
636// I believe this is parsing the accessor ( '.' | '..' | '.#' )
637CXFA_FMSimpleExpression* CXFA_FMParser::ParsePostExpression(
639 AutoRestorer<unsigned long> restorer(&m_parse_depth);
640 if (HasError() || !IncrementParseDepthAndCheck())
641 return nullptr;
642
643 size_t expr_count = 0;
644 while (true) {
645 ++expr_count;
646 // Limit the number of expressions allowed in the post expression statement.
647 // If we don't do this then its possible to generate a stack overflow
648 // by having a very large number of things like .. expressions.
649 if (expr_count > kMaxPostExpressions)
650 return nullptr;
651
652 switch (m_token.GetType()) {
653 case TOKlparen: {
654 absl::optional<std::vector<cppgc::Member<CXFA_FMSimpleExpression>>>
655 expressions = ParseArgumentList();
656 if (!expressions.has_value())
657 return nullptr;
658
659 expr = cppgc::MakeGarbageCollected<CXFA_FMCallExpression>(
660 m_heap->GetAllocationHandle(), expr, std::move(expressions.value()),
661 false);
662 if (!NextToken())
663 return nullptr;
664 if (m_token.GetType() != TOKlbracket)
665 continue;
666
667 CXFA_FMSimpleExpression* s = ParseIndexExpression();
668 if (!s)
669 return nullptr;
670
671 expr = cppgc::MakeGarbageCollected<CXFA_FMDotAccessorExpression>(
672 m_heap->GetAllocationHandle(), expr, TOKcall, WideString(), s);
673 break;
674 }
675 case TOKdot: {
676 if (!NextToken())
677 return nullptr;
678 if (m_token.GetType() != TOKidentifier)
679 return nullptr;
680
681 WideString tempStr(m_token.GetString());
682 if (!NextToken())
683 return nullptr;
684 if (m_token.GetType() == TOKlparen) {
685 absl::optional<std::vector<cppgc::Member<CXFA_FMSimpleExpression>>>
686 expressions = ParseArgumentList();
687 if (!expressions.has_value())
688 return nullptr;
689
690 auto* pIdentifier =
691 cppgc::MakeGarbageCollected<CXFA_FMIdentifierExpression>(
692 m_heap->GetAllocationHandle(), std::move(tempStr));
693 auto* pExpCall = cppgc::MakeGarbageCollected<CXFA_FMCallExpression>(
694 m_heap->GetAllocationHandle(), pIdentifier,
695 std::move(expressions.value()), true);
696 expr = cppgc::MakeGarbageCollected<CXFA_FMMethodCallExpression>(
697 m_heap->GetAllocationHandle(), expr, pExpCall);
698 if (!NextToken())
699 return nullptr;
700 if (m_token.GetType() != TOKlbracket)
701 continue;
702
703 CXFA_FMSimpleExpression* s = ParseIndexExpression();
704 if (!s)
705 return nullptr;
706
707 expr = cppgc::MakeGarbageCollected<CXFA_FMDotAccessorExpression>(
708 m_heap->GetAllocationHandle(), expr, TOKcall, WideString(), s);
709 } else if (m_token.GetType() == TOKlbracket) {
710 CXFA_FMSimpleExpression* s = ParseIndexExpression();
711 if (!s)
712 return nullptr;
713
714 expr = cppgc::MakeGarbageCollected<CXFA_FMDotAccessorExpression>(
715 m_heap->GetAllocationHandle(), expr, TOKdot, std::move(tempStr),
716 s);
717 } else {
718 auto* subexpr = cppgc::MakeGarbageCollected<CXFA_FMIndexExpression>(
719 m_heap->GetAllocationHandle(),
720 CXFA_FMIndexExpression::AccessorIndex::kNoIndex, nullptr, false);
721 expr = cppgc::MakeGarbageCollected<CXFA_FMDotAccessorExpression>(
722 m_heap->GetAllocationHandle(), expr, TOKdot, std::move(tempStr),
723 subexpr);
724 continue;
725 }
726 break;
727 }
728 case TOKdotdot: {
729 if (!NextToken())
730 return nullptr;
731 if (m_token.GetType() != TOKidentifier)
732 return nullptr;
733
734 WideString tempStr(m_token.GetString());
735 if (!NextToken())
736 return nullptr;
737 if (m_token.GetType() == TOKlbracket) {
738 CXFA_FMSimpleExpression* s = ParseIndexExpression();
739 if (!s)
740 return nullptr;
741
742 expr = cppgc::MakeGarbageCollected<CXFA_FMDotDotAccessorExpression>(
743 m_heap->GetAllocationHandle(), expr, TOKdotdot,
744 std::move(tempStr), s);
745 } else {
746 auto* subexpr = cppgc::MakeGarbageCollected<CXFA_FMIndexExpression>(
747 m_heap->GetAllocationHandle(),
748 CXFA_FMIndexExpression::AccessorIndex::kNoIndex, nullptr, false);
749 expr = cppgc::MakeGarbageCollected<CXFA_FMDotDotAccessorExpression>(
750 m_heap->GetAllocationHandle(), expr, TOKdotdot,
751 std::move(tempStr), subexpr);
752 continue;
753 }
754 break;
755 }
756 case TOKdotscream: {
757 if (!NextToken())
758 return nullptr;
759 if (m_token.GetType() != TOKidentifier)
760 return nullptr;
761
762 WideString tempStr(m_token.GetString());
763 if (!NextToken())
764 return nullptr;
765
766 if (m_token.GetType() != TOKlbracket) {
767 auto* subexpr = cppgc::MakeGarbageCollected<CXFA_FMIndexExpression>(
768 m_heap->GetAllocationHandle(),
769 CXFA_FMIndexExpression::AccessorIndex::kNoIndex, nullptr, false);
770 expr = cppgc::MakeGarbageCollected<CXFA_FMDotAccessorExpression>(
771 m_heap->GetAllocationHandle(), expr, TOKdotscream,
772 std::move(tempStr), subexpr);
773 continue;
774 }
775
776 CXFA_FMSimpleExpression* s = ParseIndexExpression();
777 if (!s)
778 return nullptr;
779
780 expr = cppgc::MakeGarbageCollected<CXFA_FMDotAccessorExpression>(
781 m_heap->GetAllocationHandle(), expr, TOKdotscream,
782 std::move(tempStr), s);
783 break;
784 }
785 case TOKdotstar: {
786 auto* subexpr = cppgc::MakeGarbageCollected<CXFA_FMIndexExpression>(
787 m_heap->GetAllocationHandle(),
788 CXFA_FMIndexExpression::AccessorIndex::kNoIndex, nullptr, false);
789 expr = cppgc::MakeGarbageCollected<CXFA_FMDotAccessorExpression>(
790 m_heap->GetAllocationHandle(), expr, TOKdotstar, L"*", subexpr);
791 break;
792 }
793 default:
794 return expr;
795 }
796 if (!NextToken())
797 return nullptr;
798 }
799}
800
801// Argument lists are zero or more comma seperated simple expressions found
802// between '(' and ')'
803absl::optional<std::vector<cppgc::Member<CXFA_FMSimpleExpression>>>
804CXFA_FMParser::ParseArgumentList() {
805 if (m_token.GetType() != TOKlparen || !NextToken())
806 return absl::nullopt;
807
808 std::vector<cppgc::Member<CXFA_FMSimpleExpression>> expressions;
809 bool first_arg = true;
810 while (m_token.GetType() != TOKrparen) {
811 if (first_arg) {
812 first_arg = false;
813 } else {
814 if (m_token.GetType() != TOKcomma || !NextToken())
815 return absl::nullopt;
816 }
817
818 CXFA_FMSimpleExpression* exp = ParseSimpleExpression();
819 if (!exp)
820 return absl::nullopt;
821
822 expressions.push_back(exp);
823 if (expressions.size() > kMaxPostExpressions)
824 return absl::nullopt;
825 }
826
827 return expressions;
828}
829
830// Index := '[' ('*' | '+' SimpleExpression | '-' SimpleExpression) ']'
831CXFA_FMSimpleExpression* CXFA_FMParser::ParseIndexExpression() {
832 AutoRestorer<unsigned long> restorer(&m_parse_depth);
833 if (HasError() || !IncrementParseDepthAndCheck())
834 return nullptr;
835 if (!CheckThenNext(TOKlbracket))
836 return nullptr;
837
838 if (m_token.GetType() == TOKmul) {
839 auto* pExp = cppgc::MakeGarbageCollected<CXFA_FMIndexExpression>(
840 m_heap->GetAllocationHandle(),
841 CXFA_FMIndexExpression::AccessorIndex::kNoRelativeIndex, nullptr, true);
842 if (!pExp || !NextToken())
843 return nullptr;
844
845 // TODO(dsinclair): This should CheckThenNext(TOKrbracket) but need to clean
846 // up the callsites.
847 if (m_token.GetType() != TOKrbracket)
848 return nullptr;
849 return pExp;
850 }
851
852 CXFA_FMIndexExpression::AccessorIndex accessorIndex =
853 CXFA_FMIndexExpression::AccessorIndex::kNoRelativeIndex;
854 if (m_token.GetType() == TOKplus) {
855 accessorIndex = CXFA_FMIndexExpression::AccessorIndex::kPositiveIndex;
856 if (!NextToken())
857 return nullptr;
858 } else if (m_token.GetType() == TOKminus) {
859 accessorIndex = CXFA_FMIndexExpression::AccessorIndex::kNegativeIndex;
860 if (!NextToken())
861 return nullptr;
862 }
863
864 CXFA_FMSimpleExpression* s = ParseSimpleExpression();
865 if (!s)
866 return nullptr;
867 if (m_token.GetType() != TOKrbracket)
868 return nullptr;
869
870 return cppgc::MakeGarbageCollected<CXFA_FMIndexExpression>(
871 m_heap->GetAllocationHandle(), accessorIndex, s, false);
872}
873
874// Paren := '(' SimpleExpression ')'
875CXFA_FMSimpleExpression* CXFA_FMParser::ParseParenExpression() {
876 AutoRestorer<unsigned long> restorer(&m_parse_depth);
877 if (HasError() || !IncrementParseDepthAndCheck())
878 return nullptr;
879
880 if (!CheckThenNext(TOKlparen))
881 return nullptr;
882 if (m_token.GetType() == TOKrparen)
883 return nullptr;
884
885 CXFA_FMSimpleExpression* pExp1 = ParseSimpleExpression();
886 if (!pExp1)
887 return nullptr;
888
889 if (!CheckThenNext(TOKrparen))
890 return nullptr;
891 return pExp1;
892}
893
894// If := 'if' '(' SimpleExpression ')' 'then' ExpressionList
895// ('elseif' '(' SimpleExpression ')' 'then' ExpressionList)*
896// ('else' ExpressionList)?
897// 'endif'
898CXFA_FMExpression* CXFA_FMParser::ParseIfExpression() {
899 AutoRestorer<unsigned long> restorer(&m_parse_depth);
900 if (HasError() || !IncrementParseDepthAndCheck())
901 return nullptr;
902
903 if (!CheckThenNext(TOKif))
904 return nullptr;
905
906 CXFA_FMSimpleExpression* pCondition = ParseParenExpression();
907 if (!pCondition)
908 return nullptr;
909 if (!CheckThenNext(TOKthen))
910 return nullptr;
911
912 auto* pIfExpressions = cppgc::MakeGarbageCollected<CXFA_FMBlockExpression>(
913 m_heap->GetAllocationHandle(), ParseExpressionList());
914
915 std::vector<cppgc::Member<CXFA_FMIfExpression>> pElseIfExpressions;
916 while (m_token.GetType() == TOKelseif) {
917 if (!NextToken())
918 return nullptr;
919
920 auto* elseIfCondition = ParseParenExpression();
921 if (!elseIfCondition)
922 return nullptr;
923 if (!CheckThenNext(TOKthen))
924 return nullptr;
925
926 auto elseIfExprs = ParseExpressionList();
927 pElseIfExpressions.push_back(
928 cppgc::MakeGarbageCollected<CXFA_FMIfExpression>(
929 m_heap->GetAllocationHandle(), elseIfCondition,
930 cppgc::MakeGarbageCollected<CXFA_FMBlockExpression>(
931 m_heap->GetAllocationHandle(), std::move(elseIfExprs)),
932 std::vector<cppgc::Member<CXFA_FMIfExpression>>(), nullptr));
933 }
934
935 CXFA_FMExpression* pElseExpression = nullptr;
936 if (m_token.GetType() == TOKelse) {
937 if (!NextToken())
938 return nullptr;
939
940 pElseExpression = cppgc::MakeGarbageCollected<CXFA_FMBlockExpression>(
941 m_heap->GetAllocationHandle(), ParseExpressionList());
942 }
943 if (!CheckThenNext(TOKendif))
944 return nullptr;
945
946 return cppgc::MakeGarbageCollected<CXFA_FMIfExpression>(
947 m_heap->GetAllocationHandle(), pCondition, pIfExpressions,
948 std::move(pElseIfExpressions), pElseExpression);
949}
950
951// While := 'while' '(' SimpleExpression ')' 'do' ExpressionList 'endwhile'
952CXFA_FMExpression* CXFA_FMParser::ParseWhileExpression() {
953 AutoRestorer<unsigned long> restorer(&m_parse_depth);
954 if (HasError() || !IncrementParseDepthAndCheck())
955 return nullptr;
956 if (!CheckThenNext(TOKwhile))
957 return nullptr;
958
959 CXFA_FMSimpleExpression* pCondition = ParseParenExpression();
960 if (!pCondition || !CheckThenNext(TOKdo))
961 return nullptr;
962
963 auto exprs = ParseExpressionList();
964 if (!CheckThenNext(TOKendwhile))
965 return nullptr;
966
967 return cppgc::MakeGarbageCollected<CXFA_FMWhileExpression>(
968 m_heap->GetAllocationHandle(), pCondition,
969 cppgc::MakeGarbageCollected<CXFA_FMBlockExpression>(
970 m_heap->GetAllocationHandle(), std::move(exprs)));
971}
972
973// For := 'for' Assignment 'upto' Accessor ('step' SimpleExpression)?
974// 'do' ExpressionList 'endfor' |
975// 'for' Assignment 'downto' Accessor ('step' SimpleExpression)?
976// 'do' ExpressionList 'endfor'
977CXFA_FMExpression* CXFA_FMParser::ParseForExpression() {
978 AutoRestorer<unsigned long> restorer(&m_parse_depth);
979 if (HasError() || !IncrementParseDepthAndCheck())
980 return nullptr;
981 if (!CheckThenNext(TOKfor))
982 return nullptr;
983 if (m_token.GetType() != TOKidentifier)
984 return nullptr;
985
986 WideString wsVariant(m_token.GetString());
987 if (!NextToken())
988 return nullptr;
989 if (!CheckThenNext(TOKassign))
990 return nullptr;
991
992 CXFA_FMSimpleExpression* pAssignment = ParseSimpleExpression();
993 if (!pAssignment)
994 return nullptr;
995
996 int32_t iDirection = 0;
997 if (m_token.GetType() == TOKupto)
998 iDirection = 1;
999 else if (m_token.GetType() == TOKdownto)
1000 iDirection = -1;
1001 else
1002 return nullptr;
1003
1004 if (!NextToken())
1005 return nullptr;
1006
1007 CXFA_FMSimpleExpression* pAccessor = ParseSimpleExpression();
1008 if (!pAccessor)
1009 return nullptr;
1010
1011 CXFA_FMSimpleExpression* pStep = nullptr;
1012 if (m_token.GetType() == TOKstep) {
1013 if (!NextToken())
1014 return nullptr;
1015 pStep = ParseSimpleExpression();
1016 if (!pStep)
1017 return nullptr;
1018 }
1019 if (!CheckThenNext(TOKdo))
1020 return nullptr;
1021
1022 auto exprs = ParseExpressionList();
1023 if (!CheckThenNext(TOKendfor))
1024 return nullptr;
1025
1026 return cppgc::MakeGarbageCollected<CXFA_FMForExpression>(
1027 m_heap->GetAllocationHandle(), wsVariant, pAssignment, pAccessor,
1028 iDirection, pStep,
1029 cppgc::MakeGarbageCollected<CXFA_FMBlockExpression>(
1030 m_heap->GetAllocationHandle(), std::move(exprs)));
1031}
1032
1033// Foreach := 'foreach' Identifier 'in' '(' ArgumentList ')'
1034// 'do' ExpressionList 'endfor'
1035CXFA_FMExpression* CXFA_FMParser::ParseForeachExpression() {
1036 if (m_token.GetType() != TOKforeach)
1037 return nullptr;
1038
1039 AutoRestorer<unsigned long> restorer(&m_parse_depth);
1040 if (HasError() || !IncrementParseDepthAndCheck())
1041 return nullptr;
1042 if (!CheckThenNext(TOKforeach))
1043 return nullptr;
1044 if (m_token.GetType() != TOKidentifier)
1045 return nullptr;
1046
1047 WideString wsIdentifier(m_token.GetString());
1048 if (!NextToken() || !CheckThenNext(TOKin) || !CheckThenNext(TOKlparen))
1049 return nullptr;
1050
1051 std::vector<cppgc::Member<CXFA_FMSimpleExpression>> pArgumentList;
1052 while (m_token.GetType() != TOKrparen) {
1053 CXFA_FMSimpleExpression* s = ParseSimpleExpression();
1054 if (!s)
1055 return nullptr;
1056
1057 pArgumentList.push_back(s);
1058 if (m_token.GetType() != TOKcomma)
1059 break;
1060 if (!NextToken())
1061 return nullptr;
1062 }
1063 // We must have arguments.
1064 if (pArgumentList.empty())
1065 return nullptr;
1066 if (!CheckThenNext(TOKrparen))
1067 return nullptr;
1068
1069 auto exprs = ParseExpressionList();
1070 if (!CheckThenNext(TOKendfor))
1071 return nullptr;
1072
1073 return cppgc::MakeGarbageCollected<CXFA_FMForeachExpression>(
1074 m_heap->GetAllocationHandle(), std::move(wsIdentifier),
1075 std::move(pArgumentList),
1076 cppgc::MakeGarbageCollected<CXFA_FMBlockExpression>(
1077 m_heap->GetAllocationHandle(), std::move(exprs)));
1078}
1079
1080// Block := 'do' ExpressionList 'end'
1081CXFA_FMExpression* CXFA_FMParser::ParseDoExpression() {
1082 if (m_token.GetType() != TOKdo)
1083 return nullptr;
1084
1085 AutoRestorer<unsigned long> restorer(&m_parse_depth);
1086 if (HasError() || !IncrementParseDepthAndCheck())
1087 return nullptr;
1088 if (!CheckThenNext(TOKdo))
1089 return nullptr;
1090
1091 auto exprs = ParseExpressionList();
1092 if (!CheckThenNext(TOKend))
1093 return nullptr;
1094
1095 return cppgc::MakeGarbageCollected<CXFA_FMDoExpression>(
1096 m_heap->GetAllocationHandle(),
1097 cppgc::MakeGarbageCollected<CXFA_FMBlockExpression>(
1098 m_heap->GetAllocationHandle(), std::move(exprs)));
1099}
1100
1102 return m_error || m_token.GetType() == TOKreserver;
1103}
bool IsComplete() const
bool HasError() const
CXFA_FMParser(cppgc::Heap *heap, CXFA_FMLexer *pLexer)
CXFA_FMAST * Parse()
XFA_FM_TOKEN
@ TOKdotstar
@ TOKge
@ TOKminus
@ TOKnumber
@ TOKendfor
@ TOKor
@ TOKeq
@ TOKksle
@ TOKfor
@ TOKdo
@ TOKlbracket
@ TOKplus
@ TOKkslt
@ TOKnull
@ TOKksgt
@ TOKendif
@ TOKgt
@ TOKle
@ TOKksnot
@ TOKrparen
@ TOKlparen
@ TOKksand
@ TOKidentifier
@ TOKksor
@ TOKassign
@ TOKendfunc
@ TOKksge
@ TOKkseq
@ TOKvar
@ TOKendwhile
@ TOKstring
@ TOKfunc
@ TOKksne
@ TOKforeach
@ TOKif
@ TOKin
@ TOKdotscream
@ TOKdiv
@ TOKne
@ TOKmul
@ TOKlt
@ TOKthen
@ TOKdotdot
@ TOKand
@ TOKdot
@ TOKend
@ TOKwhile
Definition heap.h:12