// 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/xfa_fmparse.h"
|
|
#include <memory>
|
|
CXFA_FMParse::CXFA_FMParse() : m_pToken(nullptr), m_pErrorInfo(0) {}
|
|
CXFA_FMParse::~CXFA_FMParse() {}
|
|
int32_t CXFA_FMParse::Init(const CFX_WideStringC& wsFormcalc,
|
CXFA_FMErrorInfo* pErrorInfo) {
|
m_pErrorInfo = pErrorInfo;
|
m_lexer.reset(new CXFA_FMLexer(wsFormcalc, m_pErrorInfo));
|
return 0;
|
}
|
|
void CXFA_FMParse::NextToken() {
|
m_pToken = m_lexer->NextToken();
|
while (m_pToken->m_type == TOKreserver) {
|
if (m_lexer->HasError()) {
|
break;
|
}
|
m_pToken = m_lexer->NextToken();
|
}
|
}
|
|
void CXFA_FMParse::Check(XFA_FM_TOKEN op) {
|
if (m_pToken->m_type != op) {
|
CFX_WideString ws_TempString(m_pToken->m_wstring);
|
Error(m_pToken->m_uLinenum, kFMErrExpectedToken, XFA_FM_KeywordToString(op),
|
ws_TempString.c_str());
|
}
|
NextToken();
|
}
|
|
void CXFA_FMParse::Error(uint32_t lineNum, const FX_WCHAR* msg, ...) {
|
m_pErrorInfo->linenum = lineNum;
|
va_list ap;
|
va_start(ap, msg);
|
m_pErrorInfo->message.FormatV(msg, ap);
|
va_end(ap);
|
}
|
|
CFX_ArrayTemplate<CXFA_FMExpression*>* CXFA_FMParse::ParseTopExpression() {
|
std::unique_ptr<CXFA_FMExpression> e;
|
CFX_ArrayTemplate<CXFA_FMExpression*>* expression =
|
new CFX_ArrayTemplate<CXFA_FMExpression*>();
|
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 expression;
|
}
|
|
if (m_pToken->m_type == TOKfunc) {
|
e.reset(ParseFunction());
|
if (e) {
|
expression->Add(e.release());
|
} else {
|
break;
|
}
|
} else {
|
e.reset(ParseExpression());
|
if (e) {
|
expression->Add(e.release());
|
} else {
|
break;
|
}
|
}
|
}
|
return expression;
|
}
|
|
CXFA_FMExpression* CXFA_FMParse::ParseFunction() {
|
std::unique_ptr<CXFA_FMExpression> e;
|
CFX_WideStringC ident;
|
std::unique_ptr<CFX_WideStringCArray> pArguments;
|
std::unique_ptr<CFX_ArrayTemplate<CXFA_FMExpression*>> pExpressions;
|
uint32_t line = m_pToken->m_uLinenum;
|
NextToken();
|
if (m_pToken->m_type != TOKidentifier) {
|
CFX_WideString ws_TempString(m_pToken->m_wstring);
|
Error(m_pToken->m_uLinenum, kFMErrExpectedIdentifier,
|
ws_TempString.c_str());
|
} else {
|
ident = m_pToken->m_wstring;
|
NextToken();
|
}
|
Check(TOKlparen);
|
if (m_pToken->m_type == TOKrparen) {
|
NextToken();
|
} else {
|
pArguments.reset(new CFX_WideStringCArray());
|
CFX_WideStringC p;
|
while (1) {
|
if (m_pToken->m_type == TOKidentifier) {
|
p = m_pToken->m_wstring;
|
pArguments->Add(p);
|
NextToken();
|
if (m_pToken->m_type == TOKcomma) {
|
NextToken();
|
continue;
|
} else if (m_pToken->m_type == TOKrparen) {
|
NextToken();
|
break;
|
} else {
|
Check(TOKrparen);
|
break;
|
}
|
} else {
|
CFX_WideString ws_TempString(m_pToken->m_wstring);
|
Error(m_pToken->m_uLinenum, kFMErrExpectedIdentifier,
|
ws_TempString.c_str());
|
NextToken();
|
break;
|
}
|
}
|
}
|
Check(TOKdo);
|
if (m_pToken->m_type == TOKendfunc) {
|
NextToken();
|
} else {
|
pExpressions.reset(ParseTopExpression());
|
Check(TOKendfunc);
|
}
|
if (m_pErrorInfo->message.IsEmpty()) {
|
e.reset(new CXFA_FMFunctionDefinition(line, 0, ident, pArguments.release(),
|
pExpressions.release()));
|
} else {
|
if (pArguments)
|
pArguments->RemoveAll();
|
if (pExpressions) {
|
for (int i = 0; i < pExpressions->GetSize(); ++i)
|
delete pExpressions->GetAt(i);
|
}
|
}
|
return e.release();
|
}
|
|
CXFA_FMExpression* CXFA_FMParse::ParseExpression() {
|
std::unique_ptr<CXFA_FMExpression> e;
|
uint32_t line = m_pToken->m_uLinenum;
|
switch (m_pToken->m_type) {
|
case TOKvar:
|
e.reset(ParseVarExpression());
|
break;
|
case TOKnull:
|
case TOKnumber:
|
case TOKstring:
|
case TOKplus:
|
case TOKminus:
|
case TOKksnot:
|
case TOKidentifier:
|
case TOKlparen:
|
e.reset(ParseExpExpression());
|
break;
|
case TOKif:
|
e.reset(ParseIfExpression());
|
break;
|
case TOKwhile:
|
e.reset(ParseWhileExpression());
|
break;
|
case TOKfor:
|
e.reset(ParseForExpression());
|
break;
|
case TOKforeach:
|
e.reset(ParseForeachExpression());
|
break;
|
case TOKdo:
|
e.reset(ParseDoExpression());
|
break;
|
case TOKbreak:
|
e.reset(new CXFA_FMBreakExpression(line));
|
NextToken();
|
break;
|
case TOKcontinue:
|
e.reset(new CXFA_FMContinueExpression(line));
|
NextToken();
|
break;
|
default:
|
CFX_WideString ws_TempString(m_pToken->m_wstring);
|
Error(m_pToken->m_uLinenum, kFMErrUnexpectedExpression,
|
ws_TempString.c_str());
|
NextToken();
|
break;
|
}
|
return e.release();
|
}
|
|
CXFA_FMExpression* CXFA_FMParse::ParseVarExpression() {
|
std::unique_ptr<CXFA_FMExpression> e;
|
CFX_WideStringC ident;
|
uint32_t line = m_pToken->m_uLinenum;
|
NextToken();
|
if (m_pToken->m_type != TOKidentifier) {
|
CFX_WideString ws_TempString(m_pToken->m_wstring);
|
Error(m_pToken->m_uLinenum, kFMErrExpectedIdentifier,
|
ws_TempString.c_str());
|
} else {
|
ident = m_pToken->m_wstring;
|
NextToken();
|
}
|
if (m_pToken->m_type == TOKassign) {
|
NextToken();
|
e.reset(ParseExpExpression());
|
}
|
if (m_pErrorInfo->message.IsEmpty()) {
|
e.reset(new CXFA_FMVarExpression(line, ident, e.release()));
|
} else {
|
e.reset();
|
}
|
return e.release();
|
}
|
|
CXFA_FMSimpleExpression* CXFA_FMParse::ParseSimpleExpression() {
|
uint32_t line = m_pToken->m_uLinenum;
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp1(ParseLogicalOrExpression());
|
while (m_pToken->m_type == TOKassign) {
|
NextToken();
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp2(ParseLogicalOrExpression());
|
if (m_pErrorInfo->message.IsEmpty()) {
|
pExp1.reset(new CXFA_FMAssignExpression(line, TOKassign, pExp1.release(),
|
pExp2.release()));
|
} else {
|
pExp1.reset();
|
}
|
}
|
return pExp1.release();
|
}
|
|
CXFA_FMExpression* CXFA_FMParse::ParseExpExpression() {
|
uint32_t line = m_pToken->m_uLinenum;
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp1(ParseSimpleExpression());
|
std::unique_ptr<CXFA_FMExpression> e;
|
if (m_pErrorInfo->message.IsEmpty()) {
|
e.reset(new CXFA_FMExpExpression(line, pExp1.release()));
|
} else {
|
e.reset();
|
}
|
return e.release();
|
}
|
|
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 (m_pErrorInfo->message.IsEmpty()) {
|
e1.reset(new CXFA_FMLogicalOrExpression(line, TOKor, e1.release(),
|
e2.release()));
|
} else {
|
e1.reset();
|
}
|
continue;
|
}
|
default:
|
break;
|
}
|
break;
|
}
|
return e1.release();
|
}
|
|
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 (m_pErrorInfo->message.IsEmpty()) {
|
e1.reset(new CXFA_FMLogicalAndExpression(line, TOKand, e1.release(),
|
e2.release()));
|
} else {
|
e1.reset();
|
}
|
continue;
|
}
|
default:
|
break;
|
}
|
break;
|
}
|
return e1.release();
|
}
|
|
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.reset(ParseRelationalExpression());
|
if (m_pErrorInfo->message.IsEmpty()) {
|
e1.reset(new CXFA_FMEqualityExpression(line, TOKeq, e1.release(),
|
e2.release()));
|
} else {
|
e1.reset();
|
}
|
continue;
|
case TOKne:
|
case TOKksne:
|
NextToken();
|
e2.reset(ParseRelationalExpression());
|
if (m_pErrorInfo->message.IsEmpty()) {
|
e1.reset(new CXFA_FMEqualityExpression(line, TOKne, e1.release(),
|
e2.release()));
|
} else {
|
e1.reset();
|
}
|
continue;
|
default:
|
break;
|
}
|
break;
|
}
|
return e1.release();
|
}
|
|
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.reset(ParseAddtiveExpression());
|
if (m_pErrorInfo->message.IsEmpty()) {
|
e1.reset(new CXFA_FMRelationalExpression(line, TOKlt, e1.release(),
|
e2.release()));
|
} else {
|
e1.reset();
|
}
|
continue;
|
case TOKgt:
|
case TOKksgt:
|
NextToken();
|
e2.reset(ParseAddtiveExpression());
|
if (m_pErrorInfo->message.IsEmpty()) {
|
e1.reset(new CXFA_FMRelationalExpression(line, TOKgt, e1.release(),
|
e2.release()));
|
} else {
|
e1.reset();
|
}
|
continue;
|
case TOKle:
|
case TOKksle:
|
NextToken();
|
e2.reset(ParseAddtiveExpression());
|
if (m_pErrorInfo->message.IsEmpty()) {
|
e1.reset(new CXFA_FMRelationalExpression(line, TOKle, e1.release(),
|
e2.release()));
|
} else {
|
e1.reset();
|
}
|
continue;
|
case TOKge:
|
case TOKksge:
|
NextToken();
|
e2.reset(ParseAddtiveExpression());
|
if (m_pErrorInfo->message.IsEmpty()) {
|
e1.reset(new CXFA_FMRelationalExpression(line, TOKge, e1.release(),
|
e2.release()));
|
} else {
|
e1.reset();
|
}
|
continue;
|
default:
|
break;
|
}
|
break;
|
}
|
return e1.release();
|
}
|
|
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.reset(ParseMultiplicativeExpression());
|
if (m_pErrorInfo->message.IsEmpty()) {
|
e1.reset(new CXFA_FMAdditiveExpression(line, TOKplus, e1.release(),
|
e2.release()));
|
} else {
|
e1.reset();
|
}
|
continue;
|
case TOKminus:
|
NextToken();
|
e2.reset(ParseMultiplicativeExpression());
|
if (m_pErrorInfo->message.IsEmpty()) {
|
e1.reset(new CXFA_FMAdditiveExpression(line, TOKminus, e1.release(),
|
e2.release()));
|
} else {
|
e1.reset();
|
}
|
continue;
|
default:
|
break;
|
}
|
break;
|
}
|
return e1.release();
|
}
|
|
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.reset(ParseUnaryExpression());
|
if (m_pErrorInfo->message.IsEmpty()) {
|
e1.reset(new CXFA_FMMultiplicativeExpression(
|
line, TOKmul, e1.release(), e2.release()));
|
} else {
|
e1.reset();
|
}
|
continue;
|
case TOKdiv:
|
NextToken();
|
e2.reset(ParseUnaryExpression());
|
if (m_pErrorInfo->message.IsEmpty()) {
|
e1.reset(new CXFA_FMMultiplicativeExpression(
|
line, TOKdiv, e1.release(), e2.release()));
|
} else {
|
e1.reset();
|
}
|
continue;
|
default:
|
break;
|
}
|
break;
|
}
|
return e1.release();
|
}
|
|
CXFA_FMSimpleExpression* CXFA_FMParse::ParseUnaryExpression() {
|
std::unique_ptr<CXFA_FMSimpleExpression> e;
|
uint32_t line = m_pToken->m_uLinenum;
|
switch (m_pToken->m_type) {
|
case TOKplus:
|
NextToken();
|
e.reset(ParseUnaryExpression());
|
if (m_pErrorInfo->message.IsEmpty()) {
|
e.reset(new CXFA_FMPosExpression(line, e.release()));
|
} else {
|
e.reset();
|
}
|
break;
|
case TOKminus:
|
NextToken();
|
e.reset(ParseUnaryExpression());
|
if (m_pErrorInfo->message.IsEmpty()) {
|
e.reset(new CXFA_FMNegExpression(line, e.release()));
|
} else {
|
e.reset();
|
}
|
break;
|
case TOKksnot:
|
NextToken();
|
e.reset(ParseUnaryExpression());
|
if (m_pErrorInfo->message.IsEmpty()) {
|
e.reset(new CXFA_FMNotExpression(line, e.release()));
|
} else {
|
e.reset();
|
}
|
break;
|
default:
|
e.reset(ParsePrimaryExpression());
|
break;
|
}
|
return e.release();
|
}
|
|
CXFA_FMSimpleExpression* CXFA_FMParse::ParsePrimaryExpression() {
|
std::unique_ptr<CXFA_FMSimpleExpression> e;
|
uint32_t line = m_pToken->m_uLinenum;
|
switch (m_pToken->m_type) {
|
case TOKnumber:
|
e.reset(new CXFA_FMNumberExpression(line, m_pToken->m_wstring));
|
NextToken();
|
break;
|
case TOKstring:
|
e.reset(new 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) {
|
CXFA_FMSimpleExpression* s = ParseIndexExpression();
|
if (s) {
|
e.reset(new CXFA_FMDotAccessorExpression(line, nullptr, TOKdot,
|
wsIdentifier, s));
|
}
|
NextToken();
|
} else {
|
e.reset(new CXFA_FMIdentifierExpressionn(line, wsIdentifier));
|
}
|
} break;
|
case TOKif:
|
e.reset(new CXFA_FMIdentifierExpressionn(line, m_pToken->m_wstring));
|
NextToken();
|
break;
|
case TOKnull:
|
e.reset(new CXFA_FMNullExpression(line));
|
NextToken();
|
break;
|
case TOKlparen:
|
e.reset(ParseParenExpression());
|
break;
|
default:
|
CFX_WideString ws_TempString(m_pToken->m_wstring);
|
Error(m_pToken->m_uLinenum, kFMErrUnexpectedExpression,
|
ws_TempString.c_str());
|
NextToken();
|
break;
|
}
|
e.reset(ParsePostExpression(e.release()));
|
if (!(m_pErrorInfo->message.IsEmpty()))
|
e.reset();
|
return e.release();
|
}
|
|
CXFA_FMSimpleExpression* CXFA_FMParse::ParsePostExpression(
|
CXFA_FMSimpleExpression* e) {
|
uint32_t line = m_pToken->m_uLinenum;
|
while (1) {
|
switch (m_pToken->m_type) {
|
case TOKlparen: {
|
NextToken();
|
std::unique_ptr<CFX_ArrayTemplate<CXFA_FMSimpleExpression*>> pArray;
|
if (m_pToken->m_type != TOKrparen) {
|
pArray.reset(new CFX_ArrayTemplate<CXFA_FMSimpleExpression*>());
|
while (m_pToken->m_type != TOKrparen) {
|
if (CXFA_FMSimpleExpression* expr = ParseSimpleExpression())
|
pArray->Add(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) {
|
CFX_WideString ws_TempString(m_pToken->m_wstring);
|
Error(m_pToken->m_uLinenum, kFMErrExpectedToken,
|
XFA_FM_KeywordToString(TOKrparen), ws_TempString.c_str());
|
}
|
}
|
if (m_pErrorInfo->message.IsEmpty()) {
|
e = new CXFA_FMCallExpression(line, e, pArray.release(), FALSE);
|
NextToken();
|
if (m_pToken->m_type != TOKlbracket) {
|
continue;
|
}
|
CXFA_FMSimpleExpression* s = ParseIndexExpression();
|
if (s) {
|
e = new CXFA_FMDotAccessorExpression(line, e, TOKcall,
|
FX_WSTRC(L""), s);
|
} else {
|
delete e;
|
e = nullptr;
|
}
|
} else {
|
if (pArray) {
|
for (int32_t i = 0; i < pArray->GetSize(); ++i)
|
delete pArray->GetAt(i);
|
}
|
delete e;
|
e = nullptr;
|
}
|
} 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) {
|
CXFA_FMSimpleExpression* pExpAccessor;
|
CXFA_FMSimpleExpression* pExpCall;
|
pExpAccessor = e;
|
NextToken();
|
std::unique_ptr<CFX_ArrayTemplate<CXFA_FMSimpleExpression*>> pArray;
|
if (m_pToken->m_type != TOKrparen) {
|
pArray.reset(new CFX_ArrayTemplate<CXFA_FMSimpleExpression*>());
|
while (m_pToken->m_type != TOKrparen) {
|
CXFA_FMSimpleExpression* exp = ParseSimpleExpression();
|
pArray->Add(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) {
|
CFX_WideString ws_TempString(m_pToken->m_wstring);
|
Error(m_pToken->m_uLinenum, kFMErrExpectedToken,
|
XFA_FM_KeywordToString(TOKrparen), ws_TempString.c_str());
|
}
|
}
|
if (m_pErrorInfo->message.IsEmpty()) {
|
CXFA_FMSimpleExpression* pIdentifier =
|
new CXFA_FMIdentifierExpressionn(tempLine, tempStr);
|
pExpCall = new CXFA_FMCallExpression(line, pIdentifier,
|
pArray.release(), TRUE);
|
e = new CXFA_FMMethodCallExpression(line, pExpAccessor, pExpCall);
|
NextToken();
|
if (m_pToken->m_type != TOKlbracket) {
|
continue;
|
}
|
CXFA_FMSimpleExpression* s = ParseIndexExpression();
|
if (s) {
|
e = new CXFA_FMDotAccessorExpression(line, e, TOKcall,
|
FX_WSTRC(L""), s);
|
} else {
|
delete e;
|
e = nullptr;
|
}
|
} else {
|
if (pArray) {
|
for (int32_t i = 0; i < pArray->GetSize(); ++i)
|
delete pArray->GetAt(i);
|
}
|
delete e;
|
e = nullptr;
|
}
|
} else if (m_pToken->m_type == TOKlbracket) {
|
std::unique_ptr<CXFA_FMSimpleExpression> s(ParseIndexExpression());
|
if (!(m_pErrorInfo->message.IsEmpty())) {
|
delete e;
|
return nullptr;
|
}
|
e = new CXFA_FMDotAccessorExpression(tempLine, e, TOKdot, tempStr,
|
s.release());
|
} else {
|
CXFA_FMSimpleExpression* s = new CXFA_FMIndexExpression(
|
tempLine, ACCESSOR_NO_INDEX, nullptr, FALSE);
|
e = new CXFA_FMDotAccessorExpression(line, e, TOKdot, tempStr, s);
|
continue;
|
}
|
} else {
|
CFX_WideString ws_TempString(m_pToken->m_wstring);
|
Error(m_pToken->m_uLinenum, kFMErrExpectedIdentifier,
|
ws_TempString.c_str());
|
return e;
|
}
|
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 (!(m_pErrorInfo->message.IsEmpty())) {
|
delete e;
|
return nullptr;
|
}
|
e = new CXFA_FMDotDotAccessorExpression(tempLine, e, TOKdotdot,
|
tempStr, s.release());
|
} else {
|
CXFA_FMSimpleExpression* s = new CXFA_FMIndexExpression(
|
tempLine, ACCESSOR_NO_INDEX, nullptr, FALSE);
|
e = new CXFA_FMDotDotAccessorExpression(line, e, TOKdotdot, tempStr,
|
s);
|
continue;
|
}
|
} else {
|
CFX_WideString ws_TempString(m_pToken->m_wstring);
|
Error(m_pToken->m_uLinenum, kFMErrExpectedIdentifier,
|
ws_TempString.c_str());
|
return e;
|
}
|
break;
|
case TOKdotscream:
|
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 (!(m_pErrorInfo->message.IsEmpty())) {
|
delete e;
|
return nullptr;
|
}
|
e = new CXFA_FMDotAccessorExpression(tempLine, e, TOKdotscream,
|
tempStr, s.release());
|
} else {
|
CXFA_FMSimpleExpression* s = new CXFA_FMIndexExpression(
|
tempLine, ACCESSOR_NO_INDEX, nullptr, FALSE);
|
e = new CXFA_FMDotAccessorExpression(line, e, TOKdotscream, tempStr,
|
s);
|
continue;
|
}
|
} else {
|
CFX_WideString ws_TempString(m_pToken->m_wstring);
|
Error(m_pToken->m_uLinenum, kFMErrExpectedIdentifier,
|
ws_TempString.c_str());
|
return e;
|
}
|
break;
|
case TOKdotstar: {
|
CXFA_FMSimpleExpression* s =
|
new CXFA_FMIndexExpression(line, ACCESSOR_NO_INDEX, nullptr, FALSE);
|
e = new CXFA_FMDotAccessorExpression(line, e, TOKdotstar,
|
FX_WSTRC(L"*"), s);
|
} break;
|
default:
|
return e;
|
}
|
NextToken();
|
}
|
return e;
|
}
|
|
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.reset(
|
new CXFA_FMIndexExpression(line, accessorIndex, s.release(), TRUE));
|
NextToken();
|
if (m_pToken->m_type != TOKrbracket) {
|
CFX_WideString ws_TempString(m_pToken->m_wstring);
|
Error(m_pToken->m_uLinenum, kFMErrExpectedToken,
|
XFA_FM_KeywordToString(TOKrparen), ws_TempString.c_str());
|
pExp.reset();
|
}
|
return pExp.release();
|
}
|
if (m_pToken->m_type == TOKplus) {
|
accessorIndex = ACCESSOR_POSITIVE_INDEX;
|
NextToken();
|
} else if (m_pToken->m_type == TOKminus) {
|
accessorIndex = ACCESSOR_NEGATIVE_INDEX;
|
NextToken();
|
}
|
s.reset(ParseSimpleExpression());
|
if (m_pToken->m_type != TOKrbracket) {
|
CFX_WideString ws_TempString(m_pToken->m_wstring);
|
Error(m_pToken->m_uLinenum, kFMErrExpectedToken,
|
XFA_FM_KeywordToString(TOKrparen), ws_TempString.c_str());
|
} else {
|
pExp.reset(
|
new CXFA_FMIndexExpression(line, accessorIndex, s.release(), FALSE));
|
}
|
return pExp.release();
|
}
|
|
CXFA_FMSimpleExpression* CXFA_FMParse::ParseParenExpression() {
|
Check(TOKlparen);
|
|
if (m_pToken->m_type == TOKrparen) {
|
Error(m_pToken->m_uLinenum, kFMErrExpectedNonEmptyExpression);
|
NextToken();
|
return nullptr;
|
}
|
|
uint32_t line = m_pToken->m_uLinenum;
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp1(ParseLogicalOrExpression());
|
|
while (m_pToken->m_type == TOKassign) {
|
NextToken();
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp2(ParseLogicalOrExpression());
|
if (m_pErrorInfo->message.IsEmpty()) {
|
pExp1.reset(new CXFA_FMAssignExpression(line, TOKassign, pExp1.release(),
|
pExp2.release()));
|
} else {
|
pExp1.reset();
|
}
|
}
|
Check(TOKrparen);
|
return pExp1.release();
|
}
|
|
CXFA_FMExpression* CXFA_FMParse::ParseBlockExpression() {
|
uint32_t line = m_pToken->m_uLinenum;
|
CXFA_FMExpression* e = nullptr;
|
std::unique_ptr<CFX_ArrayTemplate<CXFA_FMExpression*>> expression(
|
new CFX_ArrayTemplate<CXFA_FMExpression*>());
|
|
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:
|
e = ParseFunction();
|
if (e) {
|
expression->Add(e);
|
}
|
continue;
|
default:
|
e = ParseExpression();
|
if (e) {
|
expression->Add(e);
|
}
|
continue;
|
}
|
break;
|
}
|
std::unique_ptr<CXFA_FMBlockExpression> pExp;
|
if (m_pErrorInfo->message.IsEmpty()) {
|
pExp.reset(new CXFA_FMBlockExpression(line, expression.release()));
|
} else {
|
for (int i = 0; i < expression->GetSize(); ++i)
|
delete static_cast<CXFA_FMExpression*>(expression->GetAt(i));
|
}
|
return pExp.release();
|
}
|
|
CXFA_FMExpression* CXFA_FMParse::ParseIfExpression() {
|
uint32_t line = m_pToken->m_uLinenum;
|
const FX_WCHAR* pStartPos = m_lexer->SavePos();
|
NextToken();
|
Check(TOKlparen);
|
std::unique_ptr<CXFA_FMSimpleExpression> pExpression;
|
while (m_pToken->m_type != TOKrparen) {
|
pExpression.reset(ParseSimpleExpression());
|
if (m_pToken->m_type != TOKcomma)
|
break;
|
NextToken();
|
}
|
Check(TOKrparen);
|
if (m_pToken->m_type != TOKthen) {
|
m_lexer->SetCurrentLine(line);
|
m_pToken = new CXFA_FMToken(line);
|
m_pToken->m_type = TOKidentifier;
|
m_pToken->m_wstring = FX_WSTRC(L"if");
|
m_lexer->SetToken(m_pToken);
|
m_lexer->RestorePos(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.reset(ParseIfExpression());
|
Check(TOKendif);
|
break;
|
case TOKelseif:
|
pElseExpression.reset(ParseIfExpression());
|
break;
|
case TOKelse:
|
NextToken();
|
pElseExpression.reset(ParseBlockExpression());
|
Check(TOKendif);
|
break;
|
default:
|
CFX_WideString ws_TempString(m_pToken->m_wstring);
|
Error(m_pToken->m_uLinenum, kFMErrExpectedEndIf, ws_TempString.c_str());
|
NextToken();
|
break;
|
}
|
std::unique_ptr<CXFA_FMIfExpression> pExp;
|
if (m_pErrorInfo->message.IsEmpty()) {
|
pExp.reset(new CXFA_FMIfExpression(line, pExpression.release(),
|
pIfExpression.release(),
|
pElseExpression.release()));
|
}
|
return pExp.release();
|
}
|
|
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> e;
|
if (m_pErrorInfo->message.IsEmpty()) {
|
e.reset(new CXFA_FMWhileExpression(line, pCondition.release(),
|
pExpression.release()));
|
}
|
return e.release();
|
}
|
|
CXFA_FMSimpleExpression* CXFA_FMParse::ParseSubassignmentInForExpression() {
|
std::unique_ptr<CXFA_FMSimpleExpression> e;
|
switch (m_pToken->m_type) {
|
case TOKidentifier:
|
e.reset(ParseSimpleExpression());
|
break;
|
default:
|
CFX_WideString ws_TempString(m_pToken->m_wstring);
|
Error(m_pToken->m_uLinenum, kFMErrUnexpectedExpression,
|
ws_TempString.c_str());
|
NextToken();
|
break;
|
}
|
return e.release();
|
}
|
|
CXFA_FMExpression* CXFA_FMParse::ParseForExpression() {
|
CFX_WideStringC wsVariant;
|
uint32_t line = m_pToken->m_uLinenum;
|
NextToken();
|
if (m_pToken->m_type != TOKidentifier) {
|
CFX_WideString ws_TempString(m_pToken->m_wstring);
|
Error(m_pToken->m_uLinenum, kFMErrExpectedToken,
|
XFA_FM_KeywordToString(m_pToken->m_type), ws_TempString.c_str());
|
}
|
wsVariant = m_pToken->m_wstring;
|
NextToken();
|
std::unique_ptr<CXFA_FMSimpleExpression> pAssignment;
|
if (m_pToken->m_type == TOKassign) {
|
NextToken();
|
pAssignment.reset(ParseSimpleExpression());
|
} else {
|
CFX_WideString ws_TempString(m_pToken->m_wstring);
|
Error(m_pToken->m_uLinenum, kFMErrExpectedToken,
|
XFA_FM_KeywordToString(m_pToken->m_type), ws_TempString.c_str());
|
}
|
int32_t iDirection = 0;
|
if (m_pToken->m_type == TOKupto) {
|
iDirection = 1;
|
} else if (m_pToken->m_type == TOKdownto) {
|
iDirection = -1;
|
} else {
|
CFX_WideString ws_TempString(m_pToken->m_wstring);
|
Error(m_pToken->m_uLinenum, kFMErrExpectedToken, L"upto or downto",
|
ws_TempString.c_str());
|
}
|
NextToken();
|
std::unique_ptr<CXFA_FMSimpleExpression> pAccessor(ParseSimpleExpression());
|
std::unique_ptr<CXFA_FMSimpleExpression> pStep;
|
if (m_pToken->m_type == TOKstep) {
|
NextToken();
|
pStep.reset(ParseSimpleExpression());
|
}
|
Check(TOKdo);
|
std::unique_ptr<CXFA_FMExpression> pList(ParseBlockExpression());
|
Check(TOKendfor);
|
std::unique_ptr<CXFA_FMExpression> e;
|
if (m_pErrorInfo->message.IsEmpty()) {
|
e.reset(new CXFA_FMForExpression(line, wsVariant, pAssignment.release(),
|
pAccessor.release(), iDirection,
|
pStep.release(), pList.release()));
|
}
|
return e.release();
|
}
|
|
CXFA_FMExpression* CXFA_FMParse::ParseForeachExpression() {
|
std::unique_ptr<CXFA_FMExpression> e;
|
CFX_WideStringC wsIdentifier;
|
std::unique_ptr<CFX_ArrayTemplate<CXFA_FMSimpleExpression*>> pAccessors;
|
std::unique_ptr<CXFA_FMExpression> pList;
|
uint32_t line = m_pToken->m_uLinenum;
|
NextToken();
|
if (m_pToken->m_type != TOKidentifier) {
|
CFX_WideString ws_TempString(m_pToken->m_wstring);
|
Error(m_pToken->m_uLinenum, kFMErrExpectedToken,
|
XFA_FM_KeywordToString(m_pToken->m_type), ws_TempString.c_str());
|
}
|
wsIdentifier = m_pToken->m_wstring;
|
NextToken();
|
Check(TOKin);
|
Check(TOKlparen);
|
if (m_pToken->m_type == TOKrparen) {
|
CFX_WideString ws_TempString(m_pToken->m_wstring);
|
Error(m_pToken->m_uLinenum, kFMErrUnexpectedExpression,
|
ws_TempString.c_str());
|
NextToken();
|
} else {
|
pAccessors.reset(new CFX_ArrayTemplate<CXFA_FMSimpleExpression*>());
|
while (m_pToken->m_type != TOKrparen) {
|
CXFA_FMSimpleExpression* s = ParseSimpleExpression();
|
if (s) {
|
pAccessors->Add(s);
|
}
|
if (m_pToken->m_type == TOKcomma) {
|
NextToken();
|
} else {
|
break;
|
}
|
}
|
Check(TOKrparen);
|
}
|
Check(TOKdo);
|
pList.reset(ParseBlockExpression());
|
Check(TOKendfor);
|
if (m_pErrorInfo->message.IsEmpty()) {
|
e.reset(new CXFA_FMForeachExpression(
|
line, wsIdentifier, pAccessors.release(), pList.release()));
|
} else {
|
if (pAccessors) {
|
for (int i = 0; i < pAccessors->GetSize(); ++i)
|
delete static_cast<CXFA_FMSimpleExpression*>(pAccessors->GetAt(i));
|
}
|
}
|
return e.release();
|
}
|
|
CXFA_FMExpression* CXFA_FMParse::ParseDoExpression() {
|
std::unique_ptr<CXFA_FMExpression> e;
|
uint32_t line = m_pToken->m_uLinenum;
|
NextToken();
|
e.reset(ParseBlockExpression());
|
Check(TOKend);
|
if (m_pErrorInfo->message.IsEmpty()) {
|
e.reset(new CXFA_FMDoExpression(line, e.release()));
|
} else {
|
e.reset();
|
}
|
return e.release();
|
}
|