Skip to content

Commit

Permalink
v.0.5.1 (lazy optimisation)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nikos M committed Nov 23, 2016
1 parent 78ff30b commit 37c615d
Show file tree
Hide file tree
Showing 7 changed files with 196 additions and 90 deletions.
90 changes: 67 additions & 23 deletions src/js/RegexAnalyzer.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
*
* RegexAnalyzer
* @version: 0.5.0
* @version: 0.5.1
*
* A simple Regular Expression Analyzer for PHP, Python, Node/XPCOM/JS, ActionScript
* https://github.com/foo123/RegexAnalyzer
Expand All @@ -23,7 +23,7 @@ else if ( !(name in root) ) /* Browser/WebWorker/.. */
/* module name */ "RegexAnalyzer",
/* module factory */ function ModuleFactory__RegexAnalyzer( undef ){
"use strict";
var __version__ = "0.5.0",
var __version__ = "0.5.1",

PROTO = 'prototype', Obj = Object, Arr = Array, /*Str = String,*/
Keys = Obj.keys, to_string = Obj[PROTO].toString,
Expand Down Expand Up @@ -90,6 +90,12 @@ var __version__ = "0.5.0",
T_SPECIAL = 7, T_CHARGROUP = 8, T_CHARS = 9,
T_CHARRANGE = 10, T_STRING = 11;

function clone( obj, cloned )
{
cloned = cloned || {};
for (var p in obj) if ( obj[HAS](p) ) cloned[p] = obj[p];
return cloned;
}
var RE_OBJ = function( re ) {
var self = this;
self.re = re;
Expand Down Expand Up @@ -1114,12 +1120,27 @@ RegexAnalyzer[PROTO] = {
ast: null,
re: null,
fl: null,
min: null,
max: null,
ch: null,

dispose: function( ) {
var self = this;
self.ast = null;
self.re = null;
self.fl = null;
self.min = null;
self.max = null;
self.ch = null;
return self;
},

reset: function( ) {
var self = this;
self.ast = null;
self.min = null;
self.max = null;
self.ch = null;
return self;
},

Expand Down Expand Up @@ -1150,8 +1171,8 @@ RegexAnalyzer[PROTO] = {
re = '';
}

// re is different, reset the ast
if ( self.re !== re ) self.ast = null;
// re is different, reset the ast, etc
if ( self.re !== re ) self.reset();
self.re = re; self.fl = fl;
}
return self;
Expand Down Expand Up @@ -1202,37 +1223,60 @@ RegexAnalyzer[PROTO] = {
minimum: function( ) {
var self = this, state;
if ( null == self.re ) return 0;
if ( null === self.ast ) self.analyze( );
state = {
map : map_min,
reduce : reduce_len
};
return walk(0, self.ast, state)|0;
if ( null === self.ast )
{
self.analyze( );
self.min = null;
}
if ( null === self.min )
{
state = {
map : map_min,
reduce : reduce_len
};
self.min = walk(0, self.ast, state)|0;
}
return self.min;
},

// experimental feature
maximum: function( ) {
var self = this, state;
if ( null == self.re ) return 0;
if ( null === self.ast ) self.analyze( );
state = {
map : map_max,
reduce : reduce_len
};
return walk(0, self.ast, state);
if ( null === self.ast )
{
self.analyze( );
self.max = null;
}
if ( null === self.max )
{
state = {
map : map_max,
reduce : reduce_len
};
self.max = walk(0, self.ast, state);
}
return self.max;
},

// experimental feature
peek: function( ) {
var self = this, state, isCaseInsensitive, peek, n, c, p, cases;
if ( null == self.re ) return null;
if ( null === self.ast ) self.analyze( );
state = {
map : map_1st,
reduce : reduce_peek
};
peek = walk({positive:{},negative:{}}, self.ast, state);

if ( null === self.ast )
{
self.analyze( );
self.ch = null;
}
if ( null === self.ch )
{
state = {
map : map_1st,
reduce : reduce_peek
};
self.ch = walk({positive:{},negative:{}}, self.ast, state);
}
peek = {positive:clone(self.ch.positive), negative:clone(self.ch.negative)};
isCaseInsensitive = null != self.fl.i;
for (n in peek)
{
Expand Down
4 changes: 2 additions & 2 deletions src/js/RegexAnalyzer.min.js

Large diffs are not rendered by default.

84 changes: 61 additions & 23 deletions src/php/RegexAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/**
*
* RegexAnalyzer
* @version: 0.5.0
* @version: 0.5.1
*
* A simple Regular Expression Analyzer for PHP, Python, Node/XPCOM/JS, ActionScript
* https://github.com/foo123/RegexAnalyzer
Expand Down Expand Up @@ -102,7 +102,7 @@ public function toObject( )

class RegexAnalyzer
{
const VERSION = "0.5.0";
const VERSION = "0.5.1";
const T_SEQUENCE = 1;
const T_ALTERNATION = 2;
const T_GROUP = 3;
Expand Down Expand Up @@ -1175,6 +1175,9 @@ private static function analyze_re( &$re_obj )
public $ast = null;
public $re = null;
public $fl = null;
public $min = null;
public $max = null;
public $ch = null;

public function __construct( $re=null, $delim=null )
{
Expand All @@ -1186,9 +1189,21 @@ public function dispose( )
$this->ast = null;
$this->re = null;
$this->fl = null;
$this->min = null;
$this->max = null;
$this->ch = null;
return $this;
}

public function reset()
{
$this->ast = null;
$this->min = null;
$this->max = null;
$this->ch = null;
return $this;
}

public function set($re, $delim=null)
{
if ( $re )
Expand Down Expand Up @@ -1217,8 +1232,8 @@ public function set($re, $delim=null)
$re = '';
}

// re is different, reset the ast
if ( $this->re !== $re ) $this->ast = null;
// re is different, reset the ast, etc
if ( $this->re !== $re ) $this->reset();
$this->re = $re; $this->fl = $fl;
}
return $this;
Expand Down Expand Up @@ -1269,37 +1284,60 @@ public function sample( $maxlen=1, $numsamples=1 )
public function minimum( )
{
if ( null == $this->re ) return 0;
if ( null === $this->ast ) $this->analyze( );
$state = (object)array(
'map' => array(__CLASS__, 'map_min'),
'reduce' => array(__CLASS__, 'reduce_len')
);
return (int)self::walk(0, $this->ast, $state);
if ( null === $this->ast )
{
$this->analyze( );
$this->min = null;
}
if ( null === $this->min )
{
$state = (object)array(
'map' => array(__CLASS__, 'map_min'),
'reduce' => array(__CLASS__, 'reduce_len')
);
$this->min = (int)self::walk(0, $this->ast, $state);
}
return $this->min;
}

// experimental feature
public function maximum( )
{
if ( null == $this->re ) return 0;
if ( null === $this->ast ) $this->analyze( );
$state = (object)array(
'map' => array(__CLASS__, 'map_max'),
'reduce' => array(__CLASS__, 'reduce_len')
);
return self::walk(0, $this->ast, $state);
if ( null === $this->ast )
{
$this->analyze( );
$this->max = null;
}
if ( null === $this->max )
{
$state = (object)array(
'map' => array(__CLASS__, 'map_max'),
'reduce' => array(__CLASS__, 'reduce_len')
);
$this->max = self::walk(0, $this->ast, $state);
}
return $this->max;
}

// experimental feature
public function peek( )
{
if ( null == $this->re ) return null;
if ( null === $this->ast ) $this->analyze( );
$state = (object)array(
'map' => array(__CLASS__, 'map_1st'),
'reduce' => array(__CLASS__, 'reduce_peek')
);
$peek = self::walk(array('positive'=>array(),'negative'=>array()), $this->ast, $state);

if ( null === $this->ast )
{
$this->analyze( );
$this->ch = null;
}
if ( null === $this->ch )
{
$state = (object)array(
'map' => array(__CLASS__, 'map_1st'),
'reduce' => array(__CLASS__, 'reduce_peek')
);
$this->ch = self::walk(array('positive'=>array(),'negative'=>array()), $this->ast, $state);
}
$peek = array('positive'=>array_merge(array(),$this->ch['positive']), 'negative'=>array_merge(array(),$this->ch['negative']));
$isCaseInsensitive = !empty($this->fl['i']);
foreach ($peek as $n=>$p)
{
Expand Down
Loading

0 comments on commit 37c615d

Please sign in to comment.