10
10
#include < cstring>
11
11
#include " parse_text.h"
12
12
#include " parsedef.h"
13
+ #include " tokencollisionhelper.h"
13
14
#include " dhelper.h"
14
15
#include " vhelper.h"
15
16
#include " analyse.h"
@@ -79,13 +80,28 @@ struct ParserBase {
79
80
return false ;
80
81
}
81
82
83
+ template <typename ParserBase>
84
+ static void init_collision_checker (ParserBase &base) {
85
+ ERROR (" shouldn't get here" );
86
+ }
82
87
#endif
83
88
84
89
template <typename Stream>
85
90
static void dumpJson (Stream &out, const AstType *ast) {
86
91
ERROR (" Not implemented\n " );
87
92
}
88
93
94
+ void init_collission_checker () {
95
+ TokenCollisionChecker *ptr = new TokenCollisionChecker ();
96
+ colission_checker_.reset ( ptr );
97
+ }
98
+
99
+
100
+
101
+ std::unique_ptr<TokenCollisionChecker> colission_checker_;
102
+
103
+
104
+ // must not be a polymorphic type, is accessed from static stuff only. don't have virtual functions here.
89
105
// virtual ~ParserBase() {}
90
106
};
91
107
@@ -150,18 +166,52 @@ struct CharParser : ParserBase {
150
166
static void dumpJson (Stream &out, const AstType *) {
151
167
}
152
168
169
+ template <typename ParserBase>
170
+ static void init_collision_checker (ParserBase &base) {
171
+ }
153
172
154
173
private:
155
174
Text_stream &text_;
156
175
Text_stream::Next_char_value ch_;
157
176
};
158
177
178
+
179
+
180
+ // PTopLevelParser - top level parser, initialises the collision checker;
181
+ // The collision checker is used to check that variables that have the string value of a token are not counted as a variable;
182
+ // the parse method initialises the collision checker and attaches it to the base parser, and after using it it is deleted.
183
+ //
184
+ template <typename Type>
185
+ struct PTopLevelParser : ParserBase {
186
+
187
+ using AstType = typename Type::AstType;
188
+ using ThisClass = PTopLevelParser<Type>;
189
+
190
+ template <typename ParserBase>
191
+ static Parse_result parse (ParserBase &base) {
192
+
193
+ PTopLevelParser<Type>::init_collision_checker (base);
194
+ // Type::init_collision_checker(base);
195
+ return Type::parse (base);
196
+ }
197
+
198
+ template <typename ParserBase>
199
+ static void init_collision_checker (ParserBase &base) {
200
+
201
+ base.init_collission_checker ();
202
+ if (base.colission_checker_ ->insert_type_info (&typeid (ThisClass))) {
203
+ Type::init_collision_checker (base);
204
+ base.colission_checker_ ->remove_type_info (&typeid (ThisClass));
205
+ }
206
+ }
207
+ };
208
+
159
209
//
160
210
// PEof - parse is ok if at end of input
161
211
//
162
212
163
213
template <typename Type>
164
- struct PRequireEof : ParserBase {
214
+ struct PRequireEof : PTopLevelParser<Type> {
165
215
166
216
static inline const RuleId RULE_ID = Type::RULE_ID;
167
217
@@ -170,12 +220,12 @@ struct PRequireEof : ParserBase {
170
220
template <typename ParserBase>
171
221
static Parse_result parse (ParserBase &base) {
172
222
173
- Parse_result res = Type::parse (base);
223
+ Parse_result res = PTopLevelParser< Type> ::parse (base);
174
224
if (!res.success_ ) {
175
225
return res;
176
226
}
177
227
178
- Char_value nchar = ParserBase::current_char (base);
228
+ typename ParserBase:: Char_value nchar = ParserBase::current_char (base);
179
229
while (nchar.first && isspace (nchar.second )) {
180
230
ParserBase::next_char (base);
181
231
nchar = ParserBase::current_char (base);
@@ -326,6 +376,13 @@ struct PTok : ParserBase {
326
376
}
327
377
328
378
379
+ template <typename ParserBase>
380
+ static void init_collision_checker (ParserBase &base) {
381
+ std::string sval;
382
+ gather_token_value<Cs...>(sval);
383
+ base.colission_checker_ ->insert (sval.c_str (), sval.size () );
384
+ }
385
+
329
386
private:
330
387
template <typename ParserBase, Char_t ch, Char_t ...Css>
331
388
static inline bool parse_helper ( ParserBase &text ) {
@@ -354,6 +411,17 @@ struct PTok : ParserBase {
354
411
return true ;
355
412
}
356
413
414
+ template <Char_t ch, Char_t ...Css>
415
+ static inline bool gather_token_value (std::string &strval) {
416
+
417
+ strval += ch;
418
+
419
+ if constexpr (sizeof ...(Css) > 0 ) {
420
+ return dump_helper<Css...>( strval );
421
+ }
422
+
423
+ return true ;
424
+ }
357
425
358
426
359
427
};
@@ -372,10 +440,13 @@ enum class Char_checker_result {
372
440
typedef Char_checker_result (PTokVar_cb_t) (Char_t current_char, bool iseof, Char_t *matched_so_far);
373
441
374
442
375
- template <RuleId ruleId, PTokVar_cb_t checker, bool canAcceptEmptyInput = false >
443
+ const int PTokVarCanAcceptEmptyInput = 1 ;
444
+ const int PTokVarCheckTokenClash = 2 ;
445
+
446
+ template <RuleId ruleId, PTokVar_cb_t checker, int TokVarFlags = 0 >
376
447
struct PTokVar : ParserBase {
377
448
378
- using ThisClass = PTokVar<ruleId, checker, canAcceptEmptyInput >;
449
+ using ThisClass = PTokVar<ruleId, checker, TokVarFlags >;
379
450
380
451
static inline const RuleId RULE_ID = ruleId;
381
452
@@ -421,7 +492,11 @@ struct PTokVar : ParserBase {
421
492
AstEntryBase *ret = ast.release ();
422
493
ret->start_ = token_start_pos;
423
494
ret->end_ = end_pos;
424
- return Parse_result{true , token_start_pos, end_pos, std::unique_ptr<AstEntryBase>(ret) };
495
+
496
+ if (has_collision (base, ast.get ()->entry_ )) {
497
+ return Parse_result{false , token_start_pos, token_start_pos};
498
+ }
499
+ return Parse_result{true , token_start_pos, end_pos, std::unique_ptr<AstEntryBase>(ret) };
425
500
426
501
}
427
502
@@ -432,7 +507,11 @@ struct PTokVar : ParserBase {
432
507
AstEntryBase *ret = ast.release ();
433
508
ret->start_ = token_start_pos;
434
509
ret->end_ = end_pos;
435
- return Parse_result{true , token_start_pos, end_pos, std::unique_ptr<AstEntryBase>(ret) };
510
+
511
+ if (has_collision (base, ast.get ()->entry_ )) {
512
+ return Parse_result{false , token_start_pos, token_start_pos};
513
+ }
514
+ return Parse_result{true , token_start_pos, end_pos, std::unique_ptr<AstEntryBase>(ret) };
436
515
}
437
516
438
517
}
@@ -460,7 +539,7 @@ struct PTokVar : ParserBase {
460
539
461
540
template <typename HelperType>
462
541
static bool can_accept_empty_input (HelperType *) {
463
- return canAcceptEmptyInput ;
542
+ return TokVarFlags & PTokVarCanAcceptEmptyInput ;
464
543
}
465
544
466
545
#endif
@@ -475,6 +554,24 @@ struct PTokVar : ParserBase {
475
554
Json<Stream>::jsonEndTag (out, true );
476
555
}
477
556
557
+ template <typename ParserBase>
558
+ static void init_collision_checker (ParserBase &base) {
559
+ }
560
+
561
+ inline static bool has_collision (ParserBase &base, std::string &entry) {
562
+
563
+ if constexpr ((TokVarFlags & PTokVarCheckTokenClash) != 0 ) {
564
+ if (base.colission_checker_ != nullptr ) {
565
+
566
+ const Char_t *tok = (const Char_t *) entry.c_str ();
567
+ int len = entry.size ();
568
+
569
+ return base.colission_checker_ ->has_token (tok, len);
570
+ }
571
+ }
572
+ return false ;
573
+ }
574
+
478
575
};
479
576
480
577
inline Char_checker_result pparse_is_digit (Char_t current_char, bool iseof, Char_t *matched_so_far) {
@@ -504,7 +601,29 @@ inline Char_checker_result parse_print_char(Char_t current_char, bool iseof, Cha
504
601
// PTokPrintChar - single printable character
505
602
//
506
603
template <RuleId ruleId>
507
- struct PTokChar : PTokVar<ruleId,parse_print_char> {
604
+ struct PTokChar : PTokVar<ruleId,parse_print_char, PTokVarCheckTokenClash> {
605
+ };
606
+
607
+ inline Char_checker_result pparse_identifier (Char_t current_char, bool iseof, Char_t *matched_so_far) {
608
+
609
+ ssize_t slen = strlen (matched_so_far);
610
+ if (iseof) {
611
+ if (slen >0 ) {
612
+ return Char_checker_result::acceptNow;
613
+ }
614
+ }
615
+
616
+ if (slen == 0 ) {
617
+ return isalpha (current_char) ? Char_checker_result::proceed : Char_checker_result::error;
618
+ }
619
+ return isalnum (current_char) ? Char_checker_result::proceed : Char_checker_result::acceptUnget;
620
+ }
621
+
622
+ //
623
+ // PTokIdentifier
624
+ //
625
+ template <RuleId ruleId>
626
+ struct PTokIdentifier : PTokVar<ruleId, pparse_identifier> {
508
627
};
509
628
510
629
@@ -579,6 +698,16 @@ struct PAny : ParserBase {
579
698
Json<Stream>::jsonEndTag (out, true );
580
699
}
581
700
701
+ template <typename ParserBase>
702
+ static void init_collision_checker (ParserBase &base) {
703
+
704
+ if (base.colission_checker_ != nullptr && base.colission_checker_ ->insert_type_info (&typeid (ThisClass))) {
705
+ init_collision_checker_helper<ParserBase, Types...>(base);
706
+ base.colission_checker_ ->remove_type_info (&typeid (ThisClass));
707
+ }
708
+ }
709
+
710
+
582
711
583
712
private:
584
713
template <size_t FieldIndex, typename ParserBase, typename PType, typename ...PTypes>
@@ -674,6 +803,16 @@ struct PAny : ParserBase {
674
803
return true ;
675
804
}
676
805
806
+ template <typename ParserBase, typename PType, typename ...PTypes>
807
+ static void init_collision_checker_helper (ParserBase &base) {
808
+
809
+ PType::init_collision_checker (base);
810
+
811
+ if constexpr (sizeof ...(PTypes) > 0 ) {
812
+ return init_collision_checker_helper<ParserBase, PTypes...>( base );
813
+ }
814
+ }
815
+
677
816
};
678
817
679
818
//
@@ -762,6 +901,17 @@ struct POpt : ParserBase {
762
901
Json<Stream>::jsonEndTag (out, true );
763
902
}
764
903
904
+ template <typename ParserBase>
905
+ static void init_collision_checker (ParserBase &base) {
906
+ if (base.colission_checker_ != nullptr && base.colission_checker_ ->insert_type_info (&typeid (ThisClass))) {
907
+ PType::init_collision_checker (base);
908
+ base.colission_checker_ ->remove_type_info (&typeid (ThisClass));
909
+ }
910
+ }
911
+
912
+
913
+
914
+ private:
765
915
766
916
};
767
917
@@ -841,6 +991,16 @@ struct PSeq : ParserBase {
841
991
Json<Stream>::jsonEndTag (out, true );
842
992
}
843
993
994
+ template <typename ParserBase>
995
+ static void init_collision_checker (ParserBase &base) {
996
+ if (base.colission_checker_ != nullptr && base.colission_checker_ ->insert_type_info (&typeid (ThisClass))) {
997
+ init_collision_checker_helper<ParserBase, Types...>(base);
998
+ base.colission_checker_ ->remove_type_info (&typeid (ThisClass));
999
+ }
1000
+ }
1001
+
1002
+
1003
+
844
1004
private:
845
1005
846
1006
template <size_t FieldIndex, typename Stream, typename PType, typename ...PTypes>
@@ -922,6 +1082,16 @@ struct PSeq : ParserBase {
922
1082
}
923
1083
#endif
924
1084
1085
+ template <typename ParserBase, typename PType, typename ...PTypes>
1086
+ static void init_collision_checker_helper (ParserBase &base) {
1087
+
1088
+ PType::init_collision_checker (base);
1089
+
1090
+ if constexpr (sizeof ...(PTypes) > 0 ) {
1091
+ return init_collision_checker_helper<ParserBase, PTypes...>( base );
1092
+ }
1093
+ }
1094
+
925
1095
926
1096
};
927
1097
@@ -970,6 +1140,15 @@ struct PRepeat : ParserBase {
970
1140
Json<Stream>::jsonEndTag (out, true );
971
1141
}
972
1142
1143
+ template <typename ParserBase>
1144
+ static void init_collision_checker (ParserBase &base) {
1145
+
1146
+ if (base.colission_checker_ != nullptr && base.colission_checker_ ->insert_type_info (&typeid (ThisClass))) {
1147
+ Type::init_collision_checker (base);
1148
+ base.colission_checker_ ->remove_type_info (&typeid (ThisClass));
1149
+ }
1150
+ }
1151
+
973
1152
974
1153
private:
975
1154
template <typename ParserBase>
@@ -1156,6 +1335,16 @@ struct PWithAndLookaheadImpl : ParserBase {
1156
1335
Type::dumpJson (out, ast);
1157
1336
}
1158
1337
1338
+ template <typename ParserBase>
1339
+ static void init_collision_checker (ParserBase &base) {
1340
+
1341
+ if (base.colission_checker_ != nullptr && base.colission_checker_ ->insert_type_info (&typeid (ThisClass))) {
1342
+ Type::init_collision_checker (base);
1343
+ LookaheadType::init_collision_checker (base);
1344
+ base.colission_checker_ ->remove_type_info (&typeid (ThisClass));
1345
+ }
1346
+ }
1347
+
1159
1348
1160
1349
};
1161
1350
0 commit comments