/[publicrep]/ezc/trunk/src/patternparser.cpp
ViewVC logotype

Contents of /ezc/trunk/src/patternparser.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1139 - (show annotations)
Thu Nov 1 21:52:33 2018 UTC (4 years, 4 months ago) by tomek
Content type: text/x-csrc
File size: 20516 byte(s)
fixed: program_mode was not set in cctor
fixed: container was not correctly parsed (in template mode)



1 /*
2 * This file is a part of EZC -- Easy templating in C++ library
3 * and is distributed under the BSD 3-Clause licence.
4 * Author: Tomasz Sowa <t.sowa@ttmath.org>
5 */
6
7 /*
8 * Copyright (c) 2007-2018, Tomasz Sowa
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions are met:
13 *
14 * * Redistributions of source code must retain the above copyright notice,
15 * this list of conditions and the following disclaimer.
16 *
17 * * Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 *
21 * * Neither the name Tomasz Sowa nor the names of contributors to this
22 * project may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
35 * THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38
39 #include "patternparser.h"
40 #include "convert/convert.h"
41
42 #ifdef EZC_USE_WINIX_LOGGER
43 #include "core/log.h"
44 #endif
45
46
47 namespace Ezc
48 {
49
50
51
52 PatternParser::PatternParser()
53 {
54 allow_include = true;
55 pblocks = 0;
56 include_level_max = 100;
57 delete_white_text_items = false;
58 program_mode = false;
59 }
60
61
62
63 void PatternParser::Directory(const char * dir, const char * dir2)
64 {
65 directory.clear();
66 directory2.clear();
67
68 if( dir )
69 PT::UTF8ToWide(dir, directory);
70
71 if( dir2 )
72 PT::UTF8ToWide(dir2, directory2);
73 }
74
75
76
77 void PatternParser::Directory(const std::string & dir)
78 {
79 PT::UTF8ToWide(dir, directory);
80 directory2.clear();
81 }
82
83
84
85 void PatternParser::Directory(const std::string & dir, const std::string & dir2)
86 {
87 PT::UTF8ToWide(dir, directory);
88 PT::UTF8ToWide(dir2, directory2);
89 }
90
91
92
93 void PatternParser::Directory(const wchar_t * dir, const wchar_t * dir2)
94 {
95 directory.clear();
96 directory2.clear();
97
98 if( dir )
99 directory = dir;
100
101 if( dir2 )
102 directory2 = dir2;
103 }
104
105
106
107 void PatternParser::Directory(const std::wstring & dir)
108 {
109 directory = dir;
110 directory2.clear();
111 }
112
113
114
115 void PatternParser::Directory(const std::wstring & dir, const std::wstring & dir2)
116 {
117 directory = dir;
118 directory2 = dir2;
119 }
120
121
122
123 void PatternParser::SetBlocks(Blocks & blocks)
124 {
125 pblocks = &blocks;
126 }
127
128
129 void PatternParser::SetCommentary(const char * com_start, const char * com_stop)
130 {
131 PT::UTF8ToWide(com_start, commentary_start);
132 PT::UTF8ToWide(com_stop, commentary_stop);
133 }
134
135
136
137 void PatternParser::SetCommentary(const std::string & com_start, const std::string & com_stop)
138 {
139 PT::UTF8ToWide(com_start, commentary_start);
140 PT::UTF8ToWide(com_stop, commentary_stop);
141 }
142
143
144
145 void PatternParser::SetCommentary(const wchar_t * com_start, const wchar_t * com_stop)
146 {
147 commentary_start = com_start;
148 commentary_stop = com_stop;
149 }
150
151
152
153 void PatternParser::SetCommentary(const std::wstring & com_start, const std::wstring & com_stop)
154 {
155 commentary_start = com_start;
156 commentary_stop = com_stop;
157 }
158
159
160 void PatternParser::SetProgramMode(bool program_mode)
161 {
162 this->program_mode = program_mode;
163 }
164
165
166 void PatternParser::CreateMsg(std::wstring & out, const wchar_t * type, const wchar_t * arg)
167 {
168 out = commentary_start;
169 out += L"Ezc: ";
170 out += type;
171
172 if( arg )
173 {
174 out += ' ';
175 out += arg;
176 }
177
178 out += commentary_stop;
179 }
180
181
182
183 void PatternParser::ParseFile(const std::string & file_name, Pattern & pattern)
184 {
185 ParseFile(file_name.c_str(), pattern);
186 }
187
188
189
190
191 void PatternParser::ParseFile(const char * file_name, Pattern & pattern)
192 {
193 pat = &pattern;
194 PT::UTF8ToWide(file_name, pat->item_root.file_name);
195 include_level = 0;
196
197 CreateTreeReadIncludeSkipAllowFlag(pat->item_root);
198 }
199
200
201
202
203 void PatternParser::ParseFile(const std::wstring & file_name, Pattern & pattern)
204 {
205 ParseFile(file_name.c_str(), pattern);
206 }
207
208
209
210
211 void PatternParser::ParseFile(const wchar_t * file_name, Pattern & pattern)
212 {
213 pat = &pattern;
214 pat->item_root.file_name = file_name;
215 include_level = 0;
216 CreateTreeReadIncludeSkipAllowFlag(pat->item_root);
217 }
218
219
220
221
222 void PatternParser::ParseString(const char * str, Pattern & pattern)
223 {
224 PT::UTF8ToWide(str, string_content);
225 ParseString(string_content.c_str(), pattern);
226 string_content.clear();
227 }
228
229
230
231 void PatternParser::ParseString(const std::string & str, Pattern & pattern)
232 {
233 ParseString(str.c_str(), pattern);
234 }
235
236
237
238 void PatternParser::ParseString(const wchar_t * str, Pattern & pattern)
239 {
240 pat = &pattern;
241 itext = str;
242 include_level = 0;
243
244 pat->item_root.Clear();
245 CreateTreeContainer(pat->item_root);
246 }
247
248
249
250 void PatternParser::ParseString(const std::wstring & str, Pattern & pattern)
251 {
252 ParseString(str.c_str(), pattern);
253 }
254
255
256
257
258
259
260
261
262
263 void PatternParser::AllowInclude(bool allow)
264 {
265 allow_include = allow;
266 }
267
268
269
270 void PatternParser::DeleteWhiteTextItems(bool del)
271 {
272 delete_white_text_items = del;
273 }
274
275
276
277 void PatternParser::SetIncludeMax(int include_max)
278 {
279 include_level_max = include_max;
280 }
281
282
283
284
285
286
287
288 bool PatternParser::HasFileAtBeginning(const wchar_t * path, const wchar_t * file)
289 {
290 for(; *path && *file; ++path, ++file)
291 {
292 if( *path != *file )
293 return false;
294 }
295
296 if( *file != 0 )
297 return false;
298
299 // "\" is from a dos path syntax
300 if( *path==0 || *path=='\\' || *path=='/' )
301 return true;
302
303 return false;
304 }
305
306
307 /*
308 ".." is not allowed in the file path
309 you cannot go up from your template directory
310 */
311 bool PatternParser::IsFileCorrect(const wchar_t * name)
312 {
313 while( *name )
314 {
315 if( HasFileAtBeginning(name, L"..") )
316 return false;
317
318 // looking for the next slash of backslash
319 while( *name && *name!='\\' && *name!='/' )
320 name += 1;
321
322 // skipping the slash (or backslash)
323 if( *name )
324 name += 1;
325 }
326
327 return true;
328 }
329
330
331
332
333 /*
334 'name' must be a relative path - without a slash or backslash
335 */
336 void PatternParser::ReadFile(const std::wstring & name, std::wstring & result)
337 {
338 ReadFile(name.c_str(), result);
339 }
340
341
342 /*
343 'name' must be a relative path - without a slash or backslash
344 */
345 void PatternParser::ReadFile(const wchar_t * name, std::wstring & result)
346 {
347 if( !IsFileCorrect(name) )
348 {
349 CreateMsg(result, L"incorrect file name: ", name);
350 }
351 else
352 {
353 result.clear();
354
355 if( !ReadFileFromDir(directory, name, result) )
356 if( !ReadFileFromDir(directory2, name, result) )
357 CreateMsg(result, L"can't open: ", name);
358 }
359 }
360
361
362
363 bool PatternParser::ReadFileFromDir(const std::wstring & dir, const wchar_t * name, std::wstring & result)
364 {
365 if( dir.empty() )
366 return false;
367
368 file_name = dir;
369 file_name += '/';
370 file_name += name;
371 PT::WideToUTF8(file_name, afile_name);
372
373 std::ifstream file(afile_name.c_str());
374
375 if( !file )
376 {
377 file_name.clear();
378 afile_name.clear();
379 return false;
380 }
381
382 #ifdef EZC_USE_WINIX_LOGGER
383 if( include_level <= 1 )
384 Winix::log << Winix::log3 << "Ezc: reading pattern: " << afile_name << Winix::logend;
385 else
386 Winix::log << Winix::log3 << " including pattern: " << afile_name << Winix::logend;
387 #endif
388
389 ReadFile(file, result);
390
391 file_name.clear();
392 afile_name.clear();
393
394 return true;
395 }
396
397
398
399 void PatternParser::ReadFile(std::ifstream & file, std::wstring & result)
400 {
401 PT::UTF8ToWide(file, result);
402 }
403
404
405
406 int PatternParser::ReadCharInText()
407 {
408 if( *itext==0 || *itext=='[' )
409 return -1;
410
411 if( *itext == '\\' )
412 {
413 if( *(itext+1)=='\\' || *(itext+1)=='[' || *(itext+1)==']' )
414 ++itext;
415 }
416
417 return *(itext++);
418 }
419
420
421 bool PatternParser::IsWhite(wchar_t c)
422 {
423 // 13 (\r) is from a dos file at the end of a line (\r\n)
424 // 160 is a non-breaking space
425
426 if( c==' ' || c=='\t' || c==13 || c==160 || c==10 )
427 return true;
428
429 return false;
430 }
431
432
433
434 void PatternParser::SkipWhite()
435 {
436 while( IsWhite(*itext) )
437 ++itext;
438 }
439
440
441 void PatternParser::SkipOneStatement()
442 {
443 size_t count = 1;
444
445 while( *itext != 0 && count > 0 )
446 {
447 if( *itext == '[' )
448 count += 1;
449 else
450 if( *itext == ']' )
451 count -= 1;
452
453 itext += 1;
454 }
455 }
456
457
458 void PatternParser::CheckWhiteAndDelete(std::wstring & s)
459 {
460 size_t i;
461
462 if( s.empty() )
463 return;
464
465 for(i=0 ; i<s.size() && IsWhite(s[i]) ; ++i);
466
467 if( i == s.size() )
468 s.clear(); // the whole string consists of white characters
469 }
470
471
472 void PatternParser::CheckFunctionIsNumber(Item::Function & function)
473 {
474 if( IsPositiveNumber(function.name) )
475 function.arg = wcstol(function.name.c_str(), 0, 10);
476 }
477
478
479 bool PatternParser::IsNameChar(wchar_t c)
480 {
481 return ((c>='a' && c<='z') ||
482 (c>='A' && c<='Z') ||
483 (c>='0' && c<='9') ||
484 c=='_' || c=='-' || c=='.' || c=='#');
485 }
486
487
488
489 bool PatternParser::IsDigit(wchar_t c)
490 {
491 return (c>='0' && c<='9');
492 }
493
494
495
496 bool PatternParser::IsPositiveNumber(const std::wstring & str)
497 {
498 size_t i;
499
500 for(i=0 ; i<str.size() ; ++i)
501 if( !IsDigit(str[i]) )
502 return false;
503
504 return true;
505 }
506
507
508 // reading an expression name or a function name
509 bool PatternParser::ReadName(std::wstring & name)
510 {
511 name.clear();
512
513 while( IsNameChar(*itext) )
514 {
515 name += *itext;
516 ++itext;
517 }
518
519 return !name.empty();
520 }
521
522
523
524
525 // string can have a quote character (escaped with a backslash) e.g. "sample text \"with quotes\""
526 // use \\ to insert one backslash
527 bool PatternParser::ReadString(std::wstring & str)
528 {
529 str.clear();
530 SkipWhite();
531
532 // string is signed by its first quote character (")
533 if( *itext != '\"' )
534 return false;
535
536 ++itext;
537
538 while( *itext && *itext!='\"' )
539 {
540 if( itext[0]=='\\' && itext[1]=='\"' )
541 {
542 str += '\"';
543 itext += 2;
544 }
545 else
546 if( itext[0]=='\\' && itext[1]=='\\' )
547 {
548 str += '\\';
549 itext += 2;
550 }
551 else
552 {
553 str += *itext;
554 itext += 1;
555 }
556 }
557
558 if( *itext == '\"' )
559 {
560 ++itext;
561 return true;
562 }
563 else
564 {
565 return false;
566 }
567 }
568
569
570
571
572
573 bool PatternParser::ReadParamString(Item::Function & function)
574 {
575 Item::Function & fun = function.AddNewParam();
576 fun.is_function = false;
577
578 return ReadString(fun.name);
579 }
580
581
582 /*
583 returns true if it correctly reads all parameters
584 */
585 bool PatternParser::ReadParams(Item::Function & function)
586 {
587 bool res = true;
588 bool check_next_param = true;
589
590 while( check_next_param && res )
591 {
592 SkipWhite();
593
594 if( *itext == '[' )
595 {
596 res = ReadFunction(function.AddNewParam(), true);
597 }
598 else
599 if( *itext == '\"' )
600 {
601 res = ReadParamString(function);
602 }
603 else
604 if( *itext != ']' && *itext != 0 )
605 {
606 res = ReadFunction(function.AddNewParam(), false);
607 }
608 else
609 {
610 // *itext is equal to ']'
611 check_next_param = false;
612 res = true;
613 }
614 }
615
616 return res;
617 }
618
619
620
621
622
623 bool PatternParser::ReadFunction(Item::Function & function, bool with_params)
624 {
625 bool res = false;
626 SkipWhite();
627 function.Clear();
628
629 if( *itext == '[' )
630 {
631 itext += 1;
632 res = ReadFunction(function, true);
633
634 SkipWhite();
635
636 if( *itext == ']' )
637 {
638 itext += 1;
639 }
640 else
641 {
642 SkipOneStatement();
643 res = false;
644 }
645 }
646 else
647 {
648 res = ReadName(function.name);
649
650 if( res )
651 {
652 if( *itext == ':' )
653 {
654 itext += 1;
655 ReadName(function.postfix); // we allow the postfix to be empty
656 }
657
658 if( with_params )
659 res = ReadParams(function);
660 }
661 }
662
663 if( res )
664 {
665 // IMPROVE ME
666 // this will be called more than once for nested functions
667 CheckFunctionIsNumber(function);
668 }
669
670 function.is_function = res;
671
672 return res;
673 }
674
675
676
677 /*
678 returns true if a function has been correctly read
679 */
680 bool PatternParser::ReadFunction(Item & item)
681 {
682 bool function_read_correctly = ReadFunction(item.function, true);
683
684 if( !function_read_correctly )
685 {
686 item.function.Clear();
687 item.type = Item::item_err;
688 }
689
690 return function_read_correctly;
691 }
692
693
694
695 void PatternParser::CreateTreeReadItemDirectiveCheckEnding(Item & item)
696 {
697 SkipWhite();
698
699 if( *itext == ']' )
700 {
701 itext += 1;
702 }
703 else
704 {
705 item.type = Item::item_err;
706 item.function.Clear();
707 SkipOneStatement();
708 }
709 }
710
711
712
713
714 void PatternParser::ReadNormalStatement(Item & item)
715 {
716 item.type = Item::item_function;
717 item.has_function = true;
718
719 if( !ReadFunction(item.function, true) )
720 {
721 item.type = Item::item_err;
722 item.function.Clear();
723 }
724 }
725
726
727
728 void PatternParser::ReadDirectiveIf(Item & item)
729 {
730 item.type = Item::item_if;
731 ReadFunction(item);
732 }
733
734
735
736 void PatternParser::ReadDirectiveEnd(Item & item)
737 {
738 item.type = Item::item_end;
739 }
740
741
742
743 void PatternParser::ReadDirectiveElse(Item & item)
744 {
745 item.type = Item::item_else;
746 }
747
748
749
750 void PatternParser::ReadDirectiveFor(Item & item)
751 {
752 item.type = Item::item_for;
753 ReadFunction(item);
754 }
755
756
757
758 void PatternParser::ReadDirectiveComment(Item & item)
759 {
760 item.type = Item::item_comment;
761
762 // skipping the comment
763 while( *itext && *itext!=']' )
764 ++itext;
765 }
766
767
768
769 void PatternParser::ReadDirectiveInclude(Item & item)
770 {
771 if( ReadString(item.file_name) )
772 item.type = Item::item_include;
773 else
774 item.type = Item::item_err;
775 }
776
777
778
779 void PatternParser::ReadDirectiveDef(Item & item)
780 {
781 item.type = Item::item_def;
782 ReadFunction(item);
783 }
784
785
786 void PatternParser::ReadDirectiveFilter(Item & item)
787 {
788 item.type = Item::item_filter;
789 ReadFunction(item);
790 }
791
792
793 void PatternParser::ReadDirectiveEzc(Item & item)
794 {
795 item.type = Item::item_ezc;
796 ReadFunction(item);
797 }
798
799
800 /*
801 [out] is a shorthand for [ezc out]
802 */
803 void PatternParser::ReadDirectiveOut(Item & item)
804 {
805 item.type = Item::item_ezc;
806 item.has_function = true;
807
808 item.function.Clear();
809 item.function.name = L"out";
810 item.function.is_function = true;
811
812 if( !ReadParams(item.function) )
813 {
814 item.type = Item::item_err;
815 item.function.Clear();
816 }
817 }
818
819
820 void PatternParser::ReadDirectiveBlock(Item & item)
821 {
822 item.type = Item::item_block;
823 ReadFunction(item);
824
825 // only one function without arguments
826 if( !item.function.parameters.empty() )
827 item.type = Item::item_err;
828 }
829
830
831 void PatternParser::ReadDirectiveReturn(Item & item)
832 {
833 item.type = Item::item_return;
834 ReadFunction(item);
835 }
836
837
838
839
840
841 void PatternParser::CreateTreeReadItemDirective(Item & item)
842 {
843 std::wstring name;
844
845 ++itext;
846 SkipWhite();
847 const wchar_t * old_itext = itext;
848
849 ReadName(name);
850
851 if ( name == L"if" ) ReadDirectiveIf(item);
852 else if( name == L"end" ) ReadDirectiveEnd(item);
853 else if( name == L"else" ) ReadDirectiveElse(item);
854 else if( name == L"for" ) ReadDirectiveFor(item);
855 else if( name == L"include" ) ReadDirectiveInclude(item);
856 else if( name == L"def" ) ReadDirectiveDef(item);
857 else if( name == L"filter" ) ReadDirectiveFilter(item);
858 else if( name == L"ezc" ) ReadDirectiveEzc(item);
859 else if( name == L"out" ) ReadDirectiveOut(item);
860 else if( name == L"block" ) ReadDirectiveBlock(item);
861 else if( name == L"return" ) ReadDirectiveReturn(item);
862 else if( name == L"#" ) ReadDirectiveComment(item);
863 else if( *old_itext == '[' || !name.empty() )
864 {
865 itext = old_itext;
866 ReadNormalStatement(item);
867 }
868
869 CreateTreeReadItemDirectiveCheckEnding(item);
870 }
871
872
873
874 void PatternParser::CreateTreeReadItemText(Item & item)
875 {
876 int c;
877
878 while( (c = ReadCharInText()) != -1 )
879 item.text += static_cast<wchar_t>(c);
880
881 if( delete_white_text_items )
882 CheckWhiteAndDelete(item.text);
883
884 item.type = Item::item_text;
885 }
886
887
888 void PatternParser::CreateTreeReadDirectiveExpression(Item & item, bool is_statement)
889 {
890 int brackets_counter = is_statement ? 1 : 0;
891
892 while( *itext )
893 {
894 wchar_t c = *itext;
895
896 if( c == 10 || c == 13 )
897 c = ' ';
898
899 if( c == ';' && brackets_counter == 0 )
900 {
901 itext += 1;
902 return; // end of normal expression (not in a statement such as 'for' or 'if')
903 }
904
905 if( c == '(' )
906 {
907 brackets_counter += 1;
908 }
909
910 if( c == ')' )
911 {
912 brackets_counter -= 1;
913
914 if( is_statement && brackets_counter == 0 )
915 {
916 itext += 1;
917 return; // end of statement expression
918 }
919 }
920
921 if( !IsWhite(c) || item.text.empty() || !IsWhite(item.text.back()) )
922 item.text += c;
923
924 itext += 1;
925 }
926 }
927
928
929 bool PatternParser::CreateTreeCheckProgramDirective(Item & item)
930 {
931 const wchar_t * old_itext = itext;
932
933 if( PT::IsSubStringNoCasep(L"if", itext) )
934 {
935 itext += 2;
936 SkipWhite();
937
938 if( *itext == '(' )
939 {
940 itext += 1;
941 item.type = Item::item_if;
942 return true;
943 }
944 }
945
946 if( PT::IsSubStringNoCasep(L"while", itext) )
947 {
948 itext += 5;
949 SkipWhite();
950
951 if( *itext == '(' )
952 {
953 itext += 1;
954 item.type = Item::item_for;
955 return true;
956 }
957 }
958
959 itext = old_itext;
960 return false;
961 }
962
963
964 bool PatternParser::CreateTreeReadExpression(Item & item)
965 {
966 SkipWhite();
967
968 if( *itext == 0 )
969 return false;
970
971 if( *itext == '{' )
972 {
973 item.type = Item::item_container;
974 itext += 1;
975 return true;
976 }
977
978 if( *itext == '}' )
979 {
980 item.type = Item::item_end;
981 itext += 1;
982 return true;
983 }
984
985 if( CreateTreeCheckProgramDirective(item) )
986 {
987 CreateTreeReadDirectiveExpression(item, true);
988 }
989 else
990 {
991 item.type = Item::item_function;
992 CreateTreeReadDirectiveExpression(item, false);
993 }
994
995 return true;
996 }
997
998
999 bool PatternParser::CreateTreeReadItem(Item & item)
1000 {
1001 item.Clear();
1002
1003 if( program_mode )
1004 {
1005 return CreateTreeReadExpression(item);
1006 }
1007 else
1008 {
1009 if( *itext == '[' )
1010 {
1011 CreateTreeReadItemDirective(item);
1012 return true;
1013 }
1014 else
1015 if( *itext )
1016 {
1017 CreateTreeReadItemText(item);
1018 return true;
1019 }
1020 }
1021
1022 // the end of the string
1023 return false;
1024 }
1025
1026
1027
1028
1029
1030 void PatternParser::CreateTreeReadInclude(Item & item)
1031 {
1032 if( !allow_include )
1033 return;
1034
1035 CreateTreeReadIncludeSkipAllowFlag(item);
1036 }
1037
1038
1039
1040
1041 void PatternParser::CreateTreeReadIncludeSkipAllowFlag(Item & item)
1042 {
1043 if( item.file_name.empty() )
1044 return;
1045
1046 if( include_level > include_level_max )
1047 {
1048 #ifdef EZC_USE_WINIX_LOGGER
1049 Winix::log << Winix::log1 << "Ezc: \"include\" directive has reached the maximum level" << Winix::logend;
1050 #endif
1051
1052 return;
1053 }
1054
1055 ++include_level;
1056 std::wstring file_text; // this temporary object must not be global (includes can be nested)
1057 ReadFile(item.file_name, file_text);
1058
1059 const wchar_t * itext_old = itext;
1060 itext = file_text.c_str();
1061
1062 item.Clear();
1063 CreateTreeContainer(item);
1064
1065 itext = itext_old;
1066 --include_level;
1067 }
1068
1069
1070
1071 void PatternParser::CreateTreeReadIf(Item & item)
1072 {
1073 Item * pitem = item.AddItem();
1074 pitem->Clear();
1075
1076 if( program_mode )
1077 CreateTree(*pitem);
1078 else
1079 CreateTreeContainer(*pitem);
1080
1081 if( program_mode )
1082 {
1083 SkipWhite();
1084
1085 if( PT::IsSubStringNoCasep(L"else", itext) )
1086 {
1087 itext += 4;
1088 pitem = item.AddItem();
1089 CreateTree(*pitem);
1090 }
1091 }
1092 else
1093 {
1094 if( pitem->LastItemType() == Item::item_else )
1095 {
1096 pitem->DeleteLastItem();
1097
1098 pitem = item.AddItem();
1099 CreateTreeContainer(*pitem);
1100 }
1101 }
1102
1103 if( pitem->LastItemType() == Item::item_end )
1104 pitem->DeleteLastItem();
1105 }
1106
1107
1108
1109 void PatternParser::CreateTreeReadBlock(Item & item)
1110 {
1111 Item item_block;
1112
1113 CreateTreeContainer(item_block);
1114
1115 if( item_block.LastItemType() == Item::item_end )
1116 item_block.DeleteLastItem();
1117
1118 //if( pblocks && item.functions.size()==1 )
1119 if( pblocks )
1120 pblocks->Insert(item.function.name, item_block);
1121 }
1122
1123
1124
1125 void PatternParser::CreateTreeReadFor(Item & item)
1126 {
1127 Item * pitem = item.AddItem();
1128
1129 if( program_mode )
1130 CreateTree(*pitem);
1131 else
1132 CreateTreeContainer(*pitem);
1133
1134 if( pitem->LastItemType() == Item::item_end )
1135 pitem->DeleteLastItem();
1136 }
1137
1138
1139
1140 bool PatternParser::CreateTree(Item & item)
1141 {
1142 do
1143 {
1144 if( !CreateTreeReadItem(item) )
1145 {
1146 return false;
1147 }
1148
1149 if( item.type == Item::item_block )
1150 CreateTreeReadBlock(item);
1151 }
1152 while( item.type == Item::item_comment || item.type == Item::item_block );
1153
1154 // such container can be read in program mode
1155 if( item.type == Item::item_container )
1156 CreateTreeContainer(item);
1157
1158 if( item.type == Item::item_if )
1159 CreateTreeReadIf(item);
1160
1161 // CHECK ME is it correct to check item_filter and item_ezc here and call CreateTreeReadFor?
1162 if( item.type == Item::item_for ||
1163 item.type == Item::item_filter ||
1164 item.type == Item::item_ezc )
1165 CreateTreeReadFor(item);
1166
1167 if( item.type == Item::item_include )
1168 CreateTreeReadInclude(item);
1169
1170 return true;
1171 }
1172
1173
1174 void PatternParser::CreateTreeContainer(Item & item)
1175 {
1176 bool item_read_correctly;
1177 Item * pitem;
1178
1179 item.type = Item::item_container;
1180
1181 do
1182 {
1183 pitem = item.AddItem();
1184 item_read_correctly = CreateTree(*pitem);
1185 }
1186 while( item_read_correctly && pitem->type != Item::item_end && pitem->type != Item::item_else);
1187
1188 if( !item_read_correctly )
1189 item.DeleteLastItem();
1190 }
1191
1192
1193
1194
1195
1196 } // namespace Ezc
1197
1198
1199

svnadmin@ttmath.org
ViewVC Help
Powered by ViewVC 1.2.1