1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "xfa/fxfa/fm2js/xfa_fmparse.h"
8
9 #include <memory>
10 #include <utility>
11 #include <vector>
12
13 #include "third_party/base/ptr_util.h"
14
CXFA_FMParse(const CFX_WideStringC & wsFormcalc,CXFA_FMErrorInfo * pErrorInfo)15 CXFA_FMParse::CXFA_FMParse(const CFX_WideStringC& wsFormcalc,
16 CXFA_FMErrorInfo* pErrorInfo)
17 : m_pToken(nullptr), m_pErrorInfo(pErrorInfo) {
18 m_lexer = pdfium::MakeUnique<CXFA_FMLexer>(wsFormcalc, m_pErrorInfo);
19 }
20
~CXFA_FMParse()21 CXFA_FMParse::~CXFA_FMParse() {}
22
NextToken()23 void CXFA_FMParse::NextToken() {
24 m_pToken = m_lexer->NextToken();
25 while (m_pToken->m_type == TOKreserver) {
26 if (m_lexer->HasError()) {
27 break;
28 }
29 m_pToken = m_lexer->NextToken();
30 }
31 }
32
Check(XFA_FM_TOKEN op)33 void CXFA_FMParse::Check(XFA_FM_TOKEN op) {
34 if (m_pToken->m_type != op) {
35 CFX_WideString ws_TempString(m_pToken->m_wstring);
36 Error(m_pToken->m_uLinenum, kFMErrExpectedToken, XFA_FM_KeywordToString(op),
37 ws_TempString.c_str());
38 }
39 NextToken();
40 }
41
Error(uint32_t lineNum,const FX_WCHAR * msg,...)42 void CXFA_FMParse::Error(uint32_t lineNum, const FX_WCHAR* msg, ...) {
43 m_pErrorInfo->linenum = lineNum;
44 va_list ap;
45 va_start(ap, msg);
46 m_pErrorInfo->message.FormatV(msg, ap);
47 va_end(ap);
48 }
49
50 std::vector<std::unique_ptr<CXFA_FMExpression>>
ParseTopExpression()51 CXFA_FMParse::ParseTopExpression() {
52 std::unique_ptr<CXFA_FMExpression> expr;
53 std::vector<std::unique_ptr<CXFA_FMExpression>> expressions;
54 while (1) {
55 if (m_pToken->m_type == TOKeof || m_pToken->m_type == TOKendfunc ||
56 m_pToken->m_type == TOKendif || m_pToken->m_type == TOKelseif ||
57 m_pToken->m_type == TOKelse || m_pToken->m_type == TOKreserver) {
58 return expressions;
59 }
60
61 if (m_pToken->m_type == TOKfunc) {
62 expr = ParseFunction();
63 if (expr) {
64 expressions.push_back(std::move(expr));
65 } else {
66 break;
67 }
68 } else {
69 expr = ParseExpression();
70 if (expr) {
71 expressions.push_back(std::move(expr));
72 } else {
73 break;
74 }
75 }
76 }
77 return expressions;
78 }
79
ParseFunction()80 std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseFunction() {
81 CFX_WideStringC ident;
82 std::vector<CFX_WideStringC> arguments;
83 std::vector<std::unique_ptr<CXFA_FMExpression>> expressions;
84 uint32_t line = m_pToken->m_uLinenum;
85 NextToken();
86 if (m_pToken->m_type != TOKidentifier) {
87 CFX_WideString ws_TempString(m_pToken->m_wstring);
88 Error(m_pToken->m_uLinenum, kFMErrExpectedIdentifier,
89 ws_TempString.c_str());
90 } else {
91 ident = m_pToken->m_wstring;
92 NextToken();
93 }
94 Check(TOKlparen);
95 if (m_pToken->m_type == TOKrparen) {
96 NextToken();
97 } else {
98 while (1) {
99 if (m_pToken->m_type == TOKidentifier) {
100 arguments.push_back(m_pToken->m_wstring);
101 NextToken();
102 if (m_pToken->m_type == TOKcomma) {
103 NextToken();
104 continue;
105 } else if (m_pToken->m_type == TOKrparen) {
106 NextToken();
107 break;
108 } else {
109 Check(TOKrparen);
110 break;
111 }
112 } else {
113 CFX_WideString ws_TempString(m_pToken->m_wstring);
114 Error(m_pToken->m_uLinenum, kFMErrExpectedIdentifier,
115 ws_TempString.c_str());
116 NextToken();
117 break;
118 }
119 }
120 }
121 Check(TOKdo);
122 if (m_pToken->m_type == TOKendfunc) {
123 NextToken();
124 } else {
125 expressions = ParseTopExpression();
126 Check(TOKendfunc);
127 }
128 if (!m_pErrorInfo->message.IsEmpty())
129 return nullptr;
130
131 return pdfium::MakeUnique<CXFA_FMFunctionDefinition>(
132 line, false, ident, std::move(arguments), std::move(expressions));
133 }
134
ParseExpression()135 std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseExpression() {
136 std::unique_ptr<CXFA_FMExpression> expr;
137 uint32_t line = m_pToken->m_uLinenum;
138 switch (m_pToken->m_type) {
139 case TOKvar:
140 expr = ParseVarExpression();
141 break;
142 case TOKnull:
143 case TOKnumber:
144 case TOKstring:
145 case TOKplus:
146 case TOKminus:
147 case TOKksnot:
148 case TOKidentifier:
149 case TOKlparen:
150 expr = ParseExpExpression();
151 break;
152 case TOKif:
153 expr = ParseIfExpression();
154 break;
155 case TOKwhile:
156 expr = ParseWhileExpression();
157 break;
158 case TOKfor:
159 expr = ParseForExpression();
160 break;
161 case TOKforeach:
162 expr = ParseForeachExpression();
163 break;
164 case TOKdo:
165 expr = ParseDoExpression();
166 break;
167 case TOKbreak:
168 expr = pdfium::MakeUnique<CXFA_FMBreakExpression>(line);
169 NextToken();
170 break;
171 case TOKcontinue:
172 expr = pdfium::MakeUnique<CXFA_FMContinueExpression>(line);
173 NextToken();
174 break;
175 default:
176 CFX_WideString ws_TempString(m_pToken->m_wstring);
177 Error(m_pToken->m_uLinenum, kFMErrUnexpectedExpression,
178 ws_TempString.c_str());
179 NextToken();
180 break;
181 }
182 return expr;
183 }
184
ParseVarExpression()185 std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseVarExpression() {
186 CFX_WideStringC ident;
187 uint32_t line = m_pToken->m_uLinenum;
188 NextToken();
189 if (m_pToken->m_type != TOKidentifier) {
190 CFX_WideString ws_TempString(m_pToken->m_wstring);
191 Error(m_pToken->m_uLinenum, kFMErrExpectedIdentifier,
192 ws_TempString.c_str());
193 } else {
194 ident = m_pToken->m_wstring;
195 NextToken();
196 }
197 std::unique_ptr<CXFA_FMExpression> expr;
198 if (m_pToken->m_type == TOKassign) {
199 NextToken();
200 expr = ParseExpExpression();
201 }
202 if (!m_pErrorInfo->message.IsEmpty())
203 return nullptr;
204
205 return pdfium::MakeUnique<CXFA_FMVarExpression>(line, ident, std::move(expr));
206 }
207
ParseSimpleExpression()208 std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParse::ParseSimpleExpression() {
209 uint32_t line = m_pToken->m_uLinenum;
210 std::unique_ptr<CXFA_FMSimpleExpression> pExp1 = ParseLogicalOrExpression();
211 while (m_pToken->m_type == TOKassign) {
212 NextToken();
213 std::unique_ptr<CXFA_FMSimpleExpression> pExp2 = ParseLogicalOrExpression();
214 if (m_pErrorInfo->message.IsEmpty()) {
215 pExp1 = pdfium::MakeUnique<CXFA_FMAssignExpression>(
216 line, TOKassign, std::move(pExp1), std::move(pExp2));
217 } else {
218 pExp1.reset();
219 }
220 }
221 return pExp1;
222 }
223
ParseExpExpression()224 std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseExpExpression() {
225 uint32_t line = m_pToken->m_uLinenum;
226 std::unique_ptr<CXFA_FMSimpleExpression> pExp1 = ParseSimpleExpression();
227 if (!m_pErrorInfo->message.IsEmpty())
228 return nullptr;
229
230 return pdfium::MakeUnique<CXFA_FMExpExpression>(line, std::move(pExp1));
231 }
232
233 std::unique_ptr<CXFA_FMSimpleExpression>
ParseLogicalOrExpression()234 CXFA_FMParse::ParseLogicalOrExpression() {
235 uint32_t line = m_pToken->m_uLinenum;
236 std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseLogicalAndExpression();
237 for (;;) {
238 switch (m_pToken->m_type) {
239 case TOKor:
240 case TOKksor: {
241 NextToken();
242 std::unique_ptr<CXFA_FMSimpleExpression> e2(
243 ParseLogicalAndExpression());
244 if (m_pErrorInfo->message.IsEmpty()) {
245 e1 = pdfium::MakeUnique<CXFA_FMLogicalOrExpression>(
246 line, TOKor, std::move(e1), std::move(e2));
247 } else {
248 e1.reset();
249 }
250 continue;
251 }
252 default:
253 break;
254 }
255 break;
256 }
257 return e1;
258 }
259
260 std::unique_ptr<CXFA_FMSimpleExpression>
ParseLogicalAndExpression()261 CXFA_FMParse::ParseLogicalAndExpression() {
262 uint32_t line = m_pToken->m_uLinenum;
263 std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseEqualityExpression();
264 for (;;) {
265 switch (m_pToken->m_type) {
266 case TOKand:
267 case TOKksand: {
268 NextToken();
269 std::unique_ptr<CXFA_FMSimpleExpression> e2 = ParseEqualityExpression();
270 if (m_pErrorInfo->message.IsEmpty()) {
271 e1 = pdfium::MakeUnique<CXFA_FMLogicalAndExpression>(
272 line, TOKand, std::move(e1), std::move(e2));
273 } else {
274 e1.reset();
275 }
276 continue;
277 }
278 default:
279 break;
280 }
281 break;
282 }
283 return e1;
284 }
285
286 std::unique_ptr<CXFA_FMSimpleExpression>
ParseEqualityExpression()287 CXFA_FMParse::ParseEqualityExpression() {
288 uint32_t line = m_pToken->m_uLinenum;
289 std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseRelationalExpression();
290 for (;;) {
291 std::unique_ptr<CXFA_FMSimpleExpression> e2;
292 switch (m_pToken->m_type) {
293 case TOKeq:
294 case TOKkseq:
295 NextToken();
296 e2 = ParseRelationalExpression();
297 if (m_pErrorInfo->message.IsEmpty()) {
298 e1 = pdfium::MakeUnique<CXFA_FMEqualityExpression>(
299 line, TOKeq, std::move(e1), std::move(e2));
300 } else {
301 e1.reset();
302 }
303 continue;
304 case TOKne:
305 case TOKksne:
306 NextToken();
307 e2 = ParseRelationalExpression();
308 if (m_pErrorInfo->message.IsEmpty()) {
309 e1 = pdfium::MakeUnique<CXFA_FMEqualityExpression>(
310 line, TOKne, std::move(e1), std::move(e2));
311 } else {
312 e1.reset();
313 }
314 continue;
315 default:
316 break;
317 }
318 break;
319 }
320 return e1;
321 }
322
323 std::unique_ptr<CXFA_FMSimpleExpression>
ParseRelationalExpression()324 CXFA_FMParse::ParseRelationalExpression() {
325 uint32_t line = m_pToken->m_uLinenum;
326 std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseAddtiveExpression();
327 for (;;) {
328 std::unique_ptr<CXFA_FMSimpleExpression> e2;
329 switch (m_pToken->m_type) {
330 case TOKlt:
331 case TOKkslt:
332 NextToken();
333 e2 = ParseAddtiveExpression();
334 if (m_pErrorInfo->message.IsEmpty()) {
335 e1 = pdfium::MakeUnique<CXFA_FMRelationalExpression>(
336 line, TOKlt, std::move(e1), std::move(e2));
337 } else {
338 e1.reset();
339 }
340 continue;
341 case TOKgt:
342 case TOKksgt:
343 NextToken();
344 e2 = ParseAddtiveExpression();
345 if (m_pErrorInfo->message.IsEmpty()) {
346 e1 = pdfium::MakeUnique<CXFA_FMRelationalExpression>(
347 line, TOKgt, std::move(e1), std::move(e2));
348 } else {
349 e1.reset();
350 }
351 continue;
352 case TOKle:
353 case TOKksle:
354 NextToken();
355 e2 = ParseAddtiveExpression();
356 if (m_pErrorInfo->message.IsEmpty()) {
357 e1 = pdfium::MakeUnique<CXFA_FMRelationalExpression>(
358 line, TOKle, std::move(e1), std::move(e2));
359 } else {
360 e1.reset();
361 }
362 continue;
363 case TOKge:
364 case TOKksge:
365 NextToken();
366 e2 = ParseAddtiveExpression();
367 if (m_pErrorInfo->message.IsEmpty()) {
368 e1 = pdfium::MakeUnique<CXFA_FMRelationalExpression>(
369 line, TOKge, std::move(e1), std::move(e2));
370 } else {
371 e1.reset();
372 }
373 continue;
374 default:
375 break;
376 }
377 break;
378 }
379 return e1;
380 }
381
382 std::unique_ptr<CXFA_FMSimpleExpression>
ParseAddtiveExpression()383 CXFA_FMParse::ParseAddtiveExpression() {
384 uint32_t line = m_pToken->m_uLinenum;
385 std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseMultiplicativeExpression();
386 for (;;) {
387 std::unique_ptr<CXFA_FMSimpleExpression> e2;
388 switch (m_pToken->m_type) {
389 case TOKplus:
390 NextToken();
391 e2 = ParseMultiplicativeExpression();
392 if (m_pErrorInfo->message.IsEmpty()) {
393 e1 = pdfium::MakeUnique<CXFA_FMAdditiveExpression>(
394 line, TOKplus, std::move(e1), std::move(e2));
395 } else {
396 e1.reset();
397 }
398 continue;
399 case TOKminus:
400 NextToken();
401 e2 = ParseMultiplicativeExpression();
402 if (m_pErrorInfo->message.IsEmpty()) {
403 e1 = pdfium::MakeUnique<CXFA_FMAdditiveExpression>(
404 line, TOKminus, std::move(e1), std::move(e2));
405 } else {
406 e1.reset();
407 }
408 continue;
409 default:
410 break;
411 }
412 break;
413 }
414 return e1;
415 }
416
417 std::unique_ptr<CXFA_FMSimpleExpression>
ParseMultiplicativeExpression()418 CXFA_FMParse::ParseMultiplicativeExpression() {
419 uint32_t line = m_pToken->m_uLinenum;
420 std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseUnaryExpression();
421 for (;;) {
422 std::unique_ptr<CXFA_FMSimpleExpression> e2;
423 switch (m_pToken->m_type) {
424 case TOKmul:
425 NextToken();
426 e2 = ParseUnaryExpression();
427 if (m_pErrorInfo->message.IsEmpty()) {
428 e1 = pdfium::MakeUnique<CXFA_FMMultiplicativeExpression>(
429 line, TOKmul, std::move(e1), std::move(e2));
430 } else {
431 e1.reset();
432 }
433 continue;
434 case TOKdiv:
435 NextToken();
436 e2 = ParseUnaryExpression();
437 if (m_pErrorInfo->message.IsEmpty()) {
438 e1 = pdfium::MakeUnique<CXFA_FMMultiplicativeExpression>(
439 line, TOKdiv, std::move(e1), std::move(e2));
440 } else {
441 e1.reset();
442 }
443 continue;
444 default:
445 break;
446 }
447 break;
448 }
449 return e1;
450 }
451
ParseUnaryExpression()452 std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParse::ParseUnaryExpression() {
453 std::unique_ptr<CXFA_FMSimpleExpression> expr;
454 uint32_t line = m_pToken->m_uLinenum;
455 switch (m_pToken->m_type) {
456 case TOKplus:
457 NextToken();
458 expr = ParseUnaryExpression();
459 if (m_pErrorInfo->message.IsEmpty())
460 expr = pdfium::MakeUnique<CXFA_FMPosExpression>(line, std::move(expr));
461 else
462 expr.reset();
463 break;
464 case TOKminus:
465 NextToken();
466 expr = ParseUnaryExpression();
467 if (m_pErrorInfo->message.IsEmpty())
468 expr = pdfium::MakeUnique<CXFA_FMNegExpression>(line, std::move(expr));
469 else
470 expr.reset();
471 break;
472 case TOKksnot:
473 NextToken();
474 expr = ParseUnaryExpression();
475 if (m_pErrorInfo->message.IsEmpty())
476 expr = pdfium::MakeUnique<CXFA_FMNotExpression>(line, std::move(expr));
477 else
478 expr.reset();
479 break;
480 default:
481 expr = ParsePrimaryExpression();
482 break;
483 }
484 return expr;
485 }
486
487 std::unique_ptr<CXFA_FMSimpleExpression>
ParsePrimaryExpression()488 CXFA_FMParse::ParsePrimaryExpression() {
489 std::unique_ptr<CXFA_FMSimpleExpression> expr;
490 uint32_t line = m_pToken->m_uLinenum;
491 switch (m_pToken->m_type) {
492 case TOKnumber:
493 expr = pdfium::MakeUnique<CXFA_FMNumberExpression>(line,
494 m_pToken->m_wstring);
495 NextToken();
496 break;
497 case TOKstring:
498 expr = pdfium::MakeUnique<CXFA_FMStringExpression>(line,
499 m_pToken->m_wstring);
500 NextToken();
501 break;
502 case TOKidentifier: {
503 CFX_WideStringC wsIdentifier(m_pToken->m_wstring);
504 NextToken();
505 if (m_pToken->m_type == TOKlbracket) {
506 std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression();
507 if (s) {
508 expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
509 line, nullptr, TOKdot, wsIdentifier, std::move(s));
510 }
511 NextToken();
512 } else {
513 expr =
514 pdfium::MakeUnique<CXFA_FMIdentifierExpression>(line, wsIdentifier);
515 }
516 } break;
517 case TOKif:
518 expr = pdfium::MakeUnique<CXFA_FMIdentifierExpression>(
519 line, m_pToken->m_wstring);
520 NextToken();
521 break;
522 case TOKnull:
523 expr = pdfium::MakeUnique<CXFA_FMNullExpression>(line);
524 NextToken();
525 break;
526 case TOKlparen:
527 expr = ParseParenExpression();
528 break;
529 default:
530 CFX_WideString ws_TempString(m_pToken->m_wstring);
531 Error(m_pToken->m_uLinenum, kFMErrUnexpectedExpression,
532 ws_TempString.c_str());
533 NextToken();
534 break;
535 }
536 expr = ParsePostExpression(std::move(expr));
537 if (!m_pErrorInfo->message.IsEmpty())
538 expr.reset();
539 return expr;
540 }
541
ParsePostExpression(std::unique_ptr<CXFA_FMSimpleExpression> expr)542 std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParse::ParsePostExpression(
543 std::unique_ptr<CXFA_FMSimpleExpression> expr) {
544 uint32_t line = m_pToken->m_uLinenum;
545 while (1) {
546 switch (m_pToken->m_type) {
547 case TOKlparen: {
548 NextToken();
549 std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> expressions;
550 if (m_pToken->m_type != TOKrparen) {
551 while (m_pToken->m_type != TOKrparen) {
552 if (std::unique_ptr<CXFA_FMSimpleExpression> expr =
553 ParseSimpleExpression())
554 expressions.push_back(std::move(expr));
555 if (m_pToken->m_type == TOKcomma) {
556 NextToken();
557 } else if (m_pToken->m_type == TOKeof ||
558 m_pToken->m_type == TOKreserver) {
559 break;
560 }
561 }
562 if (m_pToken->m_type != TOKrparen) {
563 CFX_WideString ws_TempString(m_pToken->m_wstring);
564 Error(m_pToken->m_uLinenum, kFMErrExpectedToken,
565 XFA_FM_KeywordToString(TOKrparen), ws_TempString.c_str());
566 }
567 }
568 if (m_pErrorInfo->message.IsEmpty()) {
569 expr = pdfium::MakeUnique<CXFA_FMCallExpression>(
570 line, std::move(expr), std::move(expressions), false);
571 NextToken();
572 if (m_pToken->m_type != TOKlbracket)
573 continue;
574
575 std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression();
576 if (s) {
577 expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
578 line, std::move(expr), TOKcall, L"", std::move(s));
579 } else {
580 expr.reset();
581 }
582 } else {
583 expr.reset();
584 }
585 } break;
586 case TOKdot:
587 NextToken();
588 if (m_pToken->m_type == TOKidentifier) {
589 CFX_WideStringC tempStr = m_pToken->m_wstring;
590 uint32_t tempLine = m_pToken->m_uLinenum;
591 NextToken();
592 if (m_pToken->m_type == TOKlparen) {
593 std::unique_ptr<CXFA_FMSimpleExpression> pExpCall;
594 NextToken();
595 std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> expressions;
596 if (m_pToken->m_type != TOKrparen) {
597 while (m_pToken->m_type != TOKrparen) {
598 std::unique_ptr<CXFA_FMSimpleExpression> exp =
599 ParseSimpleExpression();
600 expressions.push_back(std::move(exp));
601 if (m_pToken->m_type == TOKcomma) {
602 NextToken();
603 } else if (m_pToken->m_type == TOKeof ||
604 m_pToken->m_type == TOKreserver) {
605 break;
606 }
607 }
608 if (m_pToken->m_type != TOKrparen) {
609 CFX_WideString ws_TempString(m_pToken->m_wstring);
610 Error(m_pToken->m_uLinenum, kFMErrExpectedToken,
611 XFA_FM_KeywordToString(TOKrparen), ws_TempString.c_str());
612 }
613 }
614 if (m_pErrorInfo->message.IsEmpty()) {
615 std::unique_ptr<CXFA_FMSimpleExpression> pIdentifier =
616 pdfium::MakeUnique<CXFA_FMIdentifierExpression>(tempLine,
617 tempStr);
618 pExpCall = pdfium::MakeUnique<CXFA_FMCallExpression>(
619 line, std::move(pIdentifier), std::move(expressions), true);
620 expr = pdfium::MakeUnique<CXFA_FMMethodCallExpression>(
621 line, std::move(expr), std::move(pExpCall));
622 NextToken();
623 if (m_pToken->m_type != TOKlbracket)
624 continue;
625
626 std::unique_ptr<CXFA_FMSimpleExpression> s =
627 ParseIndexExpression();
628 if (s) {
629 expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
630 line, std::move(expr), TOKcall, L"", std::move(s));
631 } else {
632 expr.reset();
633 }
634 } else {
635 expr.reset();
636 }
637 } else if (m_pToken->m_type == TOKlbracket) {
638 std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression();
639 if (!(m_pErrorInfo->message.IsEmpty()))
640 return nullptr;
641
642 expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
643 tempLine, std::move(expr), TOKdot, tempStr, std::move(s));
644 } else {
645 std::unique_ptr<CXFA_FMSimpleExpression> s =
646 pdfium::MakeUnique<CXFA_FMIndexExpression>(
647 tempLine, ACCESSOR_NO_INDEX, nullptr, false);
648 expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
649 line, std::move(expr), TOKdot, tempStr, std::move(s));
650 continue;
651 }
652 } else {
653 CFX_WideString ws_TempString(m_pToken->m_wstring);
654 Error(m_pToken->m_uLinenum, kFMErrExpectedIdentifier,
655 ws_TempString.c_str());
656 return expr;
657 }
658 break;
659 case TOKdotdot:
660 NextToken();
661 if (m_pToken->m_type == TOKidentifier) {
662 CFX_WideStringC tempStr = m_pToken->m_wstring;
663 uint32_t tempLine = m_pToken->m_uLinenum;
664 NextToken();
665 if (m_pToken->m_type == TOKlbracket) {
666 std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression();
667 if (!(m_pErrorInfo->message.IsEmpty())) {
668 return nullptr;
669 }
670 expr = pdfium::MakeUnique<CXFA_FMDotDotAccessorExpression>(
671 tempLine, std::move(expr), TOKdotdot, tempStr, std::move(s));
672 } else {
673 std::unique_ptr<CXFA_FMSimpleExpression> s =
674 pdfium::MakeUnique<CXFA_FMIndexExpression>(
675 tempLine, ACCESSOR_NO_INDEX, nullptr, false);
676 expr = pdfium::MakeUnique<CXFA_FMDotDotAccessorExpression>(
677 line, std::move(expr), TOKdotdot, tempStr, std::move(s));
678 continue;
679 }
680 } else {
681 CFX_WideString ws_TempString(m_pToken->m_wstring);
682 Error(m_pToken->m_uLinenum, kFMErrExpectedIdentifier,
683 ws_TempString.c_str());
684 return expr;
685 }
686 break;
687 case TOKdotscream:
688 NextToken();
689 if (m_pToken->m_type == TOKidentifier) {
690 CFX_WideStringC tempStr = m_pToken->m_wstring;
691 uint32_t tempLine = m_pToken->m_uLinenum;
692 NextToken();
693 if (m_pToken->m_type == TOKlbracket) {
694 std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression();
695 if (!(m_pErrorInfo->message.IsEmpty()))
696 return nullptr;
697
698 expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
699 tempLine, std::move(expr), TOKdotscream, tempStr, std::move(s));
700 } else {
701 std::unique_ptr<CXFA_FMSimpleExpression> s =
702 pdfium::MakeUnique<CXFA_FMIndexExpression>(
703 tempLine, ACCESSOR_NO_INDEX, nullptr, false);
704 expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
705 line, std::move(expr), TOKdotscream, tempStr, std::move(s));
706 continue;
707 }
708 } else {
709 CFX_WideString ws_TempString(m_pToken->m_wstring);
710 Error(m_pToken->m_uLinenum, kFMErrExpectedIdentifier,
711 ws_TempString.c_str());
712 return expr;
713 }
714 break;
715 case TOKdotstar: {
716 std::unique_ptr<CXFA_FMSimpleExpression> s =
717 pdfium::MakeUnique<CXFA_FMIndexExpression>(line, ACCESSOR_NO_INDEX,
718 nullptr, false);
719 expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
720 line, std::move(expr), TOKdotstar, L"*", std::move(s));
721 } break;
722 default:
723 return expr;
724 }
725 NextToken();
726 }
727 return expr;
728 }
729
ParseIndexExpression()730 std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParse::ParseIndexExpression() {
731 std::unique_ptr<CXFA_FMSimpleExpression> pExp;
732 uint32_t line = m_pToken->m_uLinenum;
733 NextToken();
734 std::unique_ptr<CXFA_FMSimpleExpression> s;
735 XFA_FM_AccessorIndex accessorIndex = ACCESSOR_NO_RELATIVEINDEX;
736 if (m_pToken->m_type == TOKmul) {
737 pExp = pdfium::MakeUnique<CXFA_FMIndexExpression>(line, accessorIndex,
738 std::move(s), true);
739 NextToken();
740 if (m_pToken->m_type != TOKrbracket) {
741 CFX_WideString ws_TempString(m_pToken->m_wstring);
742 Error(m_pToken->m_uLinenum, kFMErrExpectedToken,
743 XFA_FM_KeywordToString(TOKrparen), ws_TempString.c_str());
744 pExp.reset();
745 }
746 return pExp;
747 }
748 if (m_pToken->m_type == TOKplus) {
749 accessorIndex = ACCESSOR_POSITIVE_INDEX;
750 NextToken();
751 } else if (m_pToken->m_type == TOKminus) {
752 accessorIndex = ACCESSOR_NEGATIVE_INDEX;
753 NextToken();
754 }
755 s = ParseSimpleExpression();
756 if (m_pToken->m_type != TOKrbracket) {
757 CFX_WideString ws_TempString(m_pToken->m_wstring);
758 Error(m_pToken->m_uLinenum, kFMErrExpectedToken,
759 XFA_FM_KeywordToString(TOKrparen), ws_TempString.c_str());
760 } else {
761 pExp = pdfium::MakeUnique<CXFA_FMIndexExpression>(line, accessorIndex,
762 std::move(s), false);
763 }
764 return pExp;
765 }
766
ParseParenExpression()767 std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParse::ParseParenExpression() {
768 Check(TOKlparen);
769
770 if (m_pToken->m_type == TOKrparen) {
771 Error(m_pToken->m_uLinenum, kFMErrExpectedNonEmptyExpression);
772 NextToken();
773 return nullptr;
774 }
775
776 uint32_t line = m_pToken->m_uLinenum;
777 std::unique_ptr<CXFA_FMSimpleExpression> pExp1 = ParseLogicalOrExpression();
778
779 while (m_pToken->m_type == TOKassign) {
780 NextToken();
781 std::unique_ptr<CXFA_FMSimpleExpression> pExp2 = ParseLogicalOrExpression();
782 if (m_pErrorInfo->message.IsEmpty()) {
783 pExp1 = pdfium::MakeUnique<CXFA_FMAssignExpression>(
784 line, TOKassign, std::move(pExp1), std::move(pExp2));
785 } else {
786 pExp1.reset();
787 }
788 }
789 Check(TOKrparen);
790 return pExp1;
791 }
792
ParseBlockExpression()793 std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseBlockExpression() {
794 uint32_t line = m_pToken->m_uLinenum;
795 std::unique_ptr<CXFA_FMExpression> expr;
796 std::vector<std::unique_ptr<CXFA_FMExpression>> expressions;
797
798 while (1) {
799 switch (m_pToken->m_type) {
800 case TOKeof:
801 case TOKendif:
802 case TOKelseif:
803 case TOKelse:
804 case TOKendwhile:
805 case TOKendfor:
806 case TOKend:
807 case TOKendfunc:
808 case TOKreserver:
809 break;
810 case TOKfunc:
811 expr = ParseFunction();
812 if (expr) {
813 expressions.push_back(std::move(expr));
814 }
815 continue;
816 default:
817 expr = ParseExpression();
818 if (expr) {
819 expressions.push_back(std::move(expr));
820 }
821 continue;
822 }
823 break;
824 }
825 std::unique_ptr<CXFA_FMBlockExpression> pExp;
826 if (m_pErrorInfo->message.IsEmpty()) {
827 pExp = pdfium::MakeUnique<CXFA_FMBlockExpression>(line,
828 std::move(expressions));
829 }
830 return pExp;
831 }
832
ParseIfExpression()833 std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseIfExpression() {
834 uint32_t line = m_pToken->m_uLinenum;
835 const FX_WCHAR* pStartPos = m_lexer->SavePos();
836 NextToken();
837 Check(TOKlparen);
838 std::unique_ptr<CXFA_FMSimpleExpression> pExpression;
839 while (m_pToken->m_type != TOKrparen) {
840 pExpression = ParseSimpleExpression();
841 if (m_pToken->m_type != TOKcomma)
842 break;
843 NextToken();
844 }
845 Check(TOKrparen);
846 if (m_pToken->m_type != TOKthen) {
847 m_lexer->SetCurrentLine(line);
848 m_pToken = new CXFA_FMToken(line);
849 m_pToken->m_type = TOKidentifier;
850 m_pToken->m_wstring = L"if";
851 m_lexer->SetToken(m_pToken);
852 m_lexer->RestorePos(pStartPos);
853 return ParseExpExpression();
854 }
855 Check(TOKthen);
856 std::unique_ptr<CXFA_FMExpression> pIfExpression = ParseBlockExpression();
857 std::unique_ptr<CXFA_FMExpression> pElseExpression;
858 switch (m_pToken->m_type) {
859 case TOKeof:
860 case TOKendif:
861 Check(TOKendif);
862 break;
863 case TOKif:
864 pElseExpression = ParseIfExpression();
865 Check(TOKendif);
866 break;
867 case TOKelseif:
868 pElseExpression = ParseIfExpression();
869 break;
870 case TOKelse:
871 NextToken();
872 pElseExpression = ParseBlockExpression();
873 Check(TOKendif);
874 break;
875 default:
876 CFX_WideString ws_TempString(m_pToken->m_wstring);
877 Error(m_pToken->m_uLinenum, kFMErrExpectedEndIf, ws_TempString.c_str());
878 NextToken();
879 break;
880 }
881 std::unique_ptr<CXFA_FMIfExpression> pExp;
882 if (m_pErrorInfo->message.IsEmpty()) {
883 pExp = pdfium::MakeUnique<CXFA_FMIfExpression>(line, std::move(pExpression),
884 std::move(pIfExpression),
885 std::move(pElseExpression));
886 }
887 return pExp;
888 }
889
ParseWhileExpression()890 std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseWhileExpression() {
891 uint32_t line = m_pToken->m_uLinenum;
892 NextToken();
893 std::unique_ptr<CXFA_FMSimpleExpression> pCondition = ParseParenExpression();
894 Check(TOKdo);
895 std::unique_ptr<CXFA_FMExpression> pExpression = ParseBlockExpression();
896 Check(TOKendwhile);
897 std::unique_ptr<CXFA_FMExpression> expr;
898 if (m_pErrorInfo->message.IsEmpty()) {
899 expr = pdfium::MakeUnique<CXFA_FMWhileExpression>(
900 line, std::move(pCondition), std::move(pExpression));
901 }
902 return expr;
903 }
904
905 std::unique_ptr<CXFA_FMSimpleExpression>
ParseSubassignmentInForExpression()906 CXFA_FMParse::ParseSubassignmentInForExpression() {
907 std::unique_ptr<CXFA_FMSimpleExpression> expr;
908 switch (m_pToken->m_type) {
909 case TOKidentifier:
910 expr = ParseSimpleExpression();
911 break;
912 default:
913 CFX_WideString ws_TempString(m_pToken->m_wstring);
914 Error(m_pToken->m_uLinenum, kFMErrUnexpectedExpression,
915 ws_TempString.c_str());
916 NextToken();
917 break;
918 }
919 return expr;
920 }
921
ParseForExpression()922 std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseForExpression() {
923 CFX_WideStringC wsVariant;
924 uint32_t line = m_pToken->m_uLinenum;
925 NextToken();
926 if (m_pToken->m_type != TOKidentifier) {
927 CFX_WideString ws_TempString(m_pToken->m_wstring);
928 Error(m_pToken->m_uLinenum, kFMErrExpectedToken,
929 XFA_FM_KeywordToString(m_pToken->m_type), ws_TempString.c_str());
930 }
931 wsVariant = m_pToken->m_wstring;
932 NextToken();
933 std::unique_ptr<CXFA_FMSimpleExpression> pAssignment;
934 if (m_pToken->m_type == TOKassign) {
935 NextToken();
936 pAssignment = ParseSimpleExpression();
937 } else {
938 CFX_WideString ws_TempString(m_pToken->m_wstring);
939 Error(m_pToken->m_uLinenum, kFMErrExpectedToken,
940 XFA_FM_KeywordToString(m_pToken->m_type), ws_TempString.c_str());
941 }
942 int32_t iDirection = 0;
943 if (m_pToken->m_type == TOKupto) {
944 iDirection = 1;
945 } else if (m_pToken->m_type == TOKdownto) {
946 iDirection = -1;
947 } else {
948 CFX_WideString ws_TempString(m_pToken->m_wstring);
949 Error(m_pToken->m_uLinenum, kFMErrExpectedToken, L"upto or downto",
950 ws_TempString.c_str());
951 }
952 NextToken();
953 std::unique_ptr<CXFA_FMSimpleExpression> pAccessor = ParseSimpleExpression();
954 std::unique_ptr<CXFA_FMSimpleExpression> pStep;
955 if (m_pToken->m_type == TOKstep) {
956 NextToken();
957 pStep = ParseSimpleExpression();
958 }
959 Check(TOKdo);
960 std::unique_ptr<CXFA_FMExpression> pList = ParseBlockExpression();
961 Check(TOKendfor);
962 std::unique_ptr<CXFA_FMExpression> expr;
963 if (m_pErrorInfo->message.IsEmpty()) {
964 expr = pdfium::MakeUnique<CXFA_FMForExpression>(
965 line, wsVariant, std::move(pAssignment), std::move(pAccessor),
966 iDirection, std::move(pStep), std::move(pList));
967 }
968 return expr;
969 }
970
ParseForeachExpression()971 std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseForeachExpression() {
972 std::unique_ptr<CXFA_FMExpression> expr;
973 CFX_WideStringC wsIdentifier;
974 std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> pAccessors;
975 std::unique_ptr<CXFA_FMExpression> pList;
976 uint32_t line = m_pToken->m_uLinenum;
977 NextToken();
978 if (m_pToken->m_type != TOKidentifier) {
979 CFX_WideString ws_TempString(m_pToken->m_wstring);
980 Error(m_pToken->m_uLinenum, kFMErrExpectedToken,
981 XFA_FM_KeywordToString(m_pToken->m_type), ws_TempString.c_str());
982 }
983 wsIdentifier = m_pToken->m_wstring;
984 NextToken();
985 Check(TOKin);
986 Check(TOKlparen);
987 if (m_pToken->m_type == TOKrparen) {
988 CFX_WideString ws_TempString(m_pToken->m_wstring);
989 Error(m_pToken->m_uLinenum, kFMErrUnexpectedExpression,
990 ws_TempString.c_str());
991 NextToken();
992 } else {
993 while (m_pToken->m_type != TOKrparen) {
994 std::unique_ptr<CXFA_FMSimpleExpression> s = ParseSimpleExpression();
995 if (s)
996 pAccessors.push_back(std::move(s));
997 if (m_pToken->m_type != TOKcomma)
998 break;
999 NextToken();
1000 }
1001 Check(TOKrparen);
1002 }
1003 Check(TOKdo);
1004 pList = ParseBlockExpression();
1005 Check(TOKendfor);
1006 if (m_pErrorInfo->message.IsEmpty()) {
1007 expr = pdfium::MakeUnique<CXFA_FMForeachExpression>(
1008 line, wsIdentifier, std::move(pAccessors), std::move(pList));
1009 }
1010 return expr;
1011 }
1012
ParseDoExpression()1013 std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseDoExpression() {
1014 uint32_t line = m_pToken->m_uLinenum;
1015 NextToken();
1016 std::unique_ptr<CXFA_FMExpression> expr = ParseBlockExpression();
1017 Check(TOKend);
1018 if (!m_pErrorInfo->message.IsEmpty())
1019 return nullptr;
1020
1021 return pdfium::MakeUnique<CXFA_FMDoExpression>(line, std::move(expr));
1022 }
1023