// Copyright 2014 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com #include "xfa/fxfa/fm2js/cxfa_fmparser.h" #include #include #include #include "third_party/base/ptr_util.h" namespace { const unsigned int kMaxAssignmentChainLength = 12; const unsigned int kMaxParseDepth = 1250; } // namespace CXFA_FMParser::CXFA_FMParser(const CFX_WideStringC& wsFormcalc) : m_error(false), m_parse_depth(0), m_max_parse_depth(kMaxParseDepth) { m_lexer = pdfium::MakeUnique(wsFormcalc); m_token = m_lexer->NextToken(); } CXFA_FMParser::~CXFA_FMParser() {} std::unique_ptr CXFA_FMParser::Parse() { auto expressions = ParseTopExpression(); if (HasError()) return nullptr; std::vector arguments; return pdfium::MakeUnique( 1, true, L"", std::move(arguments), std::move(expressions)); } bool CXFA_FMParser::NextToken() { if (HasError()) return false; m_token = m_lexer->NextToken(); while (!HasError() && m_token->m_type == TOKreserver) m_token = m_lexer->NextToken(); return !HasError(); } bool CXFA_FMParser::CheckThenNext(XFA_FM_TOKEN op) { if (HasError()) return false; if (m_token->m_type != op) { m_error = true; return false; } return NextToken(); } bool CXFA_FMParser::IncrementParseDepthAndCheck() { return ++m_parse_depth < m_max_parse_depth; } std::vector> CXFA_FMParser::ParseTopExpression() { CFX_AutoRestorer restorer(&m_parse_depth); if (HasError() || !IncrementParseDepthAndCheck()) return std::vector>(); std::unique_ptr expr; std::vector> expressions; while (!HasError()) { if (m_token->m_type == TOKeof || m_token->m_type == TOKendfunc || m_token->m_type == TOKendif || m_token->m_type == TOKelseif || m_token->m_type == TOKelse || m_token->m_type == TOKreserver) { return expressions; } expr = m_token->m_type == TOKfunc ? ParseFunction() : ParseExpression(); if (!expr) { m_error = true; break; } expressions.push_back(std::move(expr)); } return std::vector>(); } std::unique_ptr CXFA_FMParser::ParseFunction() { CFX_AutoRestorer restorer(&m_parse_depth); if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; CFX_WideStringC ident; std::vector arguments; std::vector> expressions; uint32_t line = m_token->m_line_num; if (!NextToken()) return nullptr; if (m_token->m_type != TOKidentifier) { m_error = true; return nullptr; } else { ident = m_token->m_string; if (!NextToken()) return nullptr; } if (!CheckThenNext(TOKlparen)) return nullptr; if (m_token->m_type == TOKrparen) { if (!NextToken()) return nullptr; } else { while (1) { if (m_token->m_type != TOKidentifier) { m_error = true; return nullptr; } arguments.push_back(m_token->m_string); if (!NextToken()) return nullptr; if (m_token->m_type == TOKcomma) { if (!NextToken()) return nullptr; continue; } if (m_token->m_type == TOKrparen) { if (!NextToken()) return nullptr; } else { if (!CheckThenNext(TOKrparen)) return nullptr; } break; } } if (!CheckThenNext(TOKdo)) return nullptr; if (m_token->m_type == TOKendfunc) { if (!NextToken()) return nullptr; } else { expressions = ParseTopExpression(); if (!expressions.size() || !CheckThenNext(TOKendfunc)) return nullptr; } return pdfium::MakeUnique( line, false, ident, std::move(arguments), std::move(expressions)); } std::unique_ptr CXFA_FMParser::ParseExpression() { CFX_AutoRestorer restorer(&m_parse_depth); if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; std::unique_ptr expr; uint32_t line = m_token->m_line_num; switch (m_token->m_type) { case TOKvar: expr = ParseVarExpression(); break; case TOKnull: case TOKnumber: case TOKstring: case TOKplus: case TOKminus: case TOKksnot: case TOKidentifier: case TOKlparen: expr = ParseExpExpression(); break; case TOKif: expr = ParseIfExpression(); break; case TOKwhile: expr = ParseWhileExpression(); break; case TOKfor: expr = ParseForExpression(); break; case TOKforeach: expr = ParseForeachExpression(); break; case TOKdo: expr = ParseDoExpression(); break; case TOKbreak: expr = pdfium::MakeUnique(line); if (!NextToken()) return nullptr; break; case TOKcontinue: expr = pdfium::MakeUnique(line); if (!NextToken()) return nullptr; break; default: m_error = true; return nullptr; } return expr; } std::unique_ptr CXFA_FMParser::ParseVarExpression() { CFX_AutoRestorer restorer(&m_parse_depth); if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; CFX_WideStringC ident; uint32_t line = m_token->m_line_num; if (!NextToken()) return nullptr; if (m_token->m_type != TOKidentifier) { m_error = true; return nullptr; } ident = m_token->m_string; if (!NextToken()) return nullptr; std::unique_ptr expr; if (m_token->m_type == TOKassign) { if (!NextToken()) return nullptr; expr = ParseExpExpression(); if (!expr) return nullptr; } return pdfium::MakeUnique(line, ident, std::move(expr)); } std::unique_ptr CXFA_FMParser::ParseSimpleExpression() { if (HasError()) return nullptr; uint32_t line = m_token->m_line_num; std::unique_ptr pExp1 = ParseLogicalOrExpression(); if (!pExp1) return nullptr; int level = 1; while (m_token->m_type == TOKassign) { if (!NextToken()) return nullptr; std::unique_ptr pExp2 = ParseLogicalOrExpression(); if (!pExp2) return nullptr; if (level++ == kMaxAssignmentChainLength) { m_error = true; return nullptr; } pExp1 = pdfium::MakeUnique( line, TOKassign, std::move(pExp1), std::move(pExp2)); } return pExp1; } std::unique_ptr CXFA_FMParser::ParseExpExpression() { CFX_AutoRestorer restorer(&m_parse_depth); if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; uint32_t line = m_token->m_line_num; std::unique_ptr pExp1 = ParseSimpleExpression(); if (!pExp1) return nullptr; return pdfium::MakeUnique(line, std::move(pExp1)); } std::unique_ptr CXFA_FMParser::ParseLogicalOrExpression() { CFX_AutoRestorer restorer(&m_parse_depth); if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; uint32_t line = m_token->m_line_num; std::unique_ptr e1 = ParseLogicalAndExpression(); if (!e1) return nullptr; for (;;) { switch (m_token->m_type) { case TOKor: case TOKksor: { if (!NextToken()) return nullptr; std::unique_ptr e2( ParseLogicalAndExpression()); if (!e2) return nullptr; e1 = pdfium::MakeUnique( line, TOKor, std::move(e1), std::move(e2)); continue; } default: break; } break; } return e1; } std::unique_ptr CXFA_FMParser::ParseLogicalAndExpression() { CFX_AutoRestorer restorer(&m_parse_depth); if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; uint32_t line = m_token->m_line_num; std::unique_ptr e1 = ParseEqualityExpression(); if (!e1) return nullptr; for (;;) { switch (m_token->m_type) { case TOKand: case TOKksand: { if (!NextToken()) return nullptr; std::unique_ptr e2 = ParseEqualityExpression(); if (!e2) return nullptr; e1 = pdfium::MakeUnique( line, TOKand, std::move(e1), std::move(e2)); continue; } default: break; } break; } return e1; } std::unique_ptr CXFA_FMParser::ParseEqualityExpression() { CFX_AutoRestorer restorer(&m_parse_depth); if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; uint32_t line = m_token->m_line_num; std::unique_ptr e1 = ParseRelationalExpression(); if (!e1) return nullptr; for (;;) { std::unique_ptr e2; switch (m_token->m_type) { case TOKeq: case TOKkseq: if (!NextToken()) return nullptr; e2 = ParseRelationalExpression(); if (!e2) return nullptr; e1 = pdfium::MakeUnique( line, TOKeq, std::move(e1), std::move(e2)); continue; case TOKne: case TOKksne: if (!NextToken()) return nullptr; e2 = ParseRelationalExpression(); if (!e2) return nullptr; e1 = pdfium::MakeUnique( line, TOKne, std::move(e1), std::move(e2)); continue; default: break; } break; } return e1; } std::unique_ptr CXFA_FMParser::ParseRelationalExpression() { CFX_AutoRestorer restorer(&m_parse_depth); if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; uint32_t line = m_token->m_line_num; std::unique_ptr e1 = ParseAddtiveExpression(); if (!e1) return nullptr; for (;;) { std::unique_ptr e2; switch (m_token->m_type) { case TOKlt: case TOKkslt: if (!NextToken()) return nullptr; e2 = ParseAddtiveExpression(); if (!e2) return nullptr; e1 = pdfium::MakeUnique( line, TOKlt, std::move(e1), std::move(e2)); continue; case TOKgt: case TOKksgt: if (!NextToken()) return nullptr; e2 = ParseAddtiveExpression(); if (!e2) return nullptr; e1 = pdfium::MakeUnique( line, TOKgt, std::move(e1), std::move(e2)); continue; case TOKle: case TOKksle: if (!NextToken()) return nullptr; e2 = ParseAddtiveExpression(); if (!e2) return nullptr; e1 = pdfium::MakeUnique( line, TOKle, std::move(e1), std::move(e2)); continue; case TOKge: case TOKksge: if (!NextToken()) return nullptr; e2 = ParseAddtiveExpression(); if (!e2) return nullptr; e1 = pdfium::MakeUnique( line, TOKge, std::move(e1), std::move(e2)); continue; default: break; } break; } return e1; } std::unique_ptr CXFA_FMParser::ParseAddtiveExpression() { CFX_AutoRestorer restorer(&m_parse_depth); if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; uint32_t line = m_token->m_line_num; std::unique_ptr e1 = ParseMultiplicativeExpression(); if (!e1) return nullptr; for (;;) { std::unique_ptr e2; switch (m_token->m_type) { case TOKplus: if (!NextToken()) return nullptr; e2 = ParseMultiplicativeExpression(); if (!e2) return nullptr; e1 = pdfium::MakeUnique( line, TOKplus, std::move(e1), std::move(e2)); continue; case TOKminus: if (!NextToken()) return nullptr; e2 = ParseMultiplicativeExpression(); if (!e2) return nullptr; e1 = pdfium::MakeUnique( line, TOKminus, std::move(e1), std::move(e2)); continue; default: break; } break; } return e1; } std::unique_ptr CXFA_FMParser::ParseMultiplicativeExpression() { CFX_AutoRestorer restorer(&m_parse_depth); if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; uint32_t line = m_token->m_line_num; std::unique_ptr e1 = ParseUnaryExpression(); if (!e1) return nullptr; for (;;) { std::unique_ptr e2; switch (m_token->m_type) { case TOKmul: if (!NextToken()) return nullptr; e2 = ParseUnaryExpression(); if (!e2) return nullptr; e1 = pdfium::MakeUnique( line, TOKmul, std::move(e1), std::move(e2)); continue; case TOKdiv: if (!NextToken()) return nullptr; e2 = ParseUnaryExpression(); if (!e2) return nullptr; e1 = pdfium::MakeUnique( line, TOKdiv, std::move(e1), std::move(e2)); continue; default: break; } break; } return e1; } std::unique_ptr CXFA_FMParser::ParseUnaryExpression() { CFX_AutoRestorer restorer(&m_parse_depth); if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; std::unique_ptr expr; uint32_t line = m_token->m_line_num; switch (m_token->m_type) { case TOKplus: if (!NextToken()) return nullptr; expr = ParseUnaryExpression(); if (!expr) return nullptr; expr = pdfium::MakeUnique(line, std::move(expr)); break; case TOKminus: if (!NextToken()) return nullptr; expr = ParseUnaryExpression(); if (!expr) return nullptr; expr = pdfium::MakeUnique(line, std::move(expr)); break; case TOKksnot: if (!NextToken()) return nullptr; expr = ParseUnaryExpression(); if (!expr) return nullptr; expr = pdfium::MakeUnique(line, std::move(expr)); break; default: expr = ParsePrimaryExpression(); if (!expr) return nullptr; break; } return expr; } std::unique_ptr CXFA_FMParser::ParsePrimaryExpression() { CFX_AutoRestorer restorer(&m_parse_depth); if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; std::unique_ptr expr; uint32_t line = m_token->m_line_num; switch (m_token->m_type) { case TOKnumber: expr = pdfium::MakeUnique(line, m_token->m_string); if (!NextToken()) return nullptr; break; case TOKstring: expr = pdfium::MakeUnique(line, m_token->m_string); if (!NextToken()) return nullptr; break; case TOKidentifier: { CFX_WideStringC wsIdentifier(m_token->m_string); if (!NextToken()) return nullptr; if (m_token->m_type == TOKlbracket) { std::unique_ptr s = ParseIndexExpression(); if (!s) return nullptr; expr = pdfium::MakeUnique( line, nullptr, TOKdot, wsIdentifier, std::move(s)); if (!expr) return nullptr; if (!NextToken()) return nullptr; } else { expr = pdfium::MakeUnique(line, wsIdentifier); } break; } case TOKif: expr = pdfium::MakeUnique(line, m_token->m_string); if (!expr || !NextToken()) return nullptr; break; case TOKnull: expr = pdfium::MakeUnique(line); if (!expr || !NextToken()) return nullptr; break; case TOKlparen: expr = ParseParenExpression(); if (!expr) return nullptr; break; default: m_error = true; return nullptr; } expr = ParsePostExpression(std::move(expr)); if (!expr) return nullptr; return expr; } std::unique_ptr CXFA_FMParser::ParsePostExpression( std::unique_ptr expr) { if (HasError()) return nullptr; uint32_t line = m_token->m_line_num; while (1) { switch (m_token->m_type) { case TOKlparen: { if (!NextToken()) return nullptr; std::vector> expressions; if (m_token->m_type != TOKrparen) { while (m_token->m_type != TOKrparen) { std::unique_ptr simple_expr = ParseSimpleExpression(); if (!simple_expr) return nullptr; expressions.push_back(std::move(simple_expr)); if (m_token->m_type == TOKcomma) { if (!NextToken()) return nullptr; } else if (m_token->m_type == TOKeof || m_token->m_type == TOKreserver) { break; } } if (m_token->m_type != TOKrparen) { m_error = true; return nullptr; } } expr = pdfium::MakeUnique( line, std::move(expr), std::move(expressions), false); if (!NextToken()) return nullptr; if (m_token->m_type != TOKlbracket) continue; std::unique_ptr s = ParseIndexExpression(); if (!s) return nullptr; expr = pdfium::MakeUnique( line, std::move(expr), TOKcall, L"", std::move(s)); break; } case TOKdot: { if (!NextToken()) return nullptr; if (m_token->m_type != TOKidentifier) { m_error = true; return nullptr; } CFX_WideStringC tempStr = m_token->m_string; uint32_t tempLine = m_token->m_line_num; if (!NextToken()) return nullptr; if (m_token->m_type == TOKlparen) { std::unique_ptr pExpCall; if (!NextToken()) return nullptr; std::vector> expressions; if (m_token->m_type != TOKrparen) { while (m_token->m_type != TOKrparen) { std::unique_ptr exp = ParseSimpleExpression(); if (!exp) return nullptr; expressions.push_back(std::move(exp)); if (m_token->m_type == TOKcomma) { if (!NextToken()) return nullptr; } else if (m_token->m_type == TOKeof || m_token->m_type == TOKreserver) { break; } } if (m_token->m_type != TOKrparen) { m_error = true; return nullptr; } } std::unique_ptr pIdentifier = pdfium::MakeUnique(tempLine, tempStr); pExpCall = pdfium::MakeUnique( line, std::move(pIdentifier), std::move(expressions), true); expr = pdfium::MakeUnique( line, std::move(expr), std::move(pExpCall)); if (!NextToken()) return nullptr; if (m_token->m_type != TOKlbracket) continue; std::unique_ptr s = ParseIndexExpression(); if (!s) return nullptr; expr = pdfium::MakeUnique( line, std::move(expr), TOKcall, L"", std::move(s)); } else if (m_token->m_type == TOKlbracket) { std::unique_ptr s = ParseIndexExpression(); if (!s) return nullptr; expr = pdfium::MakeUnique( tempLine, std::move(expr), TOKdot, tempStr, std::move(s)); } else { std::unique_ptr s = pdfium::MakeUnique( tempLine, ACCESSOR_NO_INDEX, nullptr, false); expr = pdfium::MakeUnique( line, std::move(expr), TOKdot, tempStr, std::move(s)); continue; } } break; case TOKdotdot: { if (!NextToken()) return nullptr; if (m_token->m_type != TOKidentifier) { m_error = true; return nullptr; } CFX_WideStringC tempStr = m_token->m_string; uint32_t tempLine = m_token->m_line_num; if (!NextToken()) return nullptr; if (m_token->m_type == TOKlbracket) { std::unique_ptr s = ParseIndexExpression(); if (!s) return nullptr; expr = pdfium::MakeUnique( tempLine, std::move(expr), TOKdotdot, tempStr, std::move(s)); } else { std::unique_ptr s = pdfium::MakeUnique( tempLine, ACCESSOR_NO_INDEX, nullptr, false); expr = pdfium::MakeUnique( line, std::move(expr), TOKdotdot, tempStr, std::move(s)); continue; } } break; case TOKdotscream: { if (!NextToken()) return nullptr; if (m_token->m_type != TOKidentifier) { m_error = true; return nullptr; } CFX_WideStringC tempStr = m_token->m_string; uint32_t tempLine = m_token->m_line_num; if (NextToken()) return nullptr; if (m_token->m_type != TOKlbracket) { std::unique_ptr s = pdfium::MakeUnique( tempLine, ACCESSOR_NO_INDEX, nullptr, false); expr = pdfium::MakeUnique( line, std::move(expr), TOKdotscream, tempStr, std::move(s)); continue; } std::unique_ptr s = ParseIndexExpression(); if (!s) return nullptr; expr = pdfium::MakeUnique( tempLine, std::move(expr), TOKdotscream, tempStr, std::move(s)); break; } case TOKdotstar: { std::unique_ptr s = pdfium::MakeUnique(line, ACCESSOR_NO_INDEX, nullptr, false); expr = pdfium::MakeUnique( line, std::move(expr), TOKdotstar, L"*", std::move(s)); break; } default: return expr; } if (!NextToken()) return nullptr; } return expr; } std::unique_ptr CXFA_FMParser::ParseIndexExpression() { CFX_AutoRestorer restorer(&m_parse_depth); if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; uint32_t line = m_token->m_line_num; if (!NextToken()) return nullptr; std::unique_ptr s; XFA_FM_AccessorIndex accessorIndex = ACCESSOR_NO_RELATIVEINDEX; std::unique_ptr pExp; if (m_token->m_type == TOKmul) { pExp = pdfium::MakeUnique(line, accessorIndex, std::move(s), true); if (!pExp || !NextToken()) return nullptr; if (m_token->m_type != TOKrbracket) { m_error = true; return nullptr; } return pExp; } if (m_token->m_type == TOKplus) { accessorIndex = ACCESSOR_POSITIVE_INDEX; if (!NextToken()) return nullptr; } else if (m_token->m_type == TOKminus) { accessorIndex = ACCESSOR_NEGATIVE_INDEX; if (!NextToken()) return nullptr; } s = ParseSimpleExpression(); if (!s) return nullptr; if (m_token->m_type != TOKrbracket) { m_error = true; return nullptr; } return pdfium::MakeUnique(line, accessorIndex, std::move(s), false); } std::unique_ptr CXFA_FMParser::ParseParenExpression() { CFX_AutoRestorer restorer(&m_parse_depth); if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; if (!CheckThenNext(TOKlparen)) return nullptr; if (m_token->m_type == TOKrparen) { m_error = true; return nullptr; } uint32_t line = m_token->m_line_num; std::unique_ptr pExp1 = ParseLogicalOrExpression(); if (!pExp1) return nullptr; int level = 1; while (m_token->m_type == TOKassign) { if (!NextToken()) return nullptr; std::unique_ptr pExp2 = ParseLogicalOrExpression(); if (!pExp2) return nullptr; if (level++ == kMaxAssignmentChainLength) { m_error = true; return nullptr; } pExp1 = pdfium::MakeUnique( line, TOKassign, std::move(pExp1), std::move(pExp2)); } if (!CheckThenNext(TOKrparen)) return nullptr; return pExp1; } std::unique_ptr CXFA_FMParser::ParseBlockExpression() { if (HasError()) return nullptr; uint32_t line = m_token->m_line_num; std::vector> expressions; while (1) { std::unique_ptr expr; switch (m_token->m_type) { case TOKeof: case TOKendif: case TOKelseif: case TOKelse: case TOKendwhile: case TOKendfor: case TOKend: case TOKendfunc: case TOKreserver: break; case TOKfunc: expr = ParseFunction(); if (!expr) return nullptr; expressions.push_back(std::move(expr)); continue; default: expr = ParseExpression(); if (!expr) return nullptr; expressions.push_back(std::move(expr)); continue; } break; } return pdfium::MakeUnique(line, std::move(expressions)); } std::unique_ptr CXFA_FMParser::ParseIfExpression() { CFX_AutoRestorer restorer(&m_parse_depth); if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; uint32_t line = m_token->m_line_num; const wchar_t* pStartPos = m_lexer->GetPos(); if (!NextToken() || !CheckThenNext(TOKlparen)) return nullptr; std::unique_ptr pExpression; while (m_token->m_type != TOKrparen) { pExpression = ParseSimpleExpression(); if (!pExpression) return nullptr; if (m_token->m_type != TOKcomma) break; if (!NextToken()) return nullptr; } if (!CheckThenNext(TOKrparen)) return nullptr; if (m_token->m_type != TOKthen) { m_lexer->SetCurrentLine(line); auto pNewToken = pdfium::MakeUnique(line); m_token = std::move(pNewToken); m_token->m_type = TOKidentifier; m_token->m_string = L"if"; m_lexer->SetPos(pStartPos); return ParseExpExpression(); } if (!CheckThenNext(TOKthen)) return nullptr; std::unique_ptr pIfExpression = ParseBlockExpression(); if (!pIfExpression) return nullptr; std::unique_ptr pElseExpression; switch (m_token->m_type) { case TOKeof: case TOKendif: if (!CheckThenNext(TOKendif)) return nullptr; break; case TOKif: pElseExpression = ParseIfExpression(); if (!pElseExpression || !CheckThenNext(TOKendif)) return nullptr; break; case TOKelseif: pElseExpression = ParseIfExpression(); if (!pElseExpression) return nullptr; break; case TOKelse: if (!NextToken()) return nullptr; pElseExpression = ParseBlockExpression(); if (!pElseExpression || !CheckThenNext(TOKendif)) return nullptr; break; default: m_error = true; return nullptr; } return pdfium::MakeUnique(line, std::move(pExpression), std::move(pIfExpression), std::move(pElseExpression)); } std::unique_ptr CXFA_FMParser::ParseWhileExpression() { CFX_AutoRestorer restorer(&m_parse_depth); if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; uint32_t line = m_token->m_line_num; if (!NextToken()) return nullptr; std::unique_ptr pCondition = ParseParenExpression(); if (!pCondition || !CheckThenNext(TOKdo)) return nullptr; std::unique_ptr pExpression = ParseBlockExpression(); if (!pExpression || !CheckThenNext(TOKendwhile)) return nullptr; return pdfium::MakeUnique(line, std::move(pCondition), std::move(pExpression)); } std::unique_ptr CXFA_FMParser::ParseSubassignmentInForExpression() { if (HasError()) return nullptr; if (m_token->m_type != TOKidentifier) { m_error = true; return nullptr; } std::unique_ptr expr = ParseSimpleExpression(); if (!expr) return nullptr; return expr; } std::unique_ptr CXFA_FMParser::ParseForExpression() { CFX_AutoRestorer restorer(&m_parse_depth); if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; CFX_WideStringC wsVariant; uint32_t line = m_token->m_line_num; if (!NextToken()) return nullptr; if (m_token->m_type != TOKidentifier) { m_error = true; return nullptr; } wsVariant = m_token->m_string; if (!NextToken()) return nullptr; if (m_token->m_type != TOKassign) { m_error = true; return nullptr; } if (!NextToken()) return nullptr; std::unique_ptr pAssignment = ParseSimpleExpression(); if (!pAssignment) return nullptr; int32_t iDirection = 0; if (m_token->m_type == TOKupto) { iDirection = 1; } else if (m_token->m_type == TOKdownto) { iDirection = -1; } else { m_error = true; return nullptr; } if (!NextToken()) return nullptr; std::unique_ptr pAccessor = ParseSimpleExpression(); if (!pAccessor) return nullptr; std::unique_ptr pStep; if (m_token->m_type == TOKstep) { if (!NextToken()) return nullptr; pStep = ParseSimpleExpression(); if (!pStep) return nullptr; } if (!CheckThenNext(TOKdo)) return nullptr; std::unique_ptr pList = ParseBlockExpression(); if (!pList || !CheckThenNext(TOKendfor)) return nullptr; std::unique_ptr expr; if (!expr) return nullptr; return pdfium::MakeUnique( line, wsVariant, std::move(pAssignment), std::move(pAccessor), iDirection, std::move(pStep), std::move(pList)); } std::unique_ptr CXFA_FMParser::ParseForeachExpression() { if (HasError()) return nullptr; std::unique_ptr expr; CFX_WideStringC wsIdentifier; std::vector> pAccessors; std::unique_ptr pList; uint32_t line = m_token->m_line_num; if (!NextToken()) return nullptr; if (m_token->m_type != TOKidentifier) { m_error = true; return nullptr; } wsIdentifier = m_token->m_string; if (!NextToken() || !CheckThenNext(TOKin) || !CheckThenNext(TOKlparen)) return nullptr; if (m_token->m_type == TOKrparen) { m_error = true; return nullptr; } while (m_token->m_type != TOKrparen) { std::unique_ptr s = ParseSimpleExpression(); if (!s) return nullptr; pAccessors.push_back(std::move(s)); if (m_token->m_type != TOKcomma) break; if (!NextToken()) return nullptr; } if (!CheckThenNext(TOKrparen) || !CheckThenNext(TOKdo)) return nullptr; pList = ParseBlockExpression(); if (!pList || !CheckThenNext(TOKendfor)) return nullptr; return pdfium::MakeUnique( line, wsIdentifier, std::move(pAccessors), std::move(pList)); } std::unique_ptr CXFA_FMParser::ParseDoExpression() { if (HasError()) return nullptr; uint32_t line = m_token->m_line_num; if (!NextToken()) return nullptr; std::unique_ptr expr = ParseBlockExpression(); if (!expr || !CheckThenNext(TOKend)) return nullptr; return pdfium::MakeUnique(line, std::move(expr)); } bool CXFA_FMParser::HasError() const { return m_error || m_token == nullptr; }