@@ -519,6 +519,7 @@ String expand_keywords(const String& tagged_str, vector<KeywordMatch> const& mat
519
519
skip_tags_for_keyword (false , true );
520
520
if (it == end) break ;
521
521
// is there a match here?
522
+ if (atom == 0 ) // don't expand keywords that are inside <atom> tags
522
523
while (match_it != matches.end () && match_it->pos <= untagged_pos) {
523
524
if (match_it->pos > untagged_pos) {
524
525
++match_it;
@@ -553,7 +554,7 @@ String expand_keywords(const String& tagged_str, vector<KeywordMatch> const& mat
553
554
// * Whether the case matches
554
555
// Add these things to the context
555
556
// Return iterator after the whole match
556
- String::const_iterator keyword_match_detail (String::const_iterator it, String::const_iterator end, KeywordMatch const & kw_match, Context& ctx) {
557
+ tuple< bool , String::const_iterator> keyword_match_detail (String::const_iterator it, String::const_iterator end, KeywordMatch const & kw_match, Context& ctx) {
557
558
Keyword const & keyword = *kw_match.keyword ;
558
559
Regex::Results const & match = kw_match.match ;
559
560
@@ -563,6 +564,9 @@ String::const_iterator keyword_match_detail(String::const_iterator it, String::c
563
564
bool correct_case = true ;
564
565
String::const_iterator match_str_it = keyword.match .begin ();
565
566
567
+ // in tags?
568
+ int atom = 0 ;
569
+
566
570
// Combined tagged match string
567
571
String total;
568
572
@@ -583,7 +587,8 @@ String::const_iterator keyword_match_detail(String::const_iterator it, String::c
583
587
// we start counting at 1, so
584
588
// sub = 1 mod 2 -> text
585
589
// sub = 0 mod 2 -> parameter
586
- if ((sub % 2 ) == 0 ) {
590
+ bool is_parameter = (sub % 2 ) == 0 ;
591
+ if (is_parameter) {
587
592
// parameter
588
593
KeywordParam& kwp = *keyword.parameters [(sub - 2 ) / 2 ];
589
594
String param = match.str (sub); // untagged version
@@ -643,7 +648,8 @@ String::const_iterator keyword_match_detail(String::const_iterator it, String::c
643
648
ctx.setVariable (String (_ (" param" )) << (int )(sub / 2 ), script_param);
644
649
645
650
} else {
646
- // Plain text, check if the case matches
651
+ // Plain text with exact match
652
+ // check if the case matches
647
653
if (correct_case) {
648
654
while (it != part_end) {
649
655
it = skip_all_tags (it, part_end);
@@ -664,17 +670,31 @@ String::const_iterator keyword_match_detail(String::const_iterator it, String::c
664
670
}
665
671
}
666
672
}
673
+ // count <atom> tags
674
+ for (String::const_iterator pit = part.begin (); pit != part.end ();) {
675
+ if (*pit == ' <' ) {
676
+ if (is_tag (pit, part.end (), " <atom" )) atom++;
677
+ else if (is_tag (pit, part.end (), " </atom" )) atom--;
678
+ pit = skip_tag (pit, part.end ());
679
+ } else {
680
+ if (atom > 0 && !is_parameter) {
681
+ // the fixed parts of a keyword should not be in atom tags
682
+ return {false ,it};
683
+ }
684
+ ++pit;
685
+ }
686
+ }
667
687
// build total match
668
688
total += part;
669
689
// next part starts after this
670
690
it = part_end;
671
691
}
672
- assert_tagged (total);
692
+ assert_tagged (total, false ); // note: tags might not be entirely balanced
673
693
ctx.setVariable (_ (" keyword" ), to_script (total));
674
694
ctx.setVariable (_ (" mode" ), to_script (keyword.mode ));
675
695
ctx.setVariable (_ (" correct_case" ), to_script (correct_case));
676
696
ctx.setVariable (_ (" used_placeholders" ), to_script (used_placeholders));
677
- return it ;
697
+ return { true , it} ;
678
698
};
679
699
680
700
// expand a keyword that matches at it
@@ -686,7 +706,8 @@ tuple<bool, String::const_iterator> expand_keyword(String::const_iterator it, St
686
706
LocalScope scope (ctx);
687
707
688
708
// Get details of the match
689
- String::const_iterator after = keyword_match_detail (it, end, kw_match, ctx);
709
+ auto [ok, after] = keyword_match_detail (it, end, kw_match, ctx);
710
+ if (!ok) return {false ,it};
690
711
691
712
// Final check whether the keyword matches
692
713
if (options.match_condition && options.match_condition ->eval (ctx)->toBool () == false ) {
0 commit comments