Skip to content

Commit

Permalink
FIX: Parse rule fails when input is modified and so does not advance
Browse files Browse the repository at this point in the history
  • Loading branch information
Oldes committed Mar 26, 2021
1 parent e9b0bb1 commit 277ab51
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 18 deletions.
23 changes: 18 additions & 5 deletions src/core/u-parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ enum parse_flags {
PF_CHANGE,
PF_RETURN,
PF_WHILE,
PF_ADVANCE, // used to report that although index was not changed, rule is suppose to advance
};

#define MAX_PARSE_DEPTH 512
Expand Down Expand Up @@ -839,8 +840,8 @@ void Print_Parse_Index(REBCNT type, REBVAL *rules, REBSER *series, REBCNT index)
// #2269 - reset the position if we are not in the middle of any rule
// don't allow code like: [copy x :pos integer!]
if (flags != 0) Trap1(RE_PARSE_RULE, rules-1);
begin = index;

begin = index;
SET_FLAG(parse->flags, PF_ADVANCE);
continue;
}

Expand Down Expand Up @@ -978,10 +979,20 @@ void Print_Parse_Index(REBCNT type, REBVAL *rules, REBSER *series, REBCNT index)
if (i != NOT_FOUND) {
count++; // may overflow to negative
if (count < 0) count = MAX_I32; // the forever case

// If input did not advance:
if (i == index && !GET_FLAG(flags, PF_WHILE)) {
if (count < mincount) index = NOT_FOUND; // was not enough
break;
if (i == index) {
// check if there was processed some _modifying_ rule, which should advance
// even if index was not changed (https://github.com/Oldes/Rebol-issues/issues/2452)
if (GET_FLAG(parse->flags, PF_ADVANCE)) {
// clear the state in case, that there are other rules to be processed
// keep it in case that we were at the last one
if(count < maxcount) CLR_FLAG(parse->flags, PF_ADVANCE);
}
else if (!GET_FLAG(flags, PF_WHILE)) {
if (count < mincount) index = NOT_FOUND; // was not enough
break;
}
}
}
//if (i >= series->tail) { // OLD check: no more input
Expand Down Expand Up @@ -1058,6 +1069,7 @@ void Print_Parse_Index(REBCNT type, REBVAL *rules, REBSER *series, REBCNT index)
if (IS_PROTECT_SERIES(series)) Trap0(RE_PROTECTED);
Remove_Series(series, begin, count);
}
SET_FLAG(parse->flags, PF_ADVANCE);
index = begin;
}
if (flags & (1<<PF_INSERT | 1<<PF_CHANGE)) {
Expand Down Expand Up @@ -1090,6 +1102,7 @@ void Print_Parse_Index(REBCNT type, REBVAL *rules, REBSER *series, REBCNT index)
index = Modify_String(GET_FLAG(flags, PF_CHANGE) ? A_CHANGE : A_INSERT,
series, begin, item, cmd, count, 1);
}
SET_FLAG(parse->flags, PF_ADVANCE);
}
if (GET_FLAG(flags, PF_AND)) index = begin;
}
Expand Down
9 changes: 0 additions & 9 deletions src/tests/units/_known-issues_.r3
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,6 @@ Rebol [
===end-group===


===start-group=== "PARSE"
--test-- "parse remove"
--assert parse v: "yx" [some [remove #"y" | #"x"] ]
--assert v = "x"
--assert parse "yx" [copy v any [ remove #"y" | #"x" ] ]
--assert v = "x"
===end-group===


===start-group=== "TIME"
;@@ https://github.com/Oldes/Rebol-issues/issues/2416
--test-- "time protect 1"
Expand Down
21 changes: 17 additions & 4 deletions src/tests/units/parse-test.r3
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,23 @@ Rebol [

===start-group=== "REMOVE"
--test-- "remove"
;--assert parse v: "yx" [some [remove #"y" | #"x"] ]
;--assert v = "x"
;--assert parse "yx" [copy v any [ remove #"y" | #"x" ] ]
;--assert v = "x"
;@@ https://github.com/Oldes/Rebol-issues/issues/2452
--assert parse v: "yx" [some [remove #"y" | #"x"]]
--assert v = "x"
--assert parse "yx" [copy v any [ remove #"y" | #"x" ]]
--assert v = "x"
--assert parse v: "yx" [some [change #"y" "" | #"x"]]
--assert v = "x"
--assert parse v: "ab" [any [s: 1 skip e: (e: remove/part s e) :e | skip]]
--assert empty? v
; and also:
lr: [s: #L integer! e: (s: remove/part s 2) :s]
--assert parse v: [#L 1 "a" #L 2 "b"][some [lr | string!]]
--assert v = ["a" "b"]
--assert parse v: [#L 1 "a" #L 2 "b"][some [string! | lr]]
--assert v = ["a" "b"]

--test-- "while .. remove"
remove-any-y: [while [remove #"y" | #"x"]]
--assert parse v: "" remove-any-y
--assert parse v: "yx" remove-any-y
Expand Down

0 comments on commit 277ab51

Please sign in to comment.