From db1e8a500588abb98026bafac376b953f61813d2 Mon Sep 17 00:00:00 2001 From: Ryan Harrison Date: Thu, 27 Jul 2017 14:53:20 -0400 Subject: Move CXFA_FMParse to CFXA_FMParser Minor nit I had with this code and want to fix. Bug: Change-Id: I2494667d580bf982a4359153123d9e8afb75e349 Reviewed-on: https://pdfium-review.googlesource.com/9370 Reviewed-by: Tom Sepez Reviewed-by: (OOO Jul 28 - Aug 8) dsinclair Commit-Queue: Ryan Harrison --- BUILD.gn | 6 +- xfa/fxfa/fm2js/cxfa_fm2jscontext.cpp | 4 +- xfa/fxfa/fm2js/cxfa_fmparse.cpp | 1184 ----------------------------- xfa/fxfa/fm2js/cxfa_fmparse.h | 59 -- xfa/fxfa/fm2js/cxfa_fmparse_unittest.cpp | 108 --- xfa/fxfa/fm2js/cxfa_fmparser.cpp | 1184 +++++++++++++++++++++++++++++ xfa/fxfa/fm2js/cxfa_fmparser.h | 59 ++ xfa/fxfa/fm2js/cxfa_fmparser_unittest.cpp | 109 +++ 8 files changed, 1357 insertions(+), 1356 deletions(-) delete mode 100644 xfa/fxfa/fm2js/cxfa_fmparse.cpp delete mode 100644 xfa/fxfa/fm2js/cxfa_fmparse.h delete mode 100644 xfa/fxfa/fm2js/cxfa_fmparse_unittest.cpp create mode 100644 xfa/fxfa/fm2js/cxfa_fmparser.cpp create mode 100644 xfa/fxfa/fm2js/cxfa_fmparser.h create mode 100644 xfa/fxfa/fm2js/cxfa_fmparser_unittest.cpp diff --git a/BUILD.gn b/BUILD.gn index 057e84ff00..f2dbc6816f 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1716,8 +1716,8 @@ if (pdf_enable_xfa) { "xfa/fxfa/fm2js/cxfa_fmexpression.h", "xfa/fxfa/fm2js/cxfa_fmlexer.cpp", "xfa/fxfa/fm2js/cxfa_fmlexer.h", - "xfa/fxfa/fm2js/cxfa_fmparse.cpp", - "xfa/fxfa/fm2js/cxfa_fmparse.h", + "xfa/fxfa/fm2js/cxfa_fmparser.cpp", + "xfa/fxfa/fm2js/cxfa_fmparser.h", "xfa/fxfa/fm2js/cxfa_fmsimpleexpression.cpp", "xfa/fxfa/fm2js/cxfa_fmsimpleexpression.h", "xfa/fxfa/fxfa.h", @@ -1956,7 +1956,7 @@ test("pdfium_unittests") { "xfa/fxfa/cxfa_ffbarcode_unittest.cpp", "xfa/fxfa/cxfa_textparser_unittest.cpp", "xfa/fxfa/fm2js/cxfa_fmlexer_unittest.cpp", - "xfa/fxfa/fm2js/cxfa_fmparse_unittest.cpp", + "xfa/fxfa/fm2js/cxfa_fmparser_unittest.cpp", "xfa/fxfa/fm2js/cxfa_fmsimpleexpression_unittest.cpp", "xfa/fxfa/parser/xfa_utils_unittest.cpp", ] diff --git a/xfa/fxfa/fm2js/cxfa_fm2jscontext.cpp b/xfa/fxfa/fm2js/cxfa_fm2jscontext.cpp index 1e8e1469a5..445d729668 100644 --- a/xfa/fxfa/fm2js/cxfa_fm2jscontext.cpp +++ b/xfa/fxfa/fm2js/cxfa_fm2jscontext.cpp @@ -19,7 +19,7 @@ #include "third_party/base/ptr_util.h" #include "third_party/base/stl_util.h" #include "xfa/fxfa/cxfa_ffnotify.h" -#include "xfa/fxfa/fm2js/cxfa_fmparse.h" +#include "xfa/fxfa/fm2js/cxfa_fmparser.h" #include "xfa/fxfa/parser/cxfa_document.h" #include "xfa/fxfa/parser/cxfa_localevalue.h" #include "xfa/fxfa/parser/cxfa_node.h" @@ -6055,7 +6055,7 @@ bool CXFA_FM2JSContext::Translate(const CFX_WideStringC& wsFormcalc, return true; } - CXFA_FMParse parser(wsFormcalc); + CXFA_FMParser parser(wsFormcalc); std::unique_ptr func = parser.Parse(); if (!func || parser.HasError()) return false; diff --git a/xfa/fxfa/fm2js/cxfa_fmparse.cpp b/xfa/fxfa/fm2js/cxfa_fmparse.cpp deleted file mode 100644 index 8e163a40d0..0000000000 --- a/xfa/fxfa/fm2js/cxfa_fmparse.cpp +++ /dev/null @@ -1,1184 +0,0 @@ -// 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 -#include -#include - -#include "third_party/base/ptr_util.h" - -namespace { - -const int kMaxAssignmentChainLength = 12; - -} // namespace - -CXFA_FMParse::CXFA_FMParse(const CFX_WideStringC& wsFormcalc) : m_error(false) { - m_lexer = pdfium::MakeUnique(wsFormcalc); - m_token = m_lexer->NextToken(); -} - -CXFA_FMParse::~CXFA_FMParse() {} - -std::unique_ptr CXFA_FMParse::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_FMParse::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_FMParse::CheckThenNext(XFA_FM_TOKEN op) { - if (HasError()) - return false; - - if (m_token->m_type != op) { - m_error = true; - return false; - } - return NextToken(); -} - -std::vector> -CXFA_FMParse::ParseTopExpression() { - std::unique_ptr expr; - std::vector> expressions; - if (HasError()) - return 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; - expressions.clear(); - break; - } - expressions.push_back(std::move(expr)); - } - if (HasError()) - expressions.clear(); - return expressions; -} - -std::unique_ptr CXFA_FMParse::ParseFunction() { - if (HasError()) - 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_FMParse::ParseExpression() { - if (HasError()) - 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_FMParse::ParseVarExpression() { - if (HasError()) - 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_FMParse::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_FMParse::ParseExpExpression() { - if (HasError()) - 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_FMParse::ParseLogicalOrExpression() { - if (HasError()) - 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_FMParse::ParseLogicalAndExpression() { - if (HasError()) - 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_FMParse::ParseEqualityExpression() { - if (HasError()) - 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_FMParse::ParseRelationalExpression() { - if (HasError()) - 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_FMParse::ParseAddtiveExpression() { - if (HasError()) - 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_FMParse::ParseMultiplicativeExpression() { - if (HasError()) - 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_FMParse::ParseUnaryExpression() { - if (HasError()) - 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_FMParse::ParsePrimaryExpression() { - if (HasError()) - 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_FMParse::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) { - if (std::unique_ptr expr = - ParseSimpleExpression()) - expressions.push_back(std::move(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_FMParse::ParseIndexExpression() { - if (HasError()) - 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_FMParse::ParseParenExpression() { - 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_FMParse::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_FMParse::ParseIfExpression() { - if (HasError()) - 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_FMParse::ParseWhileExpression() { - if (HasError()) - 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_FMParse::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_FMParse::ParseForExpression() { - if (HasError()) - 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_FMParse::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_FMParse::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_FMParse::HasError() const { - return m_error || m_token == nullptr; -} diff --git a/xfa/fxfa/fm2js/cxfa_fmparse.h b/xfa/fxfa/fm2js/cxfa_fmparse.h deleted file mode 100644 index 7377cc75d7..0000000000 --- a/xfa/fxfa/fm2js/cxfa_fmparse.h +++ /dev/null @@ -1,59 +0,0 @@ -// 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 - -#ifndef XFA_FXFA_FM2JS_CXFA_FMPARSE_H_ -#define XFA_FXFA_FM2JS_CXFA_FMPARSE_H_ - -#include -#include - -#include "xfa/fxfa/fm2js/cxfa_fmexpression.h" -#include "xfa/fxfa/fm2js/cxfa_fmlexer.h" - -class CXFA_FMParse { - public: - explicit CXFA_FMParse(const CFX_WideStringC& wsFormcalc); - ~CXFA_FMParse(); - - std::unique_ptr Parse(); - bool HasError() const; - - private: - bool NextToken(); - bool CheckThenNext(XFA_FM_TOKEN op); - - std::vector> ParseTopExpression(); - std::unique_ptr ParseFunction(); - std::unique_ptr ParseExpression(); - std::unique_ptr ParseVarExpression(); - std::unique_ptr ParseExpExpression(); - std::unique_ptr ParseBlockExpression(); - std::unique_ptr ParseIfExpression(); - std::unique_ptr ParseWhileExpression(); - std::unique_ptr ParseForExpression(); - std::unique_ptr ParseForeachExpression(); - std::unique_ptr ParseDoExpression(); - std::unique_ptr ParseParenExpression(); - std::unique_ptr ParseSimpleExpression(); - std::unique_ptr ParseSubassignmentInForExpression(); - std::unique_ptr ParseLogicalOrExpression(); - std::unique_ptr ParseLogicalAndExpression(); - std::unique_ptr ParseEqualityExpression(); - std::unique_ptr ParseRelationalExpression(); - std::unique_ptr ParseAddtiveExpression(); - std::unique_ptr ParseMultiplicativeExpression(); - std::unique_ptr ParseUnaryExpression(); - std::unique_ptr ParsePrimaryExpression(); - std::unique_ptr ParsePostExpression( - std::unique_ptr e); - std::unique_ptr ParseIndexExpression(); - - std::unique_ptr m_lexer; - std::unique_ptr m_token; - bool m_error; -}; - -#endif // XFA_FXFA_FM2JS_CXFA_FMPARSE_H_ diff --git a/xfa/fxfa/fm2js/cxfa_fmparse_unittest.cpp b/xfa/fxfa/fm2js/cxfa_fmparse_unittest.cpp deleted file mode 100644 index 9e6972b356..0000000000 --- a/xfa/fxfa/fm2js/cxfa_fmparse_unittest.cpp +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2017 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. - -#include "xfa/fxfa/fm2js/cxfa_fmparse.h" - -#include - -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/test_support.h" -#include "third_party/base/ptr_util.h" - -TEST(CXFA_FMParseTest, Empty) { - auto parser = pdfium::MakeUnique(L""); - std::unique_ptr ast = parser->Parse(); - ASSERT(ast != nullptr); - EXPECT_FALSE(parser->HasError()); - - CFX_WideTextBuf buf; - EXPECT_TRUE(ast->ToJavaScript(buf)); - // TODO(dsinclair): This is a little weird ..... - EXPECT_EQ(L"// comments only", buf.AsStringC()); -} - -TEST(CXFA_FMParseTest, CommentOnlyIsError) { - auto parser = pdfium::MakeUnique(L"; Just comment"); - std::unique_ptr ast = parser->Parse(); - ASSERT(ast != nullptr); - // TODO(dsinclair): This isn't allowed per the spec. - EXPECT_FALSE(parser->HasError()); - // EXPECT_TRUE(parser->HasError()); - - CFX_WideTextBuf buf; - EXPECT_TRUE(ast->ToJavaScript(buf)); - EXPECT_EQ(L"// comments only", buf.AsStringC()); -} - -TEST(CXFA_FMParseTest, CommentThenValue) { - const wchar_t ret[] = - L"(\nfunction ()\n{\n" - L"var pfm_ret = null;\n" - L"pfm_ret = 12;\n" - L"return pfm_rt.get_val(pfm_ret);\n" - L"}\n).call(this);\n"; - - auto parser = pdfium::MakeUnique(L"; Just comment\n12"); - std::unique_ptr ast = parser->Parse(); - ASSERT(ast != nullptr); - EXPECT_FALSE(parser->HasError()); - - CFX_WideTextBuf buf; - EXPECT_TRUE(ast->ToJavaScript(buf)); - EXPECT_EQ(ret, buf.AsStringC()); -} - -TEST(CXFA_FMParseTest, Parse) { - const wchar_t input[] = L"$ = Avg (-3, 5, -6, 12, -13);\n" - L"$ = Avg (Table2..Row[*].Cell1);\n" - L"\n" - L"if ($ ne -1)then\n" - L" border.fill.color.value = \"255,64,64\";\n" - L"else\n" - L" border.fill.color.value = \"20,170,13\";\n" - L"endif\n" - L"\n" - L"$"; - - const wchar_t ret[] = - L"(\nfunction ()\n{\n" - L"var pfm_ret = null;\n" - L"if (pfm_rt.is_obj(this))\n{\n" - L"pfm_rt.asgn_val_op(this, pfm_rt.Avg(pfm_rt.neg_op(3), 5, " - L"pfm_rt.neg_op(6), 12, pfm_rt.neg_op(13)));\n" - L"}\n" - L"if (pfm_rt.is_obj(this))\n{\n" - L"pfm_rt.asgn_val_op(this, pfm_rt.Avg(pfm_rt.dot_acc(pfm_rt.dotdot_acc(" - L"Table2, \"Table2\", \"Row\", 1), \"\", \"Cell1\", 0, 0)));\n" - L"}\n" - L"if (pfm_rt.get_val(pfm_rt.neq_op(this, pfm_rt.neg_op(1))))\n{\n" - L"if (pfm_rt.is_obj(pfm_rt.dot_acc(pfm_rt.dot_acc(pfm_rt.dot_acc(" - L"border, \"border\", \"fill\", 0, 0), \"\", \"color\", 0, 0), \"\", " - L"\"value\", 0, 0)))\n{\n" - L"pfm_rt.asgn_val_op(pfm_rt.dot_acc(pfm_rt.dot_acc(" - L"pfm_rt.dot_acc(border, \"border\", \"fill\", 0, 0), \"\", " - L"\"color\", 0, 0), \"\", \"value\", 0, 0), \"255,64,64\");\n" - L"}\n" - L"}\nelse\n{\n" - L"if (pfm_rt.is_obj(pfm_rt.dot_acc(pfm_rt.dot_acc(pfm_rt.dot_acc(" - L"border, \"border\", \"fill\", 0, 0), \"\", \"color\", 0, 0), \"\", " - L"\"value\", 0, 0)))\n{\n" - L"pfm_rt.asgn_val_op(pfm_rt.dot_acc(pfm_rt.dot_acc(" - L"pfm_rt.dot_acc(border, \"border\", \"fill\", 0, 0), \"\", " - L"\"color\", 0, 0), \"\", \"value\", 0, 0), \"20,170,13\");\n" - L"}\n" - L"}\n" - L"pfm_ret = this;\n" - L"return pfm_rt.get_val(pfm_ret);\n" - L"}\n).call(this);\n"; - - auto parser = pdfium::MakeUnique(input); - std::unique_ptr ast = parser->Parse(); - ASSERT(ast != nullptr); - EXPECT_FALSE(parser->HasError()); - - CFX_WideTextBuf buf; - EXPECT_TRUE(ast->ToJavaScript(buf)); - EXPECT_EQ(ret, buf.AsStringC()); -} diff --git a/xfa/fxfa/fm2js/cxfa_fmparser.cpp b/xfa/fxfa/fm2js/cxfa_fmparser.cpp new file mode 100644 index 0000000000..150fa5aeda --- /dev/null +++ b/xfa/fxfa/fm2js/cxfa_fmparser.cpp @@ -0,0 +1,1184 @@ +// 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 int kMaxAssignmentChainLength = 12; + +} // namespace + +CXFA_FMParser::CXFA_FMParser(const CFX_WideStringC& wsFormcalc) + : m_error(false) { + 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(); +} + +std::vector> +CXFA_FMParser::ParseTopExpression() { + std::unique_ptr expr; + std::vector> expressions; + if (HasError()) + return 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; + expressions.clear(); + break; + } + expressions.push_back(std::move(expr)); + } + if (HasError()) + expressions.clear(); + return expressions; +} + +std::unique_ptr CXFA_FMParser::ParseFunction() { + if (HasError()) + 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() { + if (HasError()) + 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() { + if (HasError()) + 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() { + if (HasError()) + 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() { + if (HasError()) + 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() { + if (HasError()) + 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() { + if (HasError()) + 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() { + if (HasError()) + 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() { + if (HasError()) + 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() { + if (HasError()) + 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() { + if (HasError()) + 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() { + if (HasError()) + 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) { + if (std::unique_ptr expr = + ParseSimpleExpression()) + expressions.push_back(std::move(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() { + if (HasError()) + 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() { + 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() { + if (HasError()) + 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() { + if (HasError()) + 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() { + if (HasError()) + 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; +} diff --git a/xfa/fxfa/fm2js/cxfa_fmparser.h b/xfa/fxfa/fm2js/cxfa_fmparser.h new file mode 100644 index 0000000000..66eb1f8392 --- /dev/null +++ b/xfa/fxfa/fm2js/cxfa_fmparser.h @@ -0,0 +1,59 @@ +// 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 + +#ifndef XFA_FXFA_FM2JS_CXFA_FMPARSER_H_ +#define XFA_FXFA_FM2JS_CXFA_FMPARSER_H_ + +#include +#include + +#include "xfa/fxfa/fm2js/cxfa_fmexpression.h" +#include "xfa/fxfa/fm2js/cxfa_fmlexer.h" + +class CXFA_FMParser { + public: + explicit CXFA_FMParser(const CFX_WideStringC& wsFormcalc); + ~CXFA_FMParser(); + + std::unique_ptr Parse(); + bool HasError() const; + + private: + bool NextToken(); + bool CheckThenNext(XFA_FM_TOKEN op); + + std::vector> ParseTopExpression(); + std::unique_ptr ParseFunction(); + std::unique_ptr ParseExpression(); + std::unique_ptr ParseVarExpression(); + std::unique_ptr ParseExpExpression(); + std::unique_ptr ParseBlockExpression(); + std::unique_ptr ParseIfExpression(); + std::unique_ptr ParseWhileExpression(); + std::unique_ptr ParseForExpression(); + std::unique_ptr ParseForeachExpression(); + std::unique_ptr ParseDoExpression(); + std::unique_ptr ParseParenExpression(); + std::unique_ptr ParseSimpleExpression(); + std::unique_ptr ParseSubassignmentInForExpression(); + std::unique_ptr ParseLogicalOrExpression(); + std::unique_ptr ParseLogicalAndExpression(); + std::unique_ptr ParseEqualityExpression(); + std::unique_ptr ParseRelationalExpression(); + std::unique_ptr ParseAddtiveExpression(); + std::unique_ptr ParseMultiplicativeExpression(); + std::unique_ptr ParseUnaryExpression(); + std::unique_ptr ParsePrimaryExpression(); + std::unique_ptr ParsePostExpression( + std::unique_ptr e); + std::unique_ptr ParseIndexExpression(); + + std::unique_ptr m_lexer; + std::unique_ptr m_token; + bool m_error; +}; + +#endif // XFA_FXFA_FM2JS_CXFA_FMPARSER_H_ diff --git a/xfa/fxfa/fm2js/cxfa_fmparser_unittest.cpp b/xfa/fxfa/fm2js/cxfa_fmparser_unittest.cpp new file mode 100644 index 0000000000..9907890e83 --- /dev/null +++ b/xfa/fxfa/fm2js/cxfa_fmparser_unittest.cpp @@ -0,0 +1,109 @@ +// Copyright 2017 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. + +#include "xfa/fxfa/fm2js/cxfa_fmparser.h" + +#include + +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" +#include "third_party/base/ptr_util.h" + +TEST(CXFA_FMParserTest, Empty) { + auto parser = pdfium::MakeUnique(L""); + std::unique_ptr ast = parser->Parse(); + ASSERT(ast != nullptr); + EXPECT_FALSE(parser->HasError()); + + CFX_WideTextBuf buf; + EXPECT_TRUE(ast->ToJavaScript(buf)); + // TODO(dsinclair): This is a little weird ..... + EXPECT_EQ(L"// comments only", buf.AsStringC()); +} + +TEST(CXFA_FMParserTest, CommentOnlyIsError) { + auto parser = pdfium::MakeUnique(L"; Just comment"); + std::unique_ptr ast = parser->Parse(); + ASSERT(ast != nullptr); + // TODO(dsinclair): This isn't allowed per the spec. + EXPECT_FALSE(parser->HasError()); + // EXPECT_TRUE(parser->HasError()); + + CFX_WideTextBuf buf; + EXPECT_TRUE(ast->ToJavaScript(buf)); + EXPECT_EQ(L"// comments only", buf.AsStringC()); +} + +TEST(CXFA_FMParserTest, CommentThenValue) { + const wchar_t ret[] = + L"(\nfunction ()\n{\n" + L"var pfm_ret = null;\n" + L"pfm_ret = 12;\n" + L"return pfm_rt.get_val(pfm_ret);\n" + L"}\n).call(this);\n"; + + auto parser = pdfium::MakeUnique(L"; Just comment\n12"); + std::unique_ptr ast = parser->Parse(); + ASSERT(ast != nullptr); + EXPECT_FALSE(parser->HasError()); + + CFX_WideTextBuf buf; + EXPECT_TRUE(ast->ToJavaScript(buf)); + EXPECT_EQ(ret, buf.AsStringC()); +} + +TEST(CXFA_FMParserTest, Parse) { + const wchar_t input[] = + L"$ = Avg (-3, 5, -6, 12, -13);\n" + L"$ = Avg (Table2..Row[*].Cell1);\n" + L"\n" + L"if ($ ne -1)then\n" + L" border.fill.color.value = \"255,64,64\";\n" + L"else\n" + L" border.fill.color.value = \"20,170,13\";\n" + L"endif\n" + L"\n" + L"$"; + + const wchar_t ret[] = + L"(\nfunction ()\n{\n" + L"var pfm_ret = null;\n" + L"if (pfm_rt.is_obj(this))\n{\n" + L"pfm_rt.asgn_val_op(this, pfm_rt.Avg(pfm_rt.neg_op(3), 5, " + L"pfm_rt.neg_op(6), 12, pfm_rt.neg_op(13)));\n" + L"}\n" + L"if (pfm_rt.is_obj(this))\n{\n" + L"pfm_rt.asgn_val_op(this, pfm_rt.Avg(pfm_rt.dot_acc(pfm_rt.dotdot_acc(" + L"Table2, \"Table2\", \"Row\", 1), \"\", \"Cell1\", 0, 0)));\n" + L"}\n" + L"if (pfm_rt.get_val(pfm_rt.neq_op(this, pfm_rt.neg_op(1))))\n{\n" + L"if (pfm_rt.is_obj(pfm_rt.dot_acc(pfm_rt.dot_acc(pfm_rt.dot_acc(" + L"border, \"border\", \"fill\", 0, 0), \"\", \"color\", 0, 0), \"\", " + L"\"value\", 0, 0)))\n{\n" + L"pfm_rt.asgn_val_op(pfm_rt.dot_acc(pfm_rt.dot_acc(" + L"pfm_rt.dot_acc(border, \"border\", \"fill\", 0, 0), \"\", " + L"\"color\", 0, 0), \"\", \"value\", 0, 0), \"255,64,64\");\n" + L"}\n" + L"}\nelse\n{\n" + L"if (pfm_rt.is_obj(pfm_rt.dot_acc(pfm_rt.dot_acc(pfm_rt.dot_acc(" + L"border, \"border\", \"fill\", 0, 0), \"\", \"color\", 0, 0), \"\", " + L"\"value\", 0, 0)))\n{\n" + L"pfm_rt.asgn_val_op(pfm_rt.dot_acc(pfm_rt.dot_acc(" + L"pfm_rt.dot_acc(border, \"border\", \"fill\", 0, 0), \"\", " + L"\"color\", 0, 0), \"\", \"value\", 0, 0), \"20,170,13\");\n" + L"}\n" + L"}\n" + L"pfm_ret = this;\n" + L"return pfm_rt.get_val(pfm_ret);\n" + L"}\n).call(this);\n"; + + auto parser = pdfium::MakeUnique(input); + std::unique_ptr ast = parser->Parse(); + ASSERT(ast != nullptr); + EXPECT_FALSE(parser->HasError()); + + CFX_WideTextBuf buf; + EXPECT_TRUE(ast->ToJavaScript(buf)); + EXPECT_EQ(ret, buf.AsStringC()); +} -- cgit v1.2.3