#define ONIG_SYN_OP2_ESC_H_XDIGIT (1U<<19) /* \h, \H */
#define ONIG_SYN_OP2_INEFFECTIVE_ESCAPE (1U<<20) /* \ */
#define ONIG_SYN_OP2_QMARK_LPAREN_IF_ELSE (1U<<21) /* (?(n)) (?(...)...|...) */
-#define ONIG_SYN_OP2_ESC_CAPITAL_R_GENERAL_NEWLINE (1U<<22) /* \R \r\n else [\x0a-\x0d] */
-#define ONIG_SYN_OP2_ESC_CAPITAL_N_NO_NEWLINE (1U<<23) /* \N [^\n] */
+#define ONIG_SYN_OP2_ESC_CAPITAL_K_KEEP (1U<<22) /* \K */
+#define ONIG_SYN_OP2_ESC_CAPITAL_R_GENERAL_NEWLINE (1U<<23) /* \R \r\n else [\x0a-\x0d] */
+#define ONIG_SYN_OP2_ESC_CAPITAL_N_NO_NEWLINE (1U<<24) /* \N [^\n] */
/* syntax (behavior) */
#define ONIG_SYN_CONTEXT_INDEP_ANCHORS (1U<<31) /* not implemented */
ONIG_SYN_OP2_QMARK_LPAREN_IF_ELSE |
ONIG_SYN_OP2_ESC_CAPITAL_R_GENERAL_NEWLINE |
ONIG_SYN_OP2_ESC_CAPITAL_N_NO_NEWLINE |
+ ONIG_SYN_OP2_ESC_CAPITAL_K_KEEP |
ONIG_SYN_OP2_ESC_G_SUBEXP_CALL |
ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY |
ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT |
}
#endif
+static int
+save_entry(ScanEnv* env, enum SaveType type, int* id)
+{
+ int nid = env->save_num;
+
+ if (IS_NULL(env->saves)) {
+ int n = 10;
+ env->saves = (SaveItem* )xmalloc(sizeof(SaveItem) * n);
+ CHECK_NULL_RETURN_MEMERR(env->saves);
+ env->save_alloc_num = n;
+ }
+ else if (env->save_alloc_num <= nid) {
+ int n = env->save_alloc_num * 2;
+ SaveItem* p = (SaveItem* )xrealloc(env->saves, sizeof(SaveItem) * n);
+ CHECK_NULL_RETURN_MEMERR(p);
+ env->saves = p;
+ env->save_alloc_num = n;
+ }
+
+ env->saves[nid].type = type;
+
+ env->save_num++;
+ *id = nid;
+ return 0;
+}
+
/* scan pattern methods */
#define PEND_VALUE 0
env->has_recursion = 0;
#endif
env->parse_depth = 0;
+ env->save_num = 0;
+ env->save_alloc_num = 0;
+ env->saves = 0;
}
static int
return node;
}
+static int
+node_new_keep(Node** node, ScanEnv* env)
+{
+ int id;
+ int r;
+
+ *node = 0;
+ r = save_entry(env, SAVE_KEEP, &id);
+ if (r != ONIG_NORMAL) return r;
+
+ *node = node_new();
+ CHECK_NULL_RETURN_MEMERR(*node);
+
+ NODE_SET_TYPE(*node, NODE_GIMMICK);
+ GIMMICK_(*node)->id = id;
+ GIMMICK_(*node)->type = SAVE_KEEP;
+ return ONIG_NORMAL;
+}
+
extern int
onig_node_str_cat(Node* node, const UChar* s, const UChar* end)
{
{
switch (NODE_TYPE(node)) {
case NODE_ANCHOR:
+ case NODE_GIMMICK:
return 1;
break;
TK_CC_OPEN,
TK_QUOTE_OPEN,
TK_CHAR_PROPERTY, /* \p{...}, \P{...} */
+ TK_KEEP, /* \K */
TK_GENERAL_NEWLINE, /* \R */
TK_NO_NEWLINE, /* \N */
tok->u.prop.not = 1;
break;
+ case 'K':
+ if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_CAPITAL_K_KEEP)) break;
+ tok->type = TK_KEEP;
+ break;
+
case 'R':
if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_CAPITAL_R_GENERAL_NEWLINE)) break;
tok->type = TK_GENERAL_NEWLINE;
}
break;
+ case TK_KEEP:
+ r = node_new_keep(np, env);
+ if (r < 0) return r;
+ break;
+
case TK_GENERAL_NEWLINE:
r = node_new_general_newline(np, env);
if (r < 0) return r;
ONIG_SYN_OP2_QMARK_LPAREN_IF_ELSE |
ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY |
ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT |
+ ONIG_SYN_OP2_ESC_CAPITAL_K_KEEP |
ONIG_SYN_OP2_ESC_CAPITAL_R_GENERAL_NEWLINE |
ONIG_SYN_OP2_ESC_CAPITAL_N_NO_NEWLINE )
, SYN_GNU_REGEX_BV
ONIG_SYN_OP2_QMARK_LT_NAMED_GROUP |
ONIG_SYN_OP2_ESC_K_NAMED_BACKREF |
ONIG_SYN_OP2_ESC_G_SUBEXP_CALL |
+ ONIG_SYN_OP2_ESC_CAPITAL_K_KEEP |
ONIG_SYN_OP2_ESC_CAPITAL_R_GENERAL_NEWLINE |
ONIG_SYN_OP2_ESC_CAPITAL_N_NO_NEWLINE )
, ( SYN_GNU_REGEX_BV |