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