23
23
** Module: u-parse.c
24
24
** Summary: parse dialect interpreter
25
25
** Section: utility
26
- ** Author: Carl Sassenrath
26
+ ** Author: Carl Sassenrath, Oldes
27
27
** Notes:
28
28
**
29
29
***********************************************************************/
@@ -41,6 +41,7 @@ typedef struct reb_parse_collect {
41
41
REBVAL * result ;
42
42
REBSER * block ;
43
43
REBINT depth ;
44
+ REBFLG flags ;
44
45
} REB_PARSE_COLLECT ;
45
46
46
47
typedef struct reb_parse {
@@ -70,6 +71,10 @@ enum parse_flags {
70
71
PF_PICK ,
71
72
};
72
73
74
+ enum collect_flags {
75
+ CF_ROOT_SET , // that the root collect block was SET to a word, so return parse's result (logic) instead
76
+ };
77
+
73
78
#define MAX_PARSE_DEPTH 512
74
79
75
80
// Returns SYMBOL or 0 if not a command:
@@ -777,6 +782,7 @@ void Print_Parse_Index(REBCNT type, REBVAL *rules, REBSER *series, REBCNT index)
777
782
REBFLG flags ;
778
783
REBCNT cmd ;
779
784
REBSER * blk ;
785
+ REB_PARSE_COLLECT * collect = parse -> collect ;
780
786
//REBVAL *rule_head = rules;
781
787
782
788
CHECK_STACK (& flags );
@@ -870,26 +876,46 @@ void Print_Parse_Index(REBCNT type, REBVAL *rules, REBSER *series, REBCNT index)
870
876
case SYM_COLLECT :
871
877
if (IS_END (rules ))
872
878
Trap1 (RE_PARSE_END , rules - 1 );
873
- //printf("COLLECT start %i\n", parse-> collect->depth);
879
+ //printf("COLLECT start %i\n", collect->depth);
874
880
// reserve a new value on stack
875
881
DS_PUSH_NONE ;
876
- if (parse -> collect -> block == NULL ) {
882
+
883
+ if (collect -> block == NULL ) {
877
884
// --- FIRST collect -------------------------
878
885
// allocate the resulting block on the stack, so it is GC safe
879
886
Set_Series (REB_BLOCK , DS_TOP , Make_Block (2 ));
880
- parse -> collect -> result = DS_TOP ;
881
- parse -> collect -> block = VAL_SERIES (DS_TOP );
887
+ collect -> result = DS_TOP ;
888
+ collect -> block = VAL_SERIES (DS_TOP );
882
889
} else {
883
890
// --- SUBSEQUENT collect ---------------------
884
891
// store current block on stack
885
- Set_Series (REB_BLOCK , DS_TOP , parse -> collect -> block );
892
+ Set_Series (REB_BLOCK , DS_TOP , collect -> block );
886
893
// do not allocate a new one, until it is needed, else
887
894
// there could be unwanted empty blocks like in case:
888
895
// parse [1][collect some [collect keep integer!]]
889
- parse -> collect -> block = NULL ;
896
+ collect -> block = NULL ;
890
897
}
891
898
SET_FLAG (flags , PF_COLLECT );
892
- parse -> collect -> depth ++ ;
899
+
900
+ if (IS_WORD (rules ) && VAL_SYM_CANON (rules ) == SYM_SET ) {
901
+ rules ++ ;
902
+ if (!(IS_WORD (rules ) || IS_SET_WORD (rules )))
903
+ Trap1 (RE_PARSE_VARIABLE , rules );
904
+ if (collect -> block == NULL ) {
905
+ // the block was not allocated yet, but we need it now!
906
+ val = Append_Value (VAL_SERIES (DS_TOP ));
907
+ Set_Series (REB_BLOCK , val , Make_Block (2 ));
908
+ // and mark it for use
909
+ collect -> block = VAL_SERIES (val );
910
+ }
911
+ if (collect -> depth == 0 ) {
912
+ SET_FLAG (collect -> flags , CF_ROOT_SET );
913
+ }
914
+
915
+ Set_Var_Series (rules , REB_BLOCK , collect -> block , 0 );
916
+ rules ++ ;
917
+ }
918
+ collect -> depth ++ ;
893
919
continue ;
894
920
895
921
case SYM_KEEP :
@@ -1086,7 +1112,7 @@ void Print_Parse_Index(REBCNT type, REBVAL *rules, REBSER *series, REBCNT index)
1086
1112
val = BLK_SKIP (series , index );
1087
1113
i = (
1088
1114
(ANY_BINSTR (val ) || ANY_BLOCK (val ))
1089
- && (Parse_Series (val , VAL_BLK_DATA (item ), parse -> flags , depth + 1 , & parse -> collect ) == VAL_TAIL (val ))
1115
+ && (Parse_Series (val , VAL_BLK_DATA (item ), parse -> flags , depth + 1 , & collect ) == VAL_TAIL (val ))
1090
1116
) ? index + 1 : NOT_FOUND ;
1091
1117
break ;
1092
1118
#ifdef USE_DO_PARSE_RULE
@@ -1216,7 +1242,7 @@ void Print_Parse_Index(REBCNT type, REBVAL *rules, REBSER *series, REBCNT index)
1216
1242
}
1217
1243
if (GET_FLAG (flags , PF_KEEP )) {
1218
1244
if (ser && GET_FLAG (flags , PF_COPY )) {
1219
- val = Append_Value (parse -> collect -> block );
1245
+ val = Append_Value (collect -> block );
1220
1246
if (IS_BLOCK_INPUT (parse )) {
1221
1247
Set_Block (val , ser );
1222
1248
}
@@ -1238,9 +1264,9 @@ void Print_Parse_Index(REBCNT type, REBVAL *rules, REBSER *series, REBCNT index)
1238
1264
// COLLECT ends
1239
1265
// get the previous target block from the stack and use it
1240
1266
val = DS_POP ;
1241
- parse -> collect -> block = VAL_SERIES (val );
1242
- parse -> collect -> depth -- ;
1243
- //printf("COLLECT done %i\n", parse-> collect->depth);
1267
+ collect -> block = VAL_SERIES (val );
1268
+ collect -> depth -- ;
1269
+ //printf("COLLECT done %i\n", collect->depth);
1244
1270
}
1245
1271
1246
1272
if (GET_FLAG (flags , PF_RETURN )) {
@@ -1512,12 +1538,10 @@ void Print_Parse_Index(REBCNT type, REBVAL *rules, REBSER *series, REBCNT index)
1512
1538
Throw_Error (VAL_ERR_OBJECT (DS_RETURN ));
1513
1539
}
1514
1540
SET_STATE (state , Saved_State );
1515
- collect .depth = 0 ;
1516
- collect .result = NULL ;
1517
- collect .block = NULL ;
1541
+ CLEARS (& collect );
1518
1542
1519
1543
n = Parse_Series (val , VAL_BLK_DATA (arg ), (opts & PF_CASE ) ? AM_FIND_CASE : 0 , 0 , & collect );
1520
- if (collect .result ) {
1544
+ if (collect .result && ! GET_FLAG ( collect . flags , CF_ROOT_SET ) ) {
1521
1545
* D_RET = * collect .result ;
1522
1546
}
1523
1547
else {
0 commit comments