| // 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_fmparse.h" | |
| #include <memory> | |
| #include <utility> | |
| #include <vector> | |
| #include "third_party/base/ptr_util.h" | |
| namespace { | |
| const int kMaxAssignmentChainLength = 12; | |
| } // namespace | |
| CXFA_FMParse::CXFA_FMParse(const CFX_WideStringC& wsFormcalc) | |
| : m_pToken(nullptr), m_ParserError(false) { | |
| m_lexer = pdfium::MakeUnique<CXFA_FMLexer>(wsFormcalc); | |
| } | |
| CXFA_FMParse::~CXFA_FMParse() {} | |
| std::unique_ptr<CXFA_FMFunctionDefinition> CXFA_FMParse::Parse() { | |
| NextToken(); | |
| if (HasError()) | |
| return nullptr; | |
| auto expressions = ParseTopExpression(); | |
| if (HasError()) | |
| return nullptr; | |
| std::vector<CFX_WideStringC> arguments; | |
| return pdfium::MakeUnique<CXFA_FMFunctionDefinition>( | |
| 1, true, L"", std::move(arguments), std::move(expressions)); | |
| } | |
| void CXFA_FMParse::NextToken() { | |
| m_pToken = m_lexer->NextToken(); | |
| while (m_pToken->m_type == TOKreserver) { | |
| if (HasError()) | |
| break; | |
| m_pToken = m_lexer->NextToken(); | |
| } | |
| } | |
| void CXFA_FMParse::Check(XFA_FM_TOKEN op) { | |
| if (m_pToken->m_type != op) | |
| m_ParserError = true; | |
| NextToken(); | |
| } | |
| std::vector<std::unique_ptr<CXFA_FMExpression>> | |
| CXFA_FMParse::ParseTopExpression() { | |
| std::unique_ptr<CXFA_FMExpression> expr; | |
| std::vector<std::unique_ptr<CXFA_FMExpression>> expressions; | |
| while (1) { | |
| if (m_pToken->m_type == TOKeof || m_pToken->m_type == TOKendfunc || | |
| m_pToken->m_type == TOKendif || m_pToken->m_type == TOKelseif || | |
| m_pToken->m_type == TOKelse || m_pToken->m_type == TOKreserver) { | |
| return expressions; | |
| } | |
| expr = m_pToken->m_type == TOKfunc ? ParseFunction() : ParseExpression(); | |
| if (!expr) | |
| break; | |
| expressions.push_back(std::move(expr)); | |
| } | |
| return expressions; | |
| } | |
| std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseFunction() { | |
| CFX_WideStringC ident; | |
| std::vector<CFX_WideStringC> arguments; | |
| std::vector<std::unique_ptr<CXFA_FMExpression>> expressions; | |
| uint32_t line = m_pToken->m_uLinenum; | |
| NextToken(); | |
| if (m_pToken->m_type != TOKidentifier) { | |
| m_ParserError = true; | |
| } else { | |
| ident = m_pToken->m_wstring; | |
| NextToken(); | |
| } | |
| Check(TOKlparen); | |
| if (m_pToken->m_type == TOKrparen) { | |
| NextToken(); | |
| } else { | |
| while (1) { | |
| if (m_pToken->m_type == TOKidentifier) { | |
| arguments.push_back(m_pToken->m_wstring); | |
| NextToken(); | |
| if (m_pToken->m_type == TOKcomma) { | |
| NextToken(); | |
| continue; | |
| } | |
| if (m_pToken->m_type == TOKrparen) | |
| NextToken(); | |
| else | |
| Check(TOKrparen); | |
| } else { | |
| m_ParserError = true; | |
| NextToken(); | |
| } | |
| break; | |
| } | |
| } | |
| Check(TOKdo); | |
| if (m_pToken->m_type == TOKendfunc) { | |
| NextToken(); | |
| } else { | |
| expressions = ParseTopExpression(); | |
| Check(TOKendfunc); | |
| } | |
| if (HasError()) | |
| return nullptr; | |
| return pdfium::MakeUnique<CXFA_FMFunctionDefinition>( | |
| line, false, ident, std::move(arguments), std::move(expressions)); | |
| } | |
| std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseExpression() { | |
| std::unique_ptr<CXFA_FMExpression> expr; | |
| uint32_t line = m_pToken->m_uLinenum; | |
| switch (m_pToken->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<CXFA_FMBreakExpression>(line); | |
| NextToken(); | |
| break; | |
| case TOKcontinue: | |
| expr = pdfium::MakeUnique<CXFA_FMContinueExpression>(line); | |
| NextToken(); | |
| break; | |
| default: | |
| m_ParserError = true; | |
| NextToken(); | |
| break; | |
| } | |
| return expr; | |
| } | |
| std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseVarExpression() { | |
| CFX_WideStringC ident; | |
| uint32_t line = m_pToken->m_uLinenum; | |
| NextToken(); | |
| if (m_pToken->m_type != TOKidentifier) { | |
| m_ParserError = true; | |
| } else { | |
| ident = m_pToken->m_wstring; | |
| NextToken(); | |
| } | |
| std::unique_ptr<CXFA_FMExpression> expr; | |
| if (m_pToken->m_type == TOKassign) { | |
| NextToken(); | |
| expr = ParseExpExpression(); | |
| } | |
| if (HasError()) | |
| return nullptr; | |
| return pdfium::MakeUnique<CXFA_FMVarExpression>(line, ident, std::move(expr)); | |
| } | |
| std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParse::ParseSimpleExpression() { | |
| uint32_t line = m_pToken->m_uLinenum; | |
| std::unique_ptr<CXFA_FMSimpleExpression> pExp1 = ParseLogicalOrExpression(); | |
| int level = 1; | |
| while (m_pToken->m_type == TOKassign) { | |
| NextToken(); | |
| std::unique_ptr<CXFA_FMSimpleExpression> pExp2 = ParseLogicalOrExpression(); | |
| if (level++ == kMaxAssignmentChainLength) | |
| m_ParserError = true; | |
| if (!HasError()) { | |
| pExp1 = pdfium::MakeUnique<CXFA_FMAssignExpression>( | |
| line, TOKassign, std::move(pExp1), std::move(pExp2)); | |
| } else { | |
| pExp1.reset(); | |
| } | |
| } | |
| return pExp1; | |
| } | |
| std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseExpExpression() { | |
| uint32_t line = m_pToken->m_uLinenum; | |
| std::unique_ptr<CXFA_FMSimpleExpression> pExp1 = ParseSimpleExpression(); | |
| if (HasError()) | |
| return nullptr; | |
| return pdfium::MakeUnique<CXFA_FMExpExpression>(line, std::move(pExp1)); | |
| } | |
| std::unique_ptr<CXFA_FMSimpleExpression> | |
| CXFA_FMParse::ParseLogicalOrExpression() { | |
| uint32_t line = m_pToken->m_uLinenum; | |
| std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseLogicalAndExpression(); | |
| for (;;) { | |
| switch (m_pToken->m_type) { | |
| case TOKor: | |
| case TOKksor: { | |
| NextToken(); | |
| std::unique_ptr<CXFA_FMSimpleExpression> e2( | |
| ParseLogicalAndExpression()); | |
| if (!HasError()) { | |
| e1 = pdfium::MakeUnique<CXFA_FMLogicalOrExpression>( | |
| line, TOKor, std::move(e1), std::move(e2)); | |
| } else { | |
| e1.reset(); | |
| } | |
| continue; | |
| } | |
| default: | |
| break; | |
| } | |
| break; | |
| } | |
| return e1; | |
| } | |
| std::unique_ptr<CXFA_FMSimpleExpression> | |
| CXFA_FMParse::ParseLogicalAndExpression() { | |
| uint32_t line = m_pToken->m_uLinenum; | |
| std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseEqualityExpression(); | |
| for (;;) { | |
| switch (m_pToken->m_type) { | |
| case TOKand: | |
| case TOKksand: { | |
| NextToken(); | |
| std::unique_ptr<CXFA_FMSimpleExpression> e2 = ParseEqualityExpression(); | |
| if (!HasError()) { | |
| e1 = pdfium::MakeUnique<CXFA_FMLogicalAndExpression>( | |
| line, TOKand, std::move(e1), std::move(e2)); | |
| } else { | |
| e1.reset(); | |
| } | |
| continue; | |
| } | |
| default: | |
| break; | |
| } | |
| break; | |
| } | |
| return e1; | |
| } | |
| std::unique_ptr<CXFA_FMSimpleExpression> | |
| CXFA_FMParse::ParseEqualityExpression() { | |
| uint32_t line = m_pToken->m_uLinenum; | |
| std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseRelationalExpression(); | |
| for (;;) { | |
| std::unique_ptr<CXFA_FMSimpleExpression> e2; | |
| switch (m_pToken->m_type) { | |
| case TOKeq: | |
| case TOKkseq: | |
| NextToken(); | |
| e2 = ParseRelationalExpression(); | |
| if (!HasError()) { | |
| e1 = pdfium::MakeUnique<CXFA_FMEqualityExpression>( | |
| line, TOKeq, std::move(e1), std::move(e2)); | |
| } else { | |
| e1.reset(); | |
| } | |
| continue; | |
| case TOKne: | |
| case TOKksne: | |
| NextToken(); | |
| e2 = ParseRelationalExpression(); | |
| if (!HasError()) { | |
| e1 = pdfium::MakeUnique<CXFA_FMEqualityExpression>( | |
| line, TOKne, std::move(e1), std::move(e2)); | |
| } else { | |
| e1.reset(); | |
| } | |
| continue; | |
| default: | |
| break; | |
| } | |
| break; | |
| } | |
| return e1; | |
| } | |
| std::unique_ptr<CXFA_FMSimpleExpression> | |
| CXFA_FMParse::ParseRelationalExpression() { | |
| uint32_t line = m_pToken->m_uLinenum; | |
| std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseAddtiveExpression(); | |
| for (;;) { | |
| std::unique_ptr<CXFA_FMSimpleExpression> e2; | |
| switch (m_pToken->m_type) { | |
| case TOKlt: | |
| case TOKkslt: | |
| NextToken(); | |
| e2 = ParseAddtiveExpression(); | |
| if (!HasError()) { | |
| e1 = pdfium::MakeUnique<CXFA_FMRelationalExpression>( | |
| line, TOKlt, std::move(e1), std::move(e2)); | |
| } else { | |
| e1.reset(); | |
| } | |
| continue; | |
| case TOKgt: | |
| case TOKksgt: | |
| NextToken(); | |
| e2 = ParseAddtiveExpression(); | |
| if (!HasError()) { | |
| e1 = pdfium::MakeUnique<CXFA_FMRelationalExpression>( | |
| line, TOKgt, std::move(e1), std::move(e2)); | |
| } else { | |
| e1.reset(); | |
| } | |
| continue; | |
| case TOKle: | |
| case TOKksle: | |
| NextToken(); | |
| e2 = ParseAddtiveExpression(); | |
| if (!HasError()) { | |
| e1 = pdfium::MakeUnique<CXFA_FMRelationalExpression>( | |
| line, TOKle, std::move(e1), std::move(e2)); | |
| } else { | |
| e1.reset(); | |
| } | |
| continue; | |
| case TOKge: | |
| case TOKksge: | |
| NextToken(); | |
| e2 = ParseAddtiveExpression(); | |
| if (!HasError()) { | |
| e1 = pdfium::MakeUnique<CXFA_FMRelationalExpression>( | |
| line, TOKge, std::move(e1), std::move(e2)); | |
| } else { | |
| e1.reset(); | |
| } | |
| continue; | |
| default: | |
| break; | |
| } | |
| break; | |
| } | |
| return e1; | |
| } | |
| std::unique_ptr<CXFA_FMSimpleExpression> | |
| CXFA_FMParse::ParseAddtiveExpression() { | |
| uint32_t line = m_pToken->m_uLinenum; | |
| std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseMultiplicativeExpression(); | |
| for (;;) { | |
| std::unique_ptr<CXFA_FMSimpleExpression> e2; | |
| switch (m_pToken->m_type) { | |
| case TOKplus: | |
| NextToken(); | |
| e2 = ParseMultiplicativeExpression(); | |
| if (!HasError()) { | |
| e1 = pdfium::MakeUnique<CXFA_FMAdditiveExpression>( | |
| line, TOKplus, std::move(e1), std::move(e2)); | |
| } else { | |
| e1.reset(); | |
| } | |
| continue; | |
| case TOKminus: | |
| NextToken(); | |
| e2 = ParseMultiplicativeExpression(); | |
| if (!HasError()) { | |
| e1 = pdfium::MakeUnique<CXFA_FMAdditiveExpression>( | |
| line, TOKminus, std::move(e1), std::move(e2)); | |
| } else { | |
| e1.reset(); | |
| } | |
| continue; | |
| default: | |
| break; | |
| } | |
| break; | |
| } | |
| return e1; | |
| } | |
| std::unique_ptr<CXFA_FMSimpleExpression> | |
| CXFA_FMParse::ParseMultiplicativeExpression() { | |
| uint32_t line = m_pToken->m_uLinenum; | |
| std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseUnaryExpression(); | |
| for (;;) { | |
| std::unique_ptr<CXFA_FMSimpleExpression> e2; | |
| switch (m_pToken->m_type) { | |
| case TOKmul: | |
| NextToken(); | |
| e2 = ParseUnaryExpression(); | |
| if (!HasError()) { | |
| e1 = pdfium::MakeUnique<CXFA_FMMultiplicativeExpression>( | |
| line, TOKmul, std::move(e1), std::move(e2)); | |
| } else { | |
| e1.reset(); | |
| } | |
| continue; | |
| case TOKdiv: | |
| NextToken(); | |
| e2 = ParseUnaryExpression(); | |
| if (!HasError()) { | |
| e1 = pdfium::MakeUnique<CXFA_FMMultiplicativeExpression>( | |
| line, TOKdiv, std::move(e1), std::move(e2)); | |
| } else { | |
| e1.reset(); | |
| } | |
| continue; | |
| default: | |
| break; | |
| } | |
| break; | |
| } | |
| return e1; | |
| } | |
| std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParse::ParseUnaryExpression() { | |
| std::unique_ptr<CXFA_FMSimpleExpression> expr; | |
| uint32_t line = m_pToken->m_uLinenum; | |
| switch (m_pToken->m_type) { | |
| case TOKplus: | |
| NextToken(); | |
| expr = ParseUnaryExpression(); | |
| if (!HasError()) | |
| expr = pdfium::MakeUnique<CXFA_FMPosExpression>(line, std::move(expr)); | |
| else | |
| expr.reset(); | |
| break; | |
| case TOKminus: | |
| NextToken(); | |
| expr = ParseUnaryExpression(); | |
| if (!HasError()) | |
| expr = pdfium::MakeUnique<CXFA_FMNegExpression>(line, std::move(expr)); | |
| else | |
| expr.reset(); | |
| break; | |
| case TOKksnot: | |
| NextToken(); | |
| expr = ParseUnaryExpression(); | |
| if (!HasError()) | |
| expr = pdfium::MakeUnique<CXFA_FMNotExpression>(line, std::move(expr)); | |
| else | |
| expr.reset(); | |
| break; | |
| default: | |
| expr = ParsePrimaryExpression(); | |
| break; | |
| } | |
| return expr; | |
| } | |
| std::unique_ptr<CXFA_FMSimpleExpression> | |
| CXFA_FMParse::ParsePrimaryExpression() { | |
| std::unique_ptr<CXFA_FMSimpleExpression> expr; | |
| uint32_t line = m_pToken->m_uLinenum; | |
| switch (m_pToken->m_type) { | |
| case TOKnumber: | |
| expr = pdfium::MakeUnique<CXFA_FMNumberExpression>(line, | |
| m_pToken->m_wstring); | |
| NextToken(); | |
| break; | |
| case TOKstring: | |
| expr = pdfium::MakeUnique<CXFA_FMStringExpression>(line, | |
| m_pToken->m_wstring); | |
| NextToken(); | |
| break; | |
| case TOKidentifier: { | |
| CFX_WideStringC wsIdentifier(m_pToken->m_wstring); | |
| NextToken(); | |
| if (m_pToken->m_type == TOKlbracket) { | |
| std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression(); | |
| if (s) { | |
| expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>( | |
| line, nullptr, TOKdot, wsIdentifier, std::move(s)); | |
| } | |
| NextToken(); | |
| } else { | |
| expr = | |
| pdfium::MakeUnique<CXFA_FMIdentifierExpression>(line, wsIdentifier); | |
| } | |
| break; | |
| } | |
| case TOKif: | |
| expr = pdfium::MakeUnique<CXFA_FMIdentifierExpression>( | |
| line, m_pToken->m_wstring); | |
| NextToken(); | |
| break; | |
| case TOKnull: | |
| expr = pdfium::MakeUnique<CXFA_FMNullExpression>(line); | |
| NextToken(); | |
| break; | |
| case TOKlparen: | |
| expr = ParseParenExpression(); | |
| break; | |
| default: | |
| m_ParserError = true; | |
| NextToken(); | |
| break; | |
| } | |
| expr = ParsePostExpression(std::move(expr)); | |
| if (HasError()) | |
| expr.reset(); | |
| return expr; | |
| } | |
| std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParse::ParsePostExpression( | |
| std::unique_ptr<CXFA_FMSimpleExpression> expr) { | |
| uint32_t line = m_pToken->m_uLinenum; | |
| while (1) { | |
| switch (m_pToken->m_type) { | |
| case TOKlparen: { | |
| NextToken(); | |
| std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> expressions; | |
| if (m_pToken->m_type != TOKrparen) { | |
| while (m_pToken->m_type != TOKrparen) { | |
| if (std::unique_ptr<CXFA_FMSimpleExpression> expr = | |
| ParseSimpleExpression()) | |
| expressions.push_back(std::move(expr)); | |
| if (m_pToken->m_type == TOKcomma) { | |
| NextToken(); | |
| } else if (m_pToken->m_type == TOKeof || | |
| m_pToken->m_type == TOKreserver) { | |
| break; | |
| } | |
| } | |
| if (m_pToken->m_type != TOKrparen) | |
| m_ParserError = true; | |
| } | |
| if (!HasError()) { | |
| expr = pdfium::MakeUnique<CXFA_FMCallExpression>( | |
| line, std::move(expr), std::move(expressions), false); | |
| NextToken(); | |
| if (m_pToken->m_type != TOKlbracket) | |
| continue; | |
| std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression(); | |
| if (s) { | |
| expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>( | |
| line, std::move(expr), TOKcall, L"", std::move(s)); | |
| } else { | |
| expr.reset(); | |
| } | |
| } else { | |
| expr.reset(); | |
| } | |
| break; | |
| } | |
| case TOKdot: | |
| NextToken(); | |
| if (m_pToken->m_type == TOKidentifier) { | |
| CFX_WideStringC tempStr = m_pToken->m_wstring; | |
| uint32_t tempLine = m_pToken->m_uLinenum; | |
| NextToken(); | |
| if (m_pToken->m_type == TOKlparen) { | |
| std::unique_ptr<CXFA_FMSimpleExpression> pExpCall; | |
| NextToken(); | |
| std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> expressions; | |
| if (m_pToken->m_type != TOKrparen) { | |
| while (m_pToken->m_type != TOKrparen) { | |
| std::unique_ptr<CXFA_FMSimpleExpression> exp = | |
| ParseSimpleExpression(); | |
| expressions.push_back(std::move(exp)); | |
| if (m_pToken->m_type == TOKcomma) { | |
| NextToken(); | |
| } else if (m_pToken->m_type == TOKeof || | |
| m_pToken->m_type == TOKreserver) { | |
| break; | |
| } | |
| } | |
| if (m_pToken->m_type != TOKrparen) | |
| m_ParserError = true; | |
| } | |
| if (!HasError()) { | |
| std::unique_ptr<CXFA_FMSimpleExpression> pIdentifier = | |
| pdfium::MakeUnique<CXFA_FMIdentifierExpression>(tempLine, | |
| tempStr); | |
| pExpCall = pdfium::MakeUnique<CXFA_FMCallExpression>( | |
| line, std::move(pIdentifier), std::move(expressions), true); | |
| expr = pdfium::MakeUnique<CXFA_FMMethodCallExpression>( | |
| line, std::move(expr), std::move(pExpCall)); | |
| NextToken(); | |
| if (m_pToken->m_type != TOKlbracket) | |
| continue; | |
| std::unique_ptr<CXFA_FMSimpleExpression> s = | |
| ParseIndexExpression(); | |
| if (s) { | |
| expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>( | |
| line, std::move(expr), TOKcall, L"", std::move(s)); | |
| } else { | |
| expr.reset(); | |
| } | |
| } else { | |
| expr.reset(); | |
| } | |
| } else if (m_pToken->m_type == TOKlbracket) { | |
| std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression(); | |
| if (HasError()) | |
| return nullptr; | |
| expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>( | |
| tempLine, std::move(expr), TOKdot, tempStr, std::move(s)); | |
| } else { | |
| std::unique_ptr<CXFA_FMSimpleExpression> s = | |
| pdfium::MakeUnique<CXFA_FMIndexExpression>( | |
| tempLine, ACCESSOR_NO_INDEX, nullptr, false); | |
| expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>( | |
| line, std::move(expr), TOKdot, tempStr, std::move(s)); | |
| continue; | |
| } | |
| } else { | |
| m_ParserError = true; | |
| return expr; | |
| } | |
| break; | |
| case TOKdotdot: | |
| NextToken(); | |
| if (m_pToken->m_type == TOKidentifier) { | |
| CFX_WideStringC tempStr = m_pToken->m_wstring; | |
| uint32_t tempLine = m_pToken->m_uLinenum; | |
| NextToken(); | |
| if (m_pToken->m_type == TOKlbracket) { | |
| std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression(); | |
| if (HasError()) | |
| return nullptr; | |
| expr = pdfium::MakeUnique<CXFA_FMDotDotAccessorExpression>( | |
| tempLine, std::move(expr), TOKdotdot, tempStr, std::move(s)); | |
| } else { | |
| std::unique_ptr<CXFA_FMSimpleExpression> s = | |
| pdfium::MakeUnique<CXFA_FMIndexExpression>( | |
| tempLine, ACCESSOR_NO_INDEX, nullptr, false); | |
| expr = pdfium::MakeUnique<CXFA_FMDotDotAccessorExpression>( | |
| line, std::move(expr), TOKdotdot, tempStr, std::move(s)); | |
| continue; | |
| } | |
| } else { | |
| m_ParserError = true; | |
| return expr; | |
| } | |
| break; | |
| case TOKdotscream: { | |
| NextToken(); | |
| if (m_pToken->m_type != TOKidentifier) { | |
| m_ParserError = true; | |
| return expr; | |
| } | |
| CFX_WideStringC tempStr = m_pToken->m_wstring; | |
| uint32_t tempLine = m_pToken->m_uLinenum; | |
| NextToken(); | |
| if (m_pToken->m_type != TOKlbracket) { | |
| std::unique_ptr<CXFA_FMSimpleExpression> s = | |
| pdfium::MakeUnique<CXFA_FMIndexExpression>( | |
| tempLine, ACCESSOR_NO_INDEX, nullptr, false); | |
| expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>( | |
| line, std::move(expr), TOKdotscream, tempStr, std::move(s)); | |
| continue; | |
| } | |
| std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression(); | |
| if (HasError()) | |
| return nullptr; | |
| expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>( | |
| tempLine, std::move(expr), TOKdotscream, tempStr, std::move(s)); | |
| break; | |
| } | |
| case TOKdotstar: { | |
| std::unique_ptr<CXFA_FMSimpleExpression> s = | |
| pdfium::MakeUnique<CXFA_FMIndexExpression>(line, ACCESSOR_NO_INDEX, | |
| nullptr, false); | |
| expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>( | |
| line, std::move(expr), TOKdotstar, L"*", std::move(s)); | |
| break; | |
| } | |
| default: | |
| return expr; | |
| } | |
| NextToken(); | |
| } | |
| return expr; | |
| } | |
| std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParse::ParseIndexExpression() { | |
| std::unique_ptr<CXFA_FMSimpleExpression> pExp; | |
| uint32_t line = m_pToken->m_uLinenum; | |
| NextToken(); | |
| std::unique_ptr<CXFA_FMSimpleExpression> s; | |
| XFA_FM_AccessorIndex accessorIndex = ACCESSOR_NO_RELATIVEINDEX; | |
| if (m_pToken->m_type == TOKmul) { | |
| pExp = pdfium::MakeUnique<CXFA_FMIndexExpression>(line, accessorIndex, | |
| std::move(s), true); | |
| NextToken(); | |
| if (m_pToken->m_type != TOKrbracket) { | |
| m_ParserError = true; | |
| pExp.reset(); | |
| } | |
| return pExp; | |
| } | |
| if (m_pToken->m_type == TOKplus) { | |
| accessorIndex = ACCESSOR_POSITIVE_INDEX; | |
| NextToken(); | |
| } else if (m_pToken->m_type == TOKminus) { | |
| accessorIndex = ACCESSOR_NEGATIVE_INDEX; | |
| NextToken(); | |
| } | |
| s = ParseSimpleExpression(); | |
| if (m_pToken->m_type != TOKrbracket) { | |
| m_ParserError = true; | |
| } else { | |
| pExp = pdfium::MakeUnique<CXFA_FMIndexExpression>(line, accessorIndex, | |
| std::move(s), false); | |
| } | |
| return pExp; | |
| } | |
| std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParse::ParseParenExpression() { | |
| Check(TOKlparen); | |
| if (m_pToken->m_type == TOKrparen) { | |
| m_ParserError = true; | |
| NextToken(); | |
| return nullptr; | |
| } | |
| uint32_t line = m_pToken->m_uLinenum; | |
| std::unique_ptr<CXFA_FMSimpleExpression> pExp1 = ParseLogicalOrExpression(); | |
| int level = 1; | |
| while (m_pToken->m_type == TOKassign) { | |
| NextToken(); | |
| std::unique_ptr<CXFA_FMSimpleExpression> pExp2 = ParseLogicalOrExpression(); | |
| if (level++ == kMaxAssignmentChainLength) | |
| m_ParserError = true; | |
| if (!HasError()) { | |
| pExp1 = pdfium::MakeUnique<CXFA_FMAssignExpression>( | |
| line, TOKassign, std::move(pExp1), std::move(pExp2)); | |
| } else { | |
| pExp1.reset(); | |
| } | |
| } | |
| Check(TOKrparen); | |
| return pExp1; | |
| } | |
| std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseBlockExpression() { | |
| uint32_t line = m_pToken->m_uLinenum; | |
| std::unique_ptr<CXFA_FMExpression> expr; | |
| std::vector<std::unique_ptr<CXFA_FMExpression>> expressions; | |
| while (1) { | |
| switch (m_pToken->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) { | |
| expressions.push_back(std::move(expr)); | |
| } | |
| continue; | |
| default: | |
| expr = ParseExpression(); | |
| if (expr) { | |
| expressions.push_back(std::move(expr)); | |
| } | |
| continue; | |
| } | |
| break; | |
| } | |
| std::unique_ptr<CXFA_FMBlockExpression> pExp; | |
| if (!HasError()) { | |
| pExp = pdfium::MakeUnique<CXFA_FMBlockExpression>(line, | |
| std::move(expressions)); | |
| } | |
| return pExp; | |
| } | |
| std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseIfExpression() { | |
| uint32_t line = m_pToken->m_uLinenum; | |
| const wchar_t* pStartPos = m_lexer->GetPos(); | |
| NextToken(); | |
| Check(TOKlparen); | |
| std::unique_ptr<CXFA_FMSimpleExpression> pExpression; | |
| while (m_pToken->m_type != TOKrparen) { | |
| pExpression = ParseSimpleExpression(); | |
| if (m_pToken->m_type != TOKcomma) | |
| break; | |
| NextToken(); | |
| } | |
| Check(TOKrparen); | |
| if (m_pToken->m_type != TOKthen) { | |
| m_lexer->SetCurrentLine(line); | |
| auto pNewToken = pdfium::MakeUnique<CXFA_FMToken>(line); | |
| m_pToken = pNewToken.get(); | |
| m_pToken->m_type = TOKidentifier; | |
| m_pToken->m_wstring = L"if"; | |
| m_lexer->SetToken(std::move(pNewToken)); | |
| m_lexer->SetPos(pStartPos); | |
| return ParseExpExpression(); | |
| } | |
| Check(TOKthen); | |
| std::unique_ptr<CXFA_FMExpression> pIfExpression = ParseBlockExpression(); | |
| std::unique_ptr<CXFA_FMExpression> pElseExpression; | |
| switch (m_pToken->m_type) { | |
| case TOKeof: | |
| case TOKendif: | |
| Check(TOKendif); | |
| break; | |
| case TOKif: | |
| pElseExpression = ParseIfExpression(); | |
| Check(TOKendif); | |
| break; | |
| case TOKelseif: | |
| pElseExpression = ParseIfExpression(); | |
| break; | |
| case TOKelse: | |
| NextToken(); | |
| pElseExpression = ParseBlockExpression(); | |
| Check(TOKendif); | |
| break; | |
| default: | |
| m_ParserError = true; | |
| NextToken(); | |
| break; | |
| } | |
| std::unique_ptr<CXFA_FMIfExpression> pExp; | |
| if (!HasError()) { | |
| pExp = pdfium::MakeUnique<CXFA_FMIfExpression>(line, std::move(pExpression), | |
| std::move(pIfExpression), | |
| std::move(pElseExpression)); | |
| } | |
| return pExp; | |
| } | |
| std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseWhileExpression() { | |
| uint32_t line = m_pToken->m_uLinenum; | |
| NextToken(); | |
| std::unique_ptr<CXFA_FMSimpleExpression> pCondition = ParseParenExpression(); | |
| Check(TOKdo); | |
| std::unique_ptr<CXFA_FMExpression> pExpression = ParseBlockExpression(); | |
| Check(TOKendwhile); | |
| std::unique_ptr<CXFA_FMExpression> expr; | |
| if (!HasError()) { | |
| expr = pdfium::MakeUnique<CXFA_FMWhileExpression>( | |
| line, std::move(pCondition), std::move(pExpression)); | |
| } | |
| return expr; | |
| } | |
| std::unique_ptr<CXFA_FMSimpleExpression> | |
| CXFA_FMParse::ParseSubassignmentInForExpression() { | |
| std::unique_ptr<CXFA_FMSimpleExpression> expr; | |
| switch (m_pToken->m_type) { | |
| case TOKidentifier: | |
| expr = ParseSimpleExpression(); | |
| break; | |
| default: | |
| m_ParserError = true; | |
| NextToken(); | |
| break; | |
| } | |
| return expr; | |
| } | |
| std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseForExpression() { | |
| CFX_WideStringC wsVariant; | |
| uint32_t line = m_pToken->m_uLinenum; | |
| NextToken(); | |
| if (m_pToken->m_type != TOKidentifier) | |
| m_ParserError = true; | |
| wsVariant = m_pToken->m_wstring; | |
| NextToken(); | |
| std::unique_ptr<CXFA_FMSimpleExpression> pAssignment; | |
| if (m_pToken->m_type == TOKassign) { | |
| NextToken(); | |
| pAssignment = ParseSimpleExpression(); | |
| } else { | |
| m_ParserError = true; | |
| } | |
| int32_t iDirection = 0; | |
| if (m_pToken->m_type == TOKupto) | |
| iDirection = 1; | |
| else if (m_pToken->m_type == TOKdownto) | |
| iDirection = -1; | |
| else | |
| m_ParserError = true; | |
| NextToken(); | |
| std::unique_ptr<CXFA_FMSimpleExpression> pAccessor = ParseSimpleExpression(); | |
| std::unique_ptr<CXFA_FMSimpleExpression> pStep; | |
| if (m_pToken->m_type == TOKstep) { | |
| NextToken(); | |
| pStep = ParseSimpleExpression(); | |
| } | |
| Check(TOKdo); | |
| std::unique_ptr<CXFA_FMExpression> pList = ParseBlockExpression(); | |
| Check(TOKendfor); | |
| std::unique_ptr<CXFA_FMExpression> expr; | |
| if (!HasError()) { | |
| expr = pdfium::MakeUnique<CXFA_FMForExpression>( | |
| line, wsVariant, std::move(pAssignment), std::move(pAccessor), | |
| iDirection, std::move(pStep), std::move(pList)); | |
| } | |
| return expr; | |
| } | |
| std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseForeachExpression() { | |
| std::unique_ptr<CXFA_FMExpression> expr; | |
| CFX_WideStringC wsIdentifier; | |
| std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> pAccessors; | |
| std::unique_ptr<CXFA_FMExpression> pList; | |
| uint32_t line = m_pToken->m_uLinenum; | |
| NextToken(); | |
| if (m_pToken->m_type != TOKidentifier) | |
| m_ParserError = true; | |
| wsIdentifier = m_pToken->m_wstring; | |
| NextToken(); | |
| Check(TOKin); | |
| Check(TOKlparen); | |
| if (m_pToken->m_type == TOKrparen) { | |
| m_ParserError = true; | |
| NextToken(); | |
| } else { | |
| while (m_pToken->m_type != TOKrparen) { | |
| std::unique_ptr<CXFA_FMSimpleExpression> s = ParseSimpleExpression(); | |
| if (s) | |
| pAccessors.push_back(std::move(s)); | |
| if (m_pToken->m_type != TOKcomma) | |
| break; | |
| NextToken(); | |
| } | |
| Check(TOKrparen); | |
| } | |
| Check(TOKdo); | |
| pList = ParseBlockExpression(); | |
| Check(TOKendfor); | |
| if (!HasError()) { | |
| expr = pdfium::MakeUnique<CXFA_FMForeachExpression>( | |
| line, wsIdentifier, std::move(pAccessors), std::move(pList)); | |
| } | |
| return expr; | |
| } | |
| std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseDoExpression() { | |
| uint32_t line = m_pToken->m_uLinenum; | |
| NextToken(); | |
| std::unique_ptr<CXFA_FMExpression> expr = ParseBlockExpression(); | |
| Check(TOKend); | |
| if (HasError()) | |
| return nullptr; | |
| return pdfium::MakeUnique<CXFA_FMDoExpression>(line, std::move(expr)); | |
| } | |
| bool CXFA_FMParse::HasError() const { | |
| return m_ParserError || m_lexer->HasError(); | |
| } |