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