]> granicus.if.org Git - onig/commitdiff
implement parsing part of \K
authorK.Kosako <kosako@sofnec.co.jp>
Mon, 10 Jul 2017 04:16:32 +0000 (13:16 +0900)
committerK.Kosako <kosako@sofnec.co.jp>
Mon, 10 Jul 2017 04:16:32 +0000 (13:16 +0900)
src/oniguruma.h
src/regparse.c
src/regparse.h
src/regsyntax.c

index 239dbbc4ed34b94164271c306cd2842e5418fe0e..f2507dfd23d8e1391ef7721391a277a96e3ce6cb 100644 (file)
@@ -497,8 +497,9 @@ ONIG_EXTERN OnigSyntaxType*   OnigDefaultSyntax;
 #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 */
index c0093b1faeeff01dc79c7c0a6de29e820077ffed..cd3a4cecfa0bb3a0fa3e1e797224cd2705f62daa 100644 (file)
@@ -51,6 +51,7 @@ OnigSyntaxType OnigSyntaxRuby = {
       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 |
@@ -307,6 +308,32 @@ strdup_with_null(OnigEncoding enc, UChar* s, UChar* end)
 }
 #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
 
@@ -1017,6 +1044,9 @@ scan_env_clear(ScanEnv* env)
   env->has_recursion       = 0;
 #endif
   env->parse_depth         = 0;
+  env->save_num            = 0;
+  env->save_alloc_num      = 0;
+  env->saves               = 0;
 }
 
 static int
@@ -1442,6 +1472,25 @@ node_new_option(OnigOptionType option)
   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)
 {
@@ -2155,6 +2204,7 @@ is_invalid_quantifier_target(Node* node)
 {
   switch (NODE_TYPE(node)) {
   case NODE_ANCHOR:
+  case NODE_GIMMICK:
     return 1;
     break;
 
@@ -2370,6 +2420,7 @@ enum TokenSyms {
   TK_CC_OPEN,
   TK_QUOTE_OPEN,
   TK_CHAR_PROPERTY,    /* \p{...}, \P{...} */
+  TK_KEEP,             /* \K */
   TK_GENERAL_NEWLINE,  /* \R */
   TK_NO_NEWLINE,       /* \N */
 
@@ -3519,6 +3570,11 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
       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;
@@ -5688,6 +5744,11 @@ parse_exp(Node** np, OnigToken* tok, int term,
     }
     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;
index 99900a889cf2652dc2d5770901def2ef9f9c9a8a..a508b4ff1dad262bf9df8e9e6f325ae4e81f6233 100644 (file)
@@ -351,6 +351,14 @@ typedef struct {
 #endif
 } MemEnv;
 
+enum SaveType {
+  SAVE_KEEP  = 0,
+};
+
+typedef struct {
+  enum SaveType type;
+} SaveItem;
+
 typedef struct {
   OnigOptionType   option;
   OnigCaseFoldType case_fold_flag;
@@ -384,6 +392,10 @@ typedef struct {
   int has_recursion;
 #endif
   unsigned int parse_depth;
+
+  int save_num;
+  int save_alloc_num;
+  SaveItem* saves;
 } ScanEnv;
 
 
index ba93691de46429dba8467e5d1c7e7f1f20a95a08..d05f97ddd9ccabeed095e98226549688cc0f6bfe 100644 (file)
@@ -177,6 +177,7 @@ OnigSyntaxType OnigSyntaxPerl = {
       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
@@ -208,6 +209,7 @@ OnigSyntaxType OnigSyntaxPerl_NG = {
       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 |