Home | History | Annotate | Download | only in fm2js
      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 
     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 
     21 CXFA_FMParse::~CXFA_FMParse() {}
     22 
     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 
     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 
     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>>
     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 
     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 
    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 
    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 
    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 
    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>
    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>
    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>
    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>
    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>
    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>
    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 
    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>
    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 
    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 
    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 
    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 
    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 
    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 
    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>
    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 
    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 
    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 
   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