• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 PDFium Authors. All rights reserved.
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/fm2js/xfa_fmparse.h"
8 
9 #include <memory>
10 #include <utility>
11 #include <vector>
12 
13 #include "third_party/base/ptr_util.h"
14 
CXFA_FMParse(const CFX_WideStringC & wsFormcalc,CXFA_FMErrorInfo * pErrorInfo)15 CXFA_FMParse::CXFA_FMParse(const CFX_WideStringC& wsFormcalc,
16                            CXFA_FMErrorInfo* pErrorInfo)
17     : m_pToken(nullptr), m_pErrorInfo(pErrorInfo) {
18   m_lexer = pdfium::MakeUnique<CXFA_FMLexer>(wsFormcalc, m_pErrorInfo);
19 }
20 
~CXFA_FMParse()21 CXFA_FMParse::~CXFA_FMParse() {}
22 
NextToken()23 void CXFA_FMParse::NextToken() {
24   m_pToken = m_lexer->NextToken();
25   while (m_pToken->m_type == TOKreserver) {
26     if (m_lexer->HasError()) {
27       break;
28     }
29     m_pToken = m_lexer->NextToken();
30   }
31 }
32 
Check(XFA_FM_TOKEN op)33 void CXFA_FMParse::Check(XFA_FM_TOKEN op) {
34   if (m_pToken->m_type != op) {
35     CFX_WideString ws_TempString(m_pToken->m_wstring);
36     Error(m_pToken->m_uLinenum, kFMErrExpectedToken, XFA_FM_KeywordToString(op),
37           ws_TempString.c_str());
38   }
39   NextToken();
40 }
41 
Error(uint32_t lineNum,const FX_WCHAR * msg,...)42 void CXFA_FMParse::Error(uint32_t lineNum, const FX_WCHAR* msg, ...) {
43   m_pErrorInfo->linenum = lineNum;
44   va_list ap;
45   va_start(ap, msg);
46   m_pErrorInfo->message.FormatV(msg, ap);
47   va_end(ap);
48 }
49 
50 std::vector<std::unique_ptr<CXFA_FMExpression>>
ParseTopExpression()51 CXFA_FMParse::ParseTopExpression() {
52   std::unique_ptr<CXFA_FMExpression> expr;
53   std::vector<std::unique_ptr<CXFA_FMExpression>> expressions;
54   while (1) {
55     if (m_pToken->m_type == TOKeof || m_pToken->m_type == TOKendfunc ||
56         m_pToken->m_type == TOKendif || m_pToken->m_type == TOKelseif ||
57         m_pToken->m_type == TOKelse || m_pToken->m_type == TOKreserver) {
58       return expressions;
59     }
60 
61     if (m_pToken->m_type == TOKfunc) {
62       expr = ParseFunction();
63       if (expr) {
64         expressions.push_back(std::move(expr));
65       } else {
66         break;
67       }
68     } else {
69       expr = ParseExpression();
70       if (expr) {
71         expressions.push_back(std::move(expr));
72       } else {
73         break;
74       }
75     }
76   }
77   return expressions;
78 }
79 
ParseFunction()80 std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseFunction() {
81   CFX_WideStringC ident;
82   std::vector<CFX_WideStringC> arguments;
83   std::vector<std::unique_ptr<CXFA_FMExpression>> expressions;
84   uint32_t line = m_pToken->m_uLinenum;
85   NextToken();
86   if (m_pToken->m_type != TOKidentifier) {
87     CFX_WideString ws_TempString(m_pToken->m_wstring);
88     Error(m_pToken->m_uLinenum, kFMErrExpectedIdentifier,
89           ws_TempString.c_str());
90   } else {
91     ident = m_pToken->m_wstring;
92     NextToken();
93   }
94   Check(TOKlparen);
95   if (m_pToken->m_type == TOKrparen) {
96     NextToken();
97   } else {
98     while (1) {
99       if (m_pToken->m_type == TOKidentifier) {
100         arguments.push_back(m_pToken->m_wstring);
101         NextToken();
102         if (m_pToken->m_type == TOKcomma) {
103           NextToken();
104           continue;
105         } else if (m_pToken->m_type == TOKrparen) {
106           NextToken();
107           break;
108         } else {
109           Check(TOKrparen);
110           break;
111         }
112       } else {
113         CFX_WideString ws_TempString(m_pToken->m_wstring);
114         Error(m_pToken->m_uLinenum, kFMErrExpectedIdentifier,
115               ws_TempString.c_str());
116         NextToken();
117         break;
118       }
119     }
120   }
121   Check(TOKdo);
122   if (m_pToken->m_type == TOKendfunc) {
123     NextToken();
124   } else {
125     expressions = ParseTopExpression();
126     Check(TOKendfunc);
127   }
128   if (!m_pErrorInfo->message.IsEmpty())
129     return nullptr;
130 
131   return pdfium::MakeUnique<CXFA_FMFunctionDefinition>(
132       line, false, ident, std::move(arguments), std::move(expressions));
133 }
134 
ParseExpression()135 std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseExpression() {
136   std::unique_ptr<CXFA_FMExpression> expr;
137   uint32_t line = m_pToken->m_uLinenum;
138   switch (m_pToken->m_type) {
139     case TOKvar:
140       expr = ParseVarExpression();
141       break;
142     case TOKnull:
143     case TOKnumber:
144     case TOKstring:
145     case TOKplus:
146     case TOKminus:
147     case TOKksnot:
148     case TOKidentifier:
149     case TOKlparen:
150       expr = ParseExpExpression();
151       break;
152     case TOKif:
153       expr = ParseIfExpression();
154       break;
155     case TOKwhile:
156       expr = ParseWhileExpression();
157       break;
158     case TOKfor:
159       expr = ParseForExpression();
160       break;
161     case TOKforeach:
162       expr = ParseForeachExpression();
163       break;
164     case TOKdo:
165       expr = ParseDoExpression();
166       break;
167     case TOKbreak:
168       expr = pdfium::MakeUnique<CXFA_FMBreakExpression>(line);
169       NextToken();
170       break;
171     case TOKcontinue:
172       expr = pdfium::MakeUnique<CXFA_FMContinueExpression>(line);
173       NextToken();
174       break;
175     default:
176       CFX_WideString ws_TempString(m_pToken->m_wstring);
177       Error(m_pToken->m_uLinenum, kFMErrUnexpectedExpression,
178             ws_TempString.c_str());
179       NextToken();
180       break;
181   }
182   return expr;
183 }
184 
ParseVarExpression()185 std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseVarExpression() {
186   CFX_WideStringC ident;
187   uint32_t line = m_pToken->m_uLinenum;
188   NextToken();
189   if (m_pToken->m_type != TOKidentifier) {
190     CFX_WideString ws_TempString(m_pToken->m_wstring);
191     Error(m_pToken->m_uLinenum, kFMErrExpectedIdentifier,
192           ws_TempString.c_str());
193   } else {
194     ident = m_pToken->m_wstring;
195     NextToken();
196   }
197   std::unique_ptr<CXFA_FMExpression> expr;
198   if (m_pToken->m_type == TOKassign) {
199     NextToken();
200     expr = ParseExpExpression();
201   }
202   if (!m_pErrorInfo->message.IsEmpty())
203     return nullptr;
204 
205   return pdfium::MakeUnique<CXFA_FMVarExpression>(line, ident, std::move(expr));
206 }
207 
ParseSimpleExpression()208 std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParse::ParseSimpleExpression() {
209   uint32_t line = m_pToken->m_uLinenum;
210   std::unique_ptr<CXFA_FMSimpleExpression> pExp1 = ParseLogicalOrExpression();
211   while (m_pToken->m_type == TOKassign) {
212     NextToken();
213     std::unique_ptr<CXFA_FMSimpleExpression> pExp2 = ParseLogicalOrExpression();
214     if (m_pErrorInfo->message.IsEmpty()) {
215       pExp1 = pdfium::MakeUnique<CXFA_FMAssignExpression>(
216           line, TOKassign, std::move(pExp1), std::move(pExp2));
217     } else {
218       pExp1.reset();
219     }
220   }
221   return pExp1;
222 }
223 
ParseExpExpression()224 std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseExpExpression() {
225   uint32_t line = m_pToken->m_uLinenum;
226   std::unique_ptr<CXFA_FMSimpleExpression> pExp1 = ParseSimpleExpression();
227   if (!m_pErrorInfo->message.IsEmpty())
228     return nullptr;
229 
230   return pdfium::MakeUnique<CXFA_FMExpExpression>(line, std::move(pExp1));
231 }
232 
233 std::unique_ptr<CXFA_FMSimpleExpression>
ParseLogicalOrExpression()234 CXFA_FMParse::ParseLogicalOrExpression() {
235   uint32_t line = m_pToken->m_uLinenum;
236   std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseLogicalAndExpression();
237   for (;;) {
238     switch (m_pToken->m_type) {
239       case TOKor:
240       case TOKksor: {
241         NextToken();
242         std::unique_ptr<CXFA_FMSimpleExpression> e2(
243             ParseLogicalAndExpression());
244         if (m_pErrorInfo->message.IsEmpty()) {
245           e1 = pdfium::MakeUnique<CXFA_FMLogicalOrExpression>(
246               line, TOKor, std::move(e1), std::move(e2));
247         } else {
248           e1.reset();
249         }
250         continue;
251       }
252       default:
253         break;
254     }
255     break;
256   }
257   return e1;
258 }
259 
260 std::unique_ptr<CXFA_FMSimpleExpression>
ParseLogicalAndExpression()261 CXFA_FMParse::ParseLogicalAndExpression() {
262   uint32_t line = m_pToken->m_uLinenum;
263   std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseEqualityExpression();
264   for (;;) {
265     switch (m_pToken->m_type) {
266       case TOKand:
267       case TOKksand: {
268         NextToken();
269         std::unique_ptr<CXFA_FMSimpleExpression> e2 = ParseEqualityExpression();
270         if (m_pErrorInfo->message.IsEmpty()) {
271           e1 = pdfium::MakeUnique<CXFA_FMLogicalAndExpression>(
272               line, TOKand, std::move(e1), std::move(e2));
273         } else {
274           e1.reset();
275         }
276         continue;
277       }
278       default:
279         break;
280     }
281     break;
282   }
283   return e1;
284 }
285 
286 std::unique_ptr<CXFA_FMSimpleExpression>
ParseEqualityExpression()287 CXFA_FMParse::ParseEqualityExpression() {
288   uint32_t line = m_pToken->m_uLinenum;
289   std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseRelationalExpression();
290   for (;;) {
291     std::unique_ptr<CXFA_FMSimpleExpression> e2;
292     switch (m_pToken->m_type) {
293       case TOKeq:
294       case TOKkseq:
295         NextToken();
296         e2 = ParseRelationalExpression();
297         if (m_pErrorInfo->message.IsEmpty()) {
298           e1 = pdfium::MakeUnique<CXFA_FMEqualityExpression>(
299               line, TOKeq, std::move(e1), std::move(e2));
300         } else {
301           e1.reset();
302         }
303         continue;
304       case TOKne:
305       case TOKksne:
306         NextToken();
307         e2 = ParseRelationalExpression();
308         if (m_pErrorInfo->message.IsEmpty()) {
309           e1 = pdfium::MakeUnique<CXFA_FMEqualityExpression>(
310               line, TOKne, std::move(e1), std::move(e2));
311         } else {
312           e1.reset();
313         }
314         continue;
315       default:
316         break;
317     }
318     break;
319   }
320   return e1;
321 }
322 
323 std::unique_ptr<CXFA_FMSimpleExpression>
ParseRelationalExpression()324 CXFA_FMParse::ParseRelationalExpression() {
325   uint32_t line = m_pToken->m_uLinenum;
326   std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseAddtiveExpression();
327   for (;;) {
328     std::unique_ptr<CXFA_FMSimpleExpression> e2;
329     switch (m_pToken->m_type) {
330       case TOKlt:
331       case TOKkslt:
332         NextToken();
333         e2 = ParseAddtiveExpression();
334         if (m_pErrorInfo->message.IsEmpty()) {
335           e1 = pdfium::MakeUnique<CXFA_FMRelationalExpression>(
336               line, TOKlt, std::move(e1), std::move(e2));
337         } else {
338           e1.reset();
339         }
340         continue;
341       case TOKgt:
342       case TOKksgt:
343         NextToken();
344         e2 = ParseAddtiveExpression();
345         if (m_pErrorInfo->message.IsEmpty()) {
346           e1 = pdfium::MakeUnique<CXFA_FMRelationalExpression>(
347               line, TOKgt, std::move(e1), std::move(e2));
348         } else {
349           e1.reset();
350         }
351         continue;
352       case TOKle:
353       case TOKksle:
354         NextToken();
355         e2 = ParseAddtiveExpression();
356         if (m_pErrorInfo->message.IsEmpty()) {
357           e1 = pdfium::MakeUnique<CXFA_FMRelationalExpression>(
358               line, TOKle, std::move(e1), std::move(e2));
359         } else {
360           e1.reset();
361         }
362         continue;
363       case TOKge:
364       case TOKksge:
365         NextToken();
366         e2 = ParseAddtiveExpression();
367         if (m_pErrorInfo->message.IsEmpty()) {
368           e1 = pdfium::MakeUnique<CXFA_FMRelationalExpression>(
369               line, TOKge, std::move(e1), std::move(e2));
370         } else {
371           e1.reset();
372         }
373         continue;
374       default:
375         break;
376     }
377     break;
378   }
379   return e1;
380 }
381 
382 std::unique_ptr<CXFA_FMSimpleExpression>
ParseAddtiveExpression()383 CXFA_FMParse::ParseAddtiveExpression() {
384   uint32_t line = m_pToken->m_uLinenum;
385   std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseMultiplicativeExpression();
386   for (;;) {
387     std::unique_ptr<CXFA_FMSimpleExpression> e2;
388     switch (m_pToken->m_type) {
389       case TOKplus:
390         NextToken();
391         e2 = ParseMultiplicativeExpression();
392         if (m_pErrorInfo->message.IsEmpty()) {
393           e1 = pdfium::MakeUnique<CXFA_FMAdditiveExpression>(
394               line, TOKplus, std::move(e1), std::move(e2));
395         } else {
396           e1.reset();
397         }
398         continue;
399       case TOKminus:
400         NextToken();
401         e2 = ParseMultiplicativeExpression();
402         if (m_pErrorInfo->message.IsEmpty()) {
403           e1 = pdfium::MakeUnique<CXFA_FMAdditiveExpression>(
404               line, TOKminus, std::move(e1), std::move(e2));
405         } else {
406           e1.reset();
407         }
408         continue;
409       default:
410         break;
411     }
412     break;
413   }
414   return e1;
415 }
416 
417 std::unique_ptr<CXFA_FMSimpleExpression>
ParseMultiplicativeExpression()418 CXFA_FMParse::ParseMultiplicativeExpression() {
419   uint32_t line = m_pToken->m_uLinenum;
420   std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseUnaryExpression();
421   for (;;) {
422     std::unique_ptr<CXFA_FMSimpleExpression> e2;
423     switch (m_pToken->m_type) {
424       case TOKmul:
425         NextToken();
426         e2 = ParseUnaryExpression();
427         if (m_pErrorInfo->message.IsEmpty()) {
428           e1 = pdfium::MakeUnique<CXFA_FMMultiplicativeExpression>(
429               line, TOKmul, std::move(e1), std::move(e2));
430         } else {
431           e1.reset();
432         }
433         continue;
434       case TOKdiv:
435         NextToken();
436         e2 = ParseUnaryExpression();
437         if (m_pErrorInfo->message.IsEmpty()) {
438           e1 = pdfium::MakeUnique<CXFA_FMMultiplicativeExpression>(
439               line, TOKdiv, std::move(e1), std::move(e2));
440         } else {
441           e1.reset();
442         }
443         continue;
444       default:
445         break;
446     }
447     break;
448   }
449   return e1;
450 }
451 
ParseUnaryExpression()452 std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParse::ParseUnaryExpression() {
453   std::unique_ptr<CXFA_FMSimpleExpression> expr;
454   uint32_t line = m_pToken->m_uLinenum;
455   switch (m_pToken->m_type) {
456     case TOKplus:
457       NextToken();
458       expr = ParseUnaryExpression();
459       if (m_pErrorInfo->message.IsEmpty())
460         expr = pdfium::MakeUnique<CXFA_FMPosExpression>(line, std::move(expr));
461       else
462         expr.reset();
463       break;
464     case TOKminus:
465       NextToken();
466       expr = ParseUnaryExpression();
467       if (m_pErrorInfo->message.IsEmpty())
468         expr = pdfium::MakeUnique<CXFA_FMNegExpression>(line, std::move(expr));
469       else
470         expr.reset();
471       break;
472     case TOKksnot:
473       NextToken();
474       expr = ParseUnaryExpression();
475       if (m_pErrorInfo->message.IsEmpty())
476         expr = pdfium::MakeUnique<CXFA_FMNotExpression>(line, std::move(expr));
477       else
478         expr.reset();
479       break;
480     default:
481       expr = ParsePrimaryExpression();
482       break;
483   }
484   return expr;
485 }
486 
487 std::unique_ptr<CXFA_FMSimpleExpression>
ParsePrimaryExpression()488 CXFA_FMParse::ParsePrimaryExpression() {
489   std::unique_ptr<CXFA_FMSimpleExpression> expr;
490   uint32_t line = m_pToken->m_uLinenum;
491   switch (m_pToken->m_type) {
492     case TOKnumber:
493       expr = pdfium::MakeUnique<CXFA_FMNumberExpression>(line,
494                                                          m_pToken->m_wstring);
495       NextToken();
496       break;
497     case TOKstring:
498       expr = pdfium::MakeUnique<CXFA_FMStringExpression>(line,
499                                                          m_pToken->m_wstring);
500       NextToken();
501       break;
502     case TOKidentifier: {
503       CFX_WideStringC wsIdentifier(m_pToken->m_wstring);
504       NextToken();
505       if (m_pToken->m_type == TOKlbracket) {
506         std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression();
507         if (s) {
508           expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
509               line, nullptr, TOKdot, wsIdentifier, std::move(s));
510         }
511         NextToken();
512       } else {
513         expr =
514             pdfium::MakeUnique<CXFA_FMIdentifierExpression>(line, wsIdentifier);
515       }
516     } break;
517     case TOKif:
518       expr = pdfium::MakeUnique<CXFA_FMIdentifierExpression>(
519           line, m_pToken->m_wstring);
520       NextToken();
521       break;
522     case TOKnull:
523       expr = pdfium::MakeUnique<CXFA_FMNullExpression>(line);
524       NextToken();
525       break;
526     case TOKlparen:
527       expr = ParseParenExpression();
528       break;
529     default:
530       CFX_WideString ws_TempString(m_pToken->m_wstring);
531       Error(m_pToken->m_uLinenum, kFMErrUnexpectedExpression,
532             ws_TempString.c_str());
533       NextToken();
534       break;
535   }
536   expr = ParsePostExpression(std::move(expr));
537   if (!m_pErrorInfo->message.IsEmpty())
538     expr.reset();
539   return expr;
540 }
541 
ParsePostExpression(std::unique_ptr<CXFA_FMSimpleExpression> expr)542 std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParse::ParsePostExpression(
543     std::unique_ptr<CXFA_FMSimpleExpression> expr) {
544   uint32_t line = m_pToken->m_uLinenum;
545   while (1) {
546     switch (m_pToken->m_type) {
547       case TOKlparen: {
548         NextToken();
549         std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> expressions;
550         if (m_pToken->m_type != TOKrparen) {
551           while (m_pToken->m_type != TOKrparen) {
552             if (std::unique_ptr<CXFA_FMSimpleExpression> expr =
553                     ParseSimpleExpression())
554               expressions.push_back(std::move(expr));
555             if (m_pToken->m_type == TOKcomma) {
556               NextToken();
557             } else if (m_pToken->m_type == TOKeof ||
558                        m_pToken->m_type == TOKreserver) {
559               break;
560             }
561           }
562           if (m_pToken->m_type != TOKrparen) {
563             CFX_WideString ws_TempString(m_pToken->m_wstring);
564             Error(m_pToken->m_uLinenum, kFMErrExpectedToken,
565                   XFA_FM_KeywordToString(TOKrparen), ws_TempString.c_str());
566           }
567         }
568         if (m_pErrorInfo->message.IsEmpty()) {
569           expr = pdfium::MakeUnique<CXFA_FMCallExpression>(
570               line, std::move(expr), std::move(expressions), false);
571           NextToken();
572           if (m_pToken->m_type != TOKlbracket)
573             continue;
574 
575           std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression();
576           if (s) {
577             expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
578                 line, std::move(expr), TOKcall, L"", std::move(s));
579           } else {
580             expr.reset();
581           }
582         } else {
583           expr.reset();
584         }
585       } break;
586       case TOKdot:
587         NextToken();
588         if (m_pToken->m_type == TOKidentifier) {
589           CFX_WideStringC tempStr = m_pToken->m_wstring;
590           uint32_t tempLine = m_pToken->m_uLinenum;
591           NextToken();
592           if (m_pToken->m_type == TOKlparen) {
593             std::unique_ptr<CXFA_FMSimpleExpression> pExpCall;
594             NextToken();
595             std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> expressions;
596             if (m_pToken->m_type != TOKrparen) {
597               while (m_pToken->m_type != TOKrparen) {
598                 std::unique_ptr<CXFA_FMSimpleExpression> exp =
599                     ParseSimpleExpression();
600                 expressions.push_back(std::move(exp));
601                 if (m_pToken->m_type == TOKcomma) {
602                   NextToken();
603                 } else if (m_pToken->m_type == TOKeof ||
604                            m_pToken->m_type == TOKreserver) {
605                   break;
606                 }
607               }
608               if (m_pToken->m_type != TOKrparen) {
609                 CFX_WideString ws_TempString(m_pToken->m_wstring);
610                 Error(m_pToken->m_uLinenum, kFMErrExpectedToken,
611                       XFA_FM_KeywordToString(TOKrparen), ws_TempString.c_str());
612               }
613             }
614             if (m_pErrorInfo->message.IsEmpty()) {
615               std::unique_ptr<CXFA_FMSimpleExpression> pIdentifier =
616                   pdfium::MakeUnique<CXFA_FMIdentifierExpression>(tempLine,
617                                                                   tempStr);
618               pExpCall = pdfium::MakeUnique<CXFA_FMCallExpression>(
619                   line, std::move(pIdentifier), std::move(expressions), true);
620               expr = pdfium::MakeUnique<CXFA_FMMethodCallExpression>(
621                   line, std::move(expr), std::move(pExpCall));
622               NextToken();
623               if (m_pToken->m_type != TOKlbracket)
624                 continue;
625 
626               std::unique_ptr<CXFA_FMSimpleExpression> s =
627                   ParseIndexExpression();
628               if (s) {
629                 expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
630                     line, std::move(expr), TOKcall, L"", std::move(s));
631               } else {
632                 expr.reset();
633               }
634             } else {
635               expr.reset();
636             }
637           } else if (m_pToken->m_type == TOKlbracket) {
638             std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression();
639             if (!(m_pErrorInfo->message.IsEmpty()))
640               return nullptr;
641 
642             expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
643                 tempLine, std::move(expr), TOKdot, tempStr, std::move(s));
644           } else {
645             std::unique_ptr<CXFA_FMSimpleExpression> s =
646                 pdfium::MakeUnique<CXFA_FMIndexExpression>(
647                     tempLine, ACCESSOR_NO_INDEX, nullptr, false);
648             expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
649                 line, std::move(expr), TOKdot, tempStr, std::move(s));
650             continue;
651           }
652         } else {
653           CFX_WideString ws_TempString(m_pToken->m_wstring);
654           Error(m_pToken->m_uLinenum, kFMErrExpectedIdentifier,
655                 ws_TempString.c_str());
656           return expr;
657         }
658         break;
659       case TOKdotdot:
660         NextToken();
661         if (m_pToken->m_type == TOKidentifier) {
662           CFX_WideStringC tempStr = m_pToken->m_wstring;
663           uint32_t tempLine = m_pToken->m_uLinenum;
664           NextToken();
665           if (m_pToken->m_type == TOKlbracket) {
666             std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression();
667             if (!(m_pErrorInfo->message.IsEmpty())) {
668               return nullptr;
669             }
670             expr = pdfium::MakeUnique<CXFA_FMDotDotAccessorExpression>(
671                 tempLine, std::move(expr), TOKdotdot, tempStr, std::move(s));
672           } else {
673             std::unique_ptr<CXFA_FMSimpleExpression> s =
674                 pdfium::MakeUnique<CXFA_FMIndexExpression>(
675                     tempLine, ACCESSOR_NO_INDEX, nullptr, false);
676             expr = pdfium::MakeUnique<CXFA_FMDotDotAccessorExpression>(
677                 line, std::move(expr), TOKdotdot, tempStr, std::move(s));
678             continue;
679           }
680         } else {
681           CFX_WideString ws_TempString(m_pToken->m_wstring);
682           Error(m_pToken->m_uLinenum, kFMErrExpectedIdentifier,
683                 ws_TempString.c_str());
684           return expr;
685         }
686         break;
687       case TOKdotscream:
688         NextToken();
689         if (m_pToken->m_type == TOKidentifier) {
690           CFX_WideStringC tempStr = m_pToken->m_wstring;
691           uint32_t tempLine = m_pToken->m_uLinenum;
692           NextToken();
693           if (m_pToken->m_type == TOKlbracket) {
694             std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression();
695             if (!(m_pErrorInfo->message.IsEmpty()))
696               return nullptr;
697 
698             expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
699                 tempLine, std::move(expr), TOKdotscream, tempStr, std::move(s));
700           } else {
701             std::unique_ptr<CXFA_FMSimpleExpression> s =
702                 pdfium::MakeUnique<CXFA_FMIndexExpression>(
703                     tempLine, ACCESSOR_NO_INDEX, nullptr, false);
704             expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
705                 line, std::move(expr), TOKdotscream, tempStr, std::move(s));
706             continue;
707           }
708         } else {
709           CFX_WideString ws_TempString(m_pToken->m_wstring);
710           Error(m_pToken->m_uLinenum, kFMErrExpectedIdentifier,
711                 ws_TempString.c_str());
712           return expr;
713         }
714         break;
715       case TOKdotstar: {
716         std::unique_ptr<CXFA_FMSimpleExpression> s =
717             pdfium::MakeUnique<CXFA_FMIndexExpression>(line, ACCESSOR_NO_INDEX,
718                                                        nullptr, false);
719         expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
720             line, std::move(expr), TOKdotstar, L"*", std::move(s));
721       } break;
722       default:
723         return expr;
724     }
725     NextToken();
726   }
727   return expr;
728 }
729 
ParseIndexExpression()730 std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParse::ParseIndexExpression() {
731   std::unique_ptr<CXFA_FMSimpleExpression> pExp;
732   uint32_t line = m_pToken->m_uLinenum;
733   NextToken();
734   std::unique_ptr<CXFA_FMSimpleExpression> s;
735   XFA_FM_AccessorIndex accessorIndex = ACCESSOR_NO_RELATIVEINDEX;
736   if (m_pToken->m_type == TOKmul) {
737     pExp = pdfium::MakeUnique<CXFA_FMIndexExpression>(line, accessorIndex,
738                                                       std::move(s), true);
739     NextToken();
740     if (m_pToken->m_type != TOKrbracket) {
741       CFX_WideString ws_TempString(m_pToken->m_wstring);
742       Error(m_pToken->m_uLinenum, kFMErrExpectedToken,
743             XFA_FM_KeywordToString(TOKrparen), ws_TempString.c_str());
744       pExp.reset();
745     }
746     return pExp;
747   }
748   if (m_pToken->m_type == TOKplus) {
749     accessorIndex = ACCESSOR_POSITIVE_INDEX;
750     NextToken();
751   } else if (m_pToken->m_type == TOKminus) {
752     accessorIndex = ACCESSOR_NEGATIVE_INDEX;
753     NextToken();
754   }
755   s = ParseSimpleExpression();
756   if (m_pToken->m_type != TOKrbracket) {
757     CFX_WideString ws_TempString(m_pToken->m_wstring);
758     Error(m_pToken->m_uLinenum, kFMErrExpectedToken,
759           XFA_FM_KeywordToString(TOKrparen), ws_TempString.c_str());
760   } else {
761     pExp = pdfium::MakeUnique<CXFA_FMIndexExpression>(line, accessorIndex,
762                                                       std::move(s), false);
763   }
764   return pExp;
765 }
766 
ParseParenExpression()767 std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParse::ParseParenExpression() {
768   Check(TOKlparen);
769 
770   if (m_pToken->m_type == TOKrparen) {
771     Error(m_pToken->m_uLinenum, kFMErrExpectedNonEmptyExpression);
772     NextToken();
773     return nullptr;
774   }
775 
776   uint32_t line = m_pToken->m_uLinenum;
777   std::unique_ptr<CXFA_FMSimpleExpression> pExp1 = ParseLogicalOrExpression();
778 
779   while (m_pToken->m_type == TOKassign) {
780     NextToken();
781     std::unique_ptr<CXFA_FMSimpleExpression> pExp2 = ParseLogicalOrExpression();
782     if (m_pErrorInfo->message.IsEmpty()) {
783       pExp1 = pdfium::MakeUnique<CXFA_FMAssignExpression>(
784           line, TOKassign, std::move(pExp1), std::move(pExp2));
785     } else {
786       pExp1.reset();
787     }
788   }
789   Check(TOKrparen);
790   return pExp1;
791 }
792 
ParseBlockExpression()793 std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseBlockExpression() {
794   uint32_t line = m_pToken->m_uLinenum;
795   std::unique_ptr<CXFA_FMExpression> expr;
796   std::vector<std::unique_ptr<CXFA_FMExpression>> expressions;
797 
798   while (1) {
799     switch (m_pToken->m_type) {
800       case TOKeof:
801       case TOKendif:
802       case TOKelseif:
803       case TOKelse:
804       case TOKendwhile:
805       case TOKendfor:
806       case TOKend:
807       case TOKendfunc:
808       case TOKreserver:
809         break;
810       case TOKfunc:
811         expr = ParseFunction();
812         if (expr) {
813           expressions.push_back(std::move(expr));
814         }
815         continue;
816       default:
817         expr = ParseExpression();
818         if (expr) {
819           expressions.push_back(std::move(expr));
820         }
821         continue;
822     }
823     break;
824   }
825   std::unique_ptr<CXFA_FMBlockExpression> pExp;
826   if (m_pErrorInfo->message.IsEmpty()) {
827     pExp = pdfium::MakeUnique<CXFA_FMBlockExpression>(line,
828                                                       std::move(expressions));
829   }
830   return pExp;
831 }
832 
ParseIfExpression()833 std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseIfExpression() {
834   uint32_t line = m_pToken->m_uLinenum;
835   const FX_WCHAR* pStartPos = m_lexer->SavePos();
836   NextToken();
837   Check(TOKlparen);
838   std::unique_ptr<CXFA_FMSimpleExpression> pExpression;
839   while (m_pToken->m_type != TOKrparen) {
840     pExpression = ParseSimpleExpression();
841     if (m_pToken->m_type != TOKcomma)
842       break;
843     NextToken();
844   }
845   Check(TOKrparen);
846   if (m_pToken->m_type != TOKthen) {
847     m_lexer->SetCurrentLine(line);
848     m_pToken = new CXFA_FMToken(line);
849     m_pToken->m_type = TOKidentifier;
850     m_pToken->m_wstring = L"if";
851     m_lexer->SetToken(m_pToken);
852     m_lexer->RestorePos(pStartPos);
853     return ParseExpExpression();
854   }
855   Check(TOKthen);
856   std::unique_ptr<CXFA_FMExpression> pIfExpression = ParseBlockExpression();
857   std::unique_ptr<CXFA_FMExpression> pElseExpression;
858   switch (m_pToken->m_type) {
859     case TOKeof:
860     case TOKendif:
861       Check(TOKendif);
862       break;
863     case TOKif:
864       pElseExpression = ParseIfExpression();
865       Check(TOKendif);
866       break;
867     case TOKelseif:
868       pElseExpression = ParseIfExpression();
869       break;
870     case TOKelse:
871       NextToken();
872       pElseExpression = ParseBlockExpression();
873       Check(TOKendif);
874       break;
875     default:
876       CFX_WideString ws_TempString(m_pToken->m_wstring);
877       Error(m_pToken->m_uLinenum, kFMErrExpectedEndIf, ws_TempString.c_str());
878       NextToken();
879       break;
880   }
881   std::unique_ptr<CXFA_FMIfExpression> pExp;
882   if (m_pErrorInfo->message.IsEmpty()) {
883     pExp = pdfium::MakeUnique<CXFA_FMIfExpression>(line, std::move(pExpression),
884                                                    std::move(pIfExpression),
885                                                    std::move(pElseExpression));
886   }
887   return pExp;
888 }
889 
ParseWhileExpression()890 std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseWhileExpression() {
891   uint32_t line = m_pToken->m_uLinenum;
892   NextToken();
893   std::unique_ptr<CXFA_FMSimpleExpression> pCondition = ParseParenExpression();
894   Check(TOKdo);
895   std::unique_ptr<CXFA_FMExpression> pExpression = ParseBlockExpression();
896   Check(TOKendwhile);
897   std::unique_ptr<CXFA_FMExpression> expr;
898   if (m_pErrorInfo->message.IsEmpty()) {
899     expr = pdfium::MakeUnique<CXFA_FMWhileExpression>(
900         line, std::move(pCondition), std::move(pExpression));
901   }
902   return expr;
903 }
904 
905 std::unique_ptr<CXFA_FMSimpleExpression>
ParseSubassignmentInForExpression()906 CXFA_FMParse::ParseSubassignmentInForExpression() {
907   std::unique_ptr<CXFA_FMSimpleExpression> expr;
908   switch (m_pToken->m_type) {
909     case TOKidentifier:
910       expr = ParseSimpleExpression();
911       break;
912     default:
913       CFX_WideString ws_TempString(m_pToken->m_wstring);
914       Error(m_pToken->m_uLinenum, kFMErrUnexpectedExpression,
915             ws_TempString.c_str());
916       NextToken();
917       break;
918   }
919   return expr;
920 }
921 
ParseForExpression()922 std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseForExpression() {
923   CFX_WideStringC wsVariant;
924   uint32_t line = m_pToken->m_uLinenum;
925   NextToken();
926   if (m_pToken->m_type != TOKidentifier) {
927     CFX_WideString ws_TempString(m_pToken->m_wstring);
928     Error(m_pToken->m_uLinenum, kFMErrExpectedToken,
929           XFA_FM_KeywordToString(m_pToken->m_type), ws_TempString.c_str());
930   }
931   wsVariant = m_pToken->m_wstring;
932   NextToken();
933   std::unique_ptr<CXFA_FMSimpleExpression> pAssignment;
934   if (m_pToken->m_type == TOKassign) {
935     NextToken();
936     pAssignment = ParseSimpleExpression();
937   } else {
938     CFX_WideString ws_TempString(m_pToken->m_wstring);
939     Error(m_pToken->m_uLinenum, kFMErrExpectedToken,
940           XFA_FM_KeywordToString(m_pToken->m_type), ws_TempString.c_str());
941   }
942   int32_t iDirection = 0;
943   if (m_pToken->m_type == TOKupto) {
944     iDirection = 1;
945   } else if (m_pToken->m_type == TOKdownto) {
946     iDirection = -1;
947   } else {
948     CFX_WideString ws_TempString(m_pToken->m_wstring);
949     Error(m_pToken->m_uLinenum, kFMErrExpectedToken, L"upto or downto",
950           ws_TempString.c_str());
951   }
952   NextToken();
953   std::unique_ptr<CXFA_FMSimpleExpression> pAccessor = ParseSimpleExpression();
954   std::unique_ptr<CXFA_FMSimpleExpression> pStep;
955   if (m_pToken->m_type == TOKstep) {
956     NextToken();
957     pStep = ParseSimpleExpression();
958   }
959   Check(TOKdo);
960   std::unique_ptr<CXFA_FMExpression> pList = ParseBlockExpression();
961   Check(TOKendfor);
962   std::unique_ptr<CXFA_FMExpression> expr;
963   if (m_pErrorInfo->message.IsEmpty()) {
964     expr = pdfium::MakeUnique<CXFA_FMForExpression>(
965         line, wsVariant, std::move(pAssignment), std::move(pAccessor),
966         iDirection, std::move(pStep), std::move(pList));
967   }
968   return expr;
969 }
970 
ParseForeachExpression()971 std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseForeachExpression() {
972   std::unique_ptr<CXFA_FMExpression> expr;
973   CFX_WideStringC wsIdentifier;
974   std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> pAccessors;
975   std::unique_ptr<CXFA_FMExpression> pList;
976   uint32_t line = m_pToken->m_uLinenum;
977   NextToken();
978   if (m_pToken->m_type != TOKidentifier) {
979     CFX_WideString ws_TempString(m_pToken->m_wstring);
980     Error(m_pToken->m_uLinenum, kFMErrExpectedToken,
981           XFA_FM_KeywordToString(m_pToken->m_type), ws_TempString.c_str());
982   }
983   wsIdentifier = m_pToken->m_wstring;
984   NextToken();
985   Check(TOKin);
986   Check(TOKlparen);
987   if (m_pToken->m_type == TOKrparen) {
988     CFX_WideString ws_TempString(m_pToken->m_wstring);
989     Error(m_pToken->m_uLinenum, kFMErrUnexpectedExpression,
990           ws_TempString.c_str());
991     NextToken();
992   } else {
993     while (m_pToken->m_type != TOKrparen) {
994       std::unique_ptr<CXFA_FMSimpleExpression> s = ParseSimpleExpression();
995       if (s)
996         pAccessors.push_back(std::move(s));
997       if (m_pToken->m_type != TOKcomma)
998         break;
999       NextToken();
1000     }
1001     Check(TOKrparen);
1002   }
1003   Check(TOKdo);
1004   pList = ParseBlockExpression();
1005   Check(TOKendfor);
1006   if (m_pErrorInfo->message.IsEmpty()) {
1007     expr = pdfium::MakeUnique<CXFA_FMForeachExpression>(
1008         line, wsIdentifier, std::move(pAccessors), std::move(pList));
1009   }
1010   return expr;
1011 }
1012 
ParseDoExpression()1013 std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseDoExpression() {
1014   uint32_t line = m_pToken->m_uLinenum;
1015   NextToken();
1016   std::unique_ptr<CXFA_FMExpression> expr = ParseBlockExpression();
1017   Check(TOKend);
1018   if (!m_pErrorInfo->message.IsEmpty())
1019     return nullptr;
1020 
1021   return pdfium::MakeUnique<CXFA_FMDoExpression>(line, std::move(expr));
1022 }
1023