xref: /aosp_15_r20/external/pdfium/xfa/fxfa/formcalc/cxfa_fmparser.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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 
15 namespace {
16 
17 constexpr unsigned int kMaxParseDepth = 1250;
18 constexpr unsigned int kMaxPostExpressions = 256;
19 constexpr unsigned int kMaxExpressionListSize = 10000;
20 
21 }  // namespace
22 
CXFA_FMParser(cppgc::Heap * pHeap,CXFA_FMLexer * pLexer)23 CXFA_FMParser::CXFA_FMParser(cppgc::Heap* pHeap, CXFA_FMLexer* pLexer)
24     : m_heap(pHeap), m_lexer(pLexer), m_max_parse_depth(kMaxParseDepth) {}
25 
26 CXFA_FMParser::~CXFA_FMParser() = default;
27 
Parse()28 CXFA_FMAST* CXFA_FMParser::Parse() {
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 
NextToken()45 bool 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 
CheckThenNext(XFA_FM_TOKEN op)55 bool 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 
IncrementParseDepthAndCheck()66 bool CXFA_FMParser::IncrementParseDepthAndCheck() {
67   return ++m_parse_depth < m_max_parse_depth;
68 }
69 
70 std::vector<cppgc::Member<CXFA_FMExpression>>
ParseExpressionList()71 CXFA_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)*)?
ParseFunction()104 CXFA_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
ParseExpression()159 CXFA_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.
ParseDeclarationExpression()215 CXFA_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
ParseSimpleExpression()242 CXFA_FMSimpleExpression* CXFA_FMParser::ParseSimpleExpression() {
243   if (HasError())
244     return nullptr;
245 
246   return ParseLogicalOrExpression();
247 }
248 
249 // Exp := SimpleExpression ( '=' SimpleExpression )?
ParseExpExpression()250 CXFA_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
ParseLogicalOrExpression()276 CXFA_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
ParseLogicalAndExpression()309 CXFA_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
ParseEqualityExpression()342 CXFA_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
ParseRelationalExpression()386 CXFA_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
ParseAdditiveExpression()452 CXFA_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
ParseMultiplicativeExpression()494 CXFA_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
ParseUnaryExpression()535 CXFA_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 ')'
ParsePrimaryExpression()575 CXFA_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
ParseLiteral()619 CXFA_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 ( '.' | '..' | '.#' )
ParsePostExpression(CXFA_FMSimpleExpression * expr)637 CXFA_FMSimpleExpression* CXFA_FMParser::ParsePostExpression(
638     CXFA_FMSimpleExpression* expr) {
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 ')'
803 absl::optional<std::vector<cppgc::Member<CXFA_FMSimpleExpression>>>
ParseArgumentList()804 CXFA_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) ']'
ParseIndexExpression()831 CXFA_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 ')'
ParseParenExpression()875 CXFA_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'
ParseIfExpression()898 CXFA_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'
ParseWhileExpression()952 CXFA_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'
ParseForExpression()977 CXFA_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'
ParseForeachExpression()1035 CXFA_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'
ParseDoExpression()1081 CXFA_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 
HasError() const1101 bool CXFA_FMParser::HasError() const {
1102   return m_error || m_token.GetType() == TOKreserver;
1103 }
1104