Jelajahi Sumber

Added a new pattern like the lua "%bxy" but here it is "\mxy" where x and y are two distinct characters; such item matches strings that start with x, end with y, and where the x and y are balanced. This means that, if one reads the string from left to right, counting +1 for an x and -1 for a y, the ending y is the first y where the count reaches 0. For instance, the item \m() matches expressions with balanced parentheses.

mingodad 13 tahun lalu
induk
melakukan
1e5275be20
1 mengubah file dengan 33 tambahan dan 2 penghapusan
  1. 33 2
      sqstdlib/sqstdrex.cpp

+ 33 - 2
sqstdlib/sqstdrex.cpp

@@ -19,7 +19,7 @@ static const SQChar *g_nnames[] =
 	_SC("NONE"),_SC("OP_GREEDY"),	_SC("OP_OR"),
 	_SC("OP_EXPR"),_SC("OP_NOCAPEXPR"),_SC("OP_DOT"),	_SC("OP_CLASS"),
 	_SC("OP_CCLASS"),_SC("OP_NCLASS"),_SC("OP_RANGE"),_SC("OP_CHAR"),
-	_SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB")
+	_SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB"),_C("OP_MB")
 };
 
 #endif
@@ -37,6 +37,7 @@ static const SQChar *g_nnames[] =
 #define OP_EOL			(MAX_CHAR+11)
 #define OP_BOL			(MAX_CHAR+12)
 #define OP_WB			(MAX_CHAR+13)
+#define OP_MB           (MAX_CHAR+14) //match balanced
 
 #define SQREX_SYMBOL_ANY_CHAR ('.')
 #define SQREX_SYMBOL_GREEDY_ONE_OR_MORE ('+')
@@ -145,7 +146,20 @@ static SQInteger sqstd_rex_charnode(SQRex *exp,SQBool isclass)
 				t = *exp->_p; exp->_p++; 
 				return sqstd_rex_charclass(exp,t);
 				}
-			case 'b': 
+            case 'm':
+                {
+                     SQChar cb, ce; //cb = character begin match ce = character end match
+                     cb = *++exp->_p; //skip 'm'
+                     ce = *++exp->_p;
+                     exp->_p++; //points to the next char to be parsed
+                     if ((!cb) || (!ce)) sqstd_rex_error(exp,_SC("balanced chars expected"));
+                     if ( cb == ce ) sqstd_rex_error(exp,_SC("open/close char can't be the same"));
+                     SQInteger node =  sqstd_rex_newnode(exp,OP_MB);
+                     exp->_nodes[node].left = cb;
+                     exp->_nodes[node].right = ce;
+                     return node;
+                }
+			case 'b':
 			case 'B':
 				if(!isclass) {
 					SQInteger node = sqstd_rex_newnode(exp,OP_WB);
@@ -512,6 +526,23 @@ static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar
 			return str;
 		}
 		return NULL;
+    case OP_MB:
+        {
+            int cb = node->left; //char that opens a balanced expression
+            if(*str != cb) return NULL; // string doesnt start with open char
+            int ce = node->right; //char that closes a balanced expression
+            int cont = 1;
+            const SQChar *strEol = exp->_eol;
+            while (++str < strEol) {
+              if (*str == ce) {
+                if (--cont == 0) {
+                    return ++str;
+                }
+              }
+              else if (*str == cb) cont++;
+            }
+        }
+        return NULL; // string ends out of balance
 	default: /* char */
 		if(*str != node->type) return NULL;
 		str++;