+2004-03-17 Francois Beauchemin <beauche@softhome.net>
+ * syntax.cs, interpreter.cs, quicksearch.cs, regex.cs, compiler.cs :
+ Revised support for RigthToLeft.
+ quicksearch has now an reverse option.
+ This fixes bug #54537
+
+ * regex.cs, compiler.cs :
+ Some code to support CILCompiler.
+ * regex.cs :
+ Added some undocumented of MS.
+
2004-03-16 Gonzalo Paniagua Javier <gonzalo@ximian.com>
* parser.cs: allow a @"\0" escape sequence. Fixes bug #54797.
void EmitIn (LinkRef tail);\r
void EmitInfo (int count, int min, int max);\r
void EmitFastRepeat (int min, int max, bool lazy, LinkRef tail);\r
- void EmitAnchor (int offset, LinkRef tail);\r
+ void EmitAnchor (bool reverse, int offset, LinkRef tail);\r
+\r
+ // event for the CILCompiler\r
+ void EmitBranchEnd();\r
+ void EmitAlternationEnd();\r
\r
LinkRef NewLink ();\r
void ResolveLink (LinkRef link);\r
EmitLink (tail);\r
}\r
\r
- public void EmitAnchor (int offset, LinkRef tail) {\r
+ public void EmitAnchor (bool reverse, int offset, LinkRef tail) {\r
BeginLink (tail);\r
- Emit (OpCode.Anchor);\r
+ Emit (OpCode.Anchor, MakeFlags(false, false, reverse, false));\r
EmitLink (tail);\r
Emit ((ushort)offset);\r
}\r
pgm[stack.OffsetAddress] = (ushort)stack.GetOffset (CurrentAddress);\r
}\r
\r
+ public void EmitBranchEnd(){}\r
+ public void EmitAlternationEnd(){}\r
+\r
// private members\r
\r
private static OpFlags MakeFlags (bool negate, bool ignore, bool reverse, bool lazy) {\r
stack.Push ();\r
}\r
\r
+\r
private class PatternLinkStack : LinkStack {\r
public PatternLinkStack () {\r
}\r
\r
private Stack stack;\r
}\r
+\r
+ //Used by CILCompiler and Interpreter\r
+ internal struct Mark {\r
+ public int Start, End;\r
+ public int Previous;\r
+ \r
+ public bool IsDefined {\r
+ get { return Start >= 0 && End >= 0; }\r
+ }\r
+ \r
+ public int Index {\r
+ get { return Start < End ? Start : End; }\r
+ }\r
+ \r
+ public int Length {\r
+ get { return Start < End ? End - Start : Start - End; }\r
+ }\r
+ }\r
+\r
}\r
switch (op) {\r
case OpCode.Anchor: {\r
int skip = program[pc + 1];\r
-\r
+ \r
int anch_offset = program[pc + 2];\r
- int anch_ptr = ptr + anch_offset;\r
- int anch_end = text_end - match_min + anch_offset; // maximum anchor position\r
+ bool anch_reverse = (flags & OpFlags.RightToLeft) != 0; \r
+ int anch_ptr = anch_reverse ? ptr - anch_offset : ptr + anch_offset;\r
+ int anch_end = text_end - match_min + anch_offset; // maximum anchor position \r
+ \r
+ \r
+ int anch_begin = 0;\r
+\r
\r
// the general case for an anchoring expression is at the bottom, however we\r
// do some checks for the common cases before to save processing time. the current\r
// optimizer only outputs three types of anchoring expressions: fixed position,\r
// fixed substring, and no anchor.\r
\r
- OpCode anch_op = (OpCode)(program[pc + 3] & 0x00ff);\r
+ OpCode anch_op = (OpCode)(program[pc + 3] & 0x00ff); \r
if (anch_op == OpCode.Position && skip == 6) { // position anchor\r
// Anchor\r
// Position\r
// True\r
\r
switch ((Position)program[pc + 4]) {\r
- case Position.StartOfString:\r
- if (anch_ptr == 0) {\r
- ptr = 0;\r
+ case Position.StartOfString: \r
+ if (anch_reverse || anch_offset == 0) {\r
+ ptr = anch_offset;\r
if (TryMatch (ref ptr, pc + skip))\r
goto Pass;\r
}\r
break;\r
\r
case Position.StartOfLine:\r
- if (anch_ptr == 0) {\r
+ \r
+ if (anch_ptr == 0) {\r
ptr = 0;\r
if (TryMatch (ref ptr, pc + skip))\r
goto Pass;\r
-\r
+ \r
++ anch_ptr;\r
}\r
\r
- while (anch_ptr <= anch_end) {\r
- if (text[anch_ptr - 1] == '\n') {\r
- ptr = anch_ptr - anch_offset;\r
+ while ((anch_reverse && anch_ptr >= 0) || (!anch_reverse && anch_ptr <= anch_end)) { \r
+ if (anch_ptr == 0 || text[anch_ptr - 1] == '\n') {\r
+ if (anch_reverse)\r
+ ptr = anch_ptr == anch_end ? anch_ptr : anch_ptr + anch_offset;\r
+ else\r
+ ptr = anch_ptr == 0 ? anch_ptr : anch_ptr - anch_offset;\r
if (TryMatch (ref ptr, pc + skip))\r
goto Pass;\r
}\r
-\r
- ++ anch_ptr;\r
+ \r
+ if (anch_reverse)\r
+ -- anch_ptr;\r
+ else\r
+ ++ anch_ptr;\r
}\r
break;\r
\r
case Position.StartOfScan:\r
- if (anch_ptr == scan_ptr) {\r
- ptr = scan_ptr - anch_offset;\r
+ if (anch_ptr == scan_ptr) { \r
+ ptr = anch_reverse ? scan_ptr + anch_offset : scan_ptr - anch_offset;\r
if (TryMatch (ref ptr, pc + skip))\r
goto Pass;\r
}\r
// Anchor\r
// String\r
// True\r
+ \r
+ bool reverse = ((OpFlags)program[pc + 3] & OpFlags.RightToLeft) != 0;\r
+ string substring = GetString (pc + 3);\r
\r
if (qs == null) {\r
bool ignore = ((OpFlags)program[pc + 3] & OpFlags.IgnoreCase) != 0;\r
- string substring = GetString (pc + 3);\r
\r
- qs = new QuickSearch (substring, ignore);\r
+ qs = new QuickSearch (substring, ignore, reverse);\r
}\r
-\r
- while (anch_ptr <= anch_end) {\r
- anch_ptr = qs.Search (text, anch_ptr, anch_end);\r
+ while ((anch_reverse && anch_ptr >= anch_begin) \r
+ || (!anch_reverse && anch_ptr <= anch_end)) {\r
+\r
+ if (reverse) \r
+ {\r
+ anch_ptr = qs.Search (text, anch_ptr, anch_begin);\r
+ if (anch_ptr != -1)\r
+ anch_ptr += substring.Length ;\r
+ \r
+ }\r
+ else\r
+ anch_ptr = qs.Search (text, anch_ptr, anch_end);\r
if (anch_ptr < 0)\r
break;\r
\r
- ptr = anch_ptr - anch_offset;\r
+ ptr = reverse ? anch_ptr + anch_offset : anch_ptr - anch_offset;\r
if (TryMatch (ref ptr, pc + skip))\r
goto Pass;\r
\r
- ++ anch_ptr;\r
+ if (reverse)\r
+ anch_ptr -= 2;\r
+ else \r
+ ++ anch_ptr;\r
}\r
}\r
else if (anch_op == OpCode.True) { // no anchor\r
// Anchor\r
// True\r
\r
- while (anch_ptr <= anch_end) {\r
+ \r
+ while ((anch_reverse && anch_ptr >= anch_begin) \r
+ || (!anch_reverse && anch_ptr <= anch_end)) {\r
+\r
ptr = anch_ptr;\r
if (TryMatch (ref ptr, pc + skip))\r
goto Pass;\r
-\r
- ++ anch_ptr;\r
+ if (anch_reverse)\r
+ -- anch_ptr;\r
+ else \r
+ ++ anch_ptr;\r
}\r
}\r
else { // general case\r
// <expr>\r
// True\r
\r
- while (anch_ptr <= anch_end) {\r
+ while ((anch_reverse && anch_ptr >= anch_begin) \r
+ || (!anch_reverse && anch_ptr <= anch_end)) {\r
+\r
ptr = anch_ptr;\r
if (Eval (Mode.Match, ref ptr, pc + 3)) {\r
// anchor expression passed: try real expression at the correct offset\r
\r
- ptr = anch_ptr - anch_offset;\r
+ ptr = anch_reverse ? anch_ptr + anch_offset : anch_ptr - anch_offset;\r
if (TryMatch (ref ptr, pc + skip))\r
goto Pass;\r
}\r
\r
- ++ anch_ptr;\r
+ if (anch_reverse)\r
+ -- anch_ptr;\r
+ else \r
+ ++ anch_ptr;\r
}\r
}\r
\r
if (ptr < 0)\r
goto Fail;\r
}\r
- else if (ptr + len > text_end)\r
+ else \r
+ if (ptr + len > text_end)\r
goto Fail;\r
\r
pc += 2;\r
OpFlags tail_flags = (OpFlags)(tail_word & 0xff00);\r
\r
if (tail_op == OpCode.String)\r
- c1 = program[pc + 2]; // first char of string\r
+ {\r
+ int offset = 0;\r
+ \r
+ if ((tail_flags & OpFlags.RightToLeft) != 0)\r
+ {\r
+ offset = program[pc + 1] - 1 ;\r
+ }\r
+ \r
+ c1 = program[pc + 2 + offset]; // first char of string\r
+ }\r
else\r
c1 = program[pc + 1]; // character\r
\r
char c = '\0';\r
bool negate;\r
bool ignore;\r
+ \r
do {\r
ushort word = program[pc];\r
OpCode op = (OpCode)(word & 0x00ff);\r
int i = (int)c - lo;\r
if (i < 0 || i >= len << 4)\r
break;\r
+ \r
\r
if ((program[bits + (i >> 4)] & (1 << (i & 0xf))) != 0)\r
return !negate;\r
private int[] groups; // current group definitions\r
\r
// private classes\r
-\r
+/*\r
private struct Mark {\r
public int Start, End;\r
public int Previous;\r
get { return Start < End ? End - Start : Start - End; }\r
}\r
}\r
-\r
+*/\r
private class RepeatContext {\r
public RepeatContext (RepeatContext previous, int min, int max, bool lazy, int expr_pc) {\r
this.previous = previous;\r
using System.Collections;
namespace System.Text.RegularExpressions {
- class QuickSearch {
+ public class QuickSearch {
// simplified boyer-moore for fast substring matching
// (for short strings, we use simple scans)
+ public QuickSearch (string str, bool ignore)
+ : this(str, ignore, false)
+ {
+ }
- public QuickSearch (string str, bool ignore) {
+ public QuickSearch (string str, bool ignore, bool reverse) {
this.str = str;
this.len = str.Length;
this.ignore = ignore;
+ this.reverse = reverse;
if (ignore)
str = str.ToLower ();
public int Search (string text, int start, int end) {
int ptr = start;
- // use simple scan for a single-character search string
- if (len == 1) {
- while (ptr <= end) {
- if(str[0] == GetChar(text[ptr]))
- return ptr;
+
+ if ( reverse )
+ {
+ if (start < end)
+ return -1;
+
+ if ( ptr > text.Length)
+ {
+ ptr = text.Length;
+ }
+
+ // use simple scan for a single-character search string
+ if (len == 1)
+ {
+ while (--ptr >= end)
+ {
+ if(str[0] == GetChar(text[ptr]))
+ return ptr ;
+
+ }
+ return -1;
+ }
+
+
+ if ( end < len)
+ end = len - 1 ;
+
+ ptr--;
+ while (ptr >= end)
+ {
+ int i = len -1 ;
+ while (str[i] == GetChar(text[ptr - len +1 + i]))
+ {
+ if (-- i < 0)
+ return ptr - len + 1;
+ }
+
+ if (ptr > end)
+ {
+ ptr -= GetShiftDistance (text[ptr - len ]);
+
+ }
else
- ptr++;
+ break;
}
- return -1;
+
}
+ else
+ {
+ // use simple scan for a single-character search string
+ if (len == 1)
+ {
+ while (ptr <= end)
+ {
+ if(str[0] == GetChar(text[ptr]))
+ return ptr;
+ else
+ ptr++;
+ }
+ return -1;
+ }
- if (end > text.Length - len)
- end = text.Length - len;
+ if (end > text.Length - len)
+ end = text.Length - len;
- while (ptr <= end) {
- int i = len - 1;
- while (str[i] == GetChar(text[ptr + i])) {
- if (-- i < 0)
- return ptr;
- }
+ while (ptr <= end)
+ {
+ int i = len - 1;
+ while (str[i] == GetChar(text[ptr + i]))
+ {
+ if (-- i < 0)
+ return ptr;
+ }
- if (ptr < end)
- ptr += GetShiftDistance (text[ptr + len]);
- else
- break;
+ if (ptr < end)
+ ptr += GetShiftDistance (text[ptr + len]);
+ else
+ break;
+ }
}
return -1;
+
}
- // private
+ // private
private void SetupShiftTable () {
shift = new Hashtable ();
- for (int i = 0; i < len; ++ i) {
- char c = str[i];
- shift[GetChar(c)] = len - i;
+ if (reverse)
+ {
+ for (int i = len ; i > 0; -- i)
+ {
+ char c = str[i -1];
+ shift[GetChar(c)] = i;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < len; ++ i)
+ {
+ char c = str[i];
+ shift[GetChar(c)] = len - i;
+ }
}
+
}
private int GetShiftDistance (char c) {
private string str;
private int len;
private bool ignore;
+ private bool reverse;
private Hashtable shift;
private readonly static int THRESHOLD = 5;
using RegularExpression = System.Text.RegularExpressions.Syntax.RegularExpression;\r
using Parser = System.Text.RegularExpressions.Syntax.Parser;\r
\r
+using System.Diagnostics;\r
+\r
+\r
namespace System.Text.RegularExpressions {\r
\r
public delegate string MatchEvaluator (Match match);\r
public static void CompileToAssembly\r
(RegexCompilationInfo[] regexes, AssemblyName aname)\r
{\r
- throw new Exception ("Not implemented.");\r
+ Regex.CompileToAssembly(regexes, aname, new CustomAttributeBuilder[] {}, null);\r
}\r
\r
public static void CompileToAssembly\r
(RegexCompilationInfo[] regexes, AssemblyName aname,\r
CustomAttributeBuilder[] attribs)\r
{\r
- throw new Exception ("Not implemented.");\r
+ Regex.CompileToAssembly(regexes, aname, attribs, null); \r
}\r
\r
public static void CompileToAssembly\r
(RegexCompilationInfo[] regexes, AssemblyName aname,\r
CustomAttributeBuilder[] attribs, string resourceFile)\r
{\r
- throw new Exception ("Not implemented.");\r
+ throw new Exception ("Not fully implemented.");\r
+ // TODO : Make use of attribs and resourceFile parameters\r
+ /*\r
+ AssemblyBuilder asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly (aname, AssemblyBuilderAccess.RunAndSave);\r
+ ModuleBuilder modBuilder = asmBuilder.DefineDynamicModule("InnerRegexModule",aname.Name);\r
+ Parser psr = new Parser (); \r
+ \r
+ System.Console.WriteLine("CompileToAssembly");\r
+ \r
+ for(int i=0; i < regexes.Length; i++)\r
+ {\r
+ System.Console.WriteLine("Compiling expression :" + regexes[i].Pattern);\r
+ RegularExpression re = psr.ParseRegularExpression (regexes[i].Pattern, regexes[i].Options);\r
+ \r
+ // compile\r
+ \r
+ CILCompiler cmp = new CILCompiler (modBuilder, i);\r
+ bool reverse = (regexes[i].Options & RegexOptions.RightToLeft) !=0;\r
+ re.Compile (cmp, reverse);\r
+ cmp.Close();\r
+ \r
+ }\r
+ \r
+\r
+ // Define a runtime class with specified name and attributes.\r
+ TypeBuilder builder = modBuilder.DefineType("ITest");\r
+ builder.CreateType();\r
+ asmBuilder.Save(aname.Name);\r
+ */\r
}\r
\r
public static string Escape (string str) {\r
\r
protected Regex () {\r
// XXX what's this constructor for?\r
+ // : Used to compile to assembly (Custum regex inherit from Regex and use this constructor)\r
}\r
\r
public Regex (string pattern) : this (pattern, RegexOptions.None) {\r
\r
public Regex (string pattern, RegexOptions options) {\r
this.pattern = pattern;\r
- this.options = options;\r
+ this.roptions = options;\r
\r
- this.factory = cache.Lookup (pattern, options);\r
+ this.machineFactory = cache.Lookup (pattern, options);\r
\r
- if (this.factory == null) {\r
+ if (this.machineFactory == null) {\r
// parse and install group mapping\r
\r
Parser psr = new Parser ();\r
\r
ICompiler cmp;\r
//if ((options & RegexOptions.Compiled) != 0)\r
- // throw new Exception ("Not implemented.");\r
- //cmp = new CILCompiler ();\r
+ // //throw new Exception ("Not implemented.");\r
+ // cmp = new CILCompiler ();\r
//else\r
cmp = new PatternCompiler ();\r
\r
\r
// install machine factory and add to pattern cache\r
\r
- this.factory = cmp.GetMachineFactory ();\r
- this.factory.Mapping = mapping;\r
- cache.Add (pattern, options, this.factory);\r
+ this.machineFactory = cmp.GetMachineFactory ();\r
+ this.machineFactory.Mapping = mapping;\r
+ cache.Add (pattern, options, this.machineFactory);\r
} else {\r
- this.group_count = this.factory.GroupCount;\r
- this.mapping = this.factory.Mapping;\r
+ this.group_count = this.machineFactory.GroupCount;\r
+ this.mapping = this.machineFactory.Mapping;\r
}\r
}\r
\r
protected Regex (SerializationInfo info, StreamingContext context) :\r
this (info.GetString ("pattern"), \r
- (RegexOptions) info.GetValue ("options", typeof (RegexOptions))) { \r
+ (RegexOptions) info.GetValue ("roptions", typeof (RegexOptions))) { \r
}\r
\r
\r
// public instance properties\r
\r
public RegexOptions Options {\r
- get { return options; }\r
+ get { return roptions; }\r
}\r
\r
public bool RightToLeft {\r
- get { return (options & RegexOptions.RightToLeft) != 0; }\r
+ get { return (roptions & RegexOptions.RightToLeft) != 0; }\r
}\r
\r
// public instance methods\r
// match methods\r
\r
public bool IsMatch (string input) {\r
- return IsMatch (input, 0);\r
+ if (RightToLeft)\r
+ return IsMatch (input, input.Length);\r
+ else\r
+ return IsMatch (input, 0);\r
}\r
\r
public bool IsMatch (string input, int startat) {\r
}\r
\r
public Match Match (string input) {\r
- return Match (input, 0);\r
+ if (RightToLeft)\r
+ return Match (input, input.Length);\r
+ else\r
+ return Match (input, 0);\r
}\r
\r
public Match Match (string input, int startat) {\r
+ \r
return CreateMachine ().Scan (this, input, startat, input.Length);\r
}\r
\r
public Match Match (string input, int startat, int length) {\r
+ \r
return CreateMachine ().Scan (this, input, startat, startat + length);\r
}\r
\r
public MatchCollection Matches (string input) {\r
- return Matches (input, 0);\r
+ if (RightToLeft)\r
+ return Matches (input, input.Length);\r
+ else\r
+ return Matches (input, 0);\r
}\r
\r
public MatchCollection Matches (string input, int startat) {\r
// replace methods\r
\r
public string Replace (string input, MatchEvaluator evaluator) {\r
- return Replace (input, evaluator, Int32.MaxValue, 0);\r
+ if (RightToLeft) \r
+ return Replace (input, evaluator, Int32.MaxValue, input.Length);\r
+ else\r
+ return Replace (input, evaluator, Int32.MaxValue, 0);\r
}\r
\r
public string Replace (string input, MatchEvaluator evaluator, int count) {\r
- return Replace (input, evaluator, count, 0);\r
+ if (RightToLeft)\r
+ return Replace (input, evaluator, count, input.Length);\r
+ else\r
+ return Replace (input, evaluator, count, 0);\r
}\r
\r
public string Replace (string input, MatchEvaluator evaluator, int count, int startat)\r
}\r
\r
public string Replace (string input, string replacement) {\r
- return Replace (input, replacement, Int32.MaxValue, 0);\r
+ if (RightToLeft)\r
+ return Replace (input, replacement, Int32.MaxValue, input.Length);\r
+ else\r
+ return Replace (input, replacement, Int32.MaxValue, 0);\r
}\r
\r
public string Replace (string input, string replacement, int count) {\r
- return Replace (input, replacement, count, 0);\r
+ if (RightToLeft) \r
+ return Replace (input, replacement, count, input.Length);\r
+ else \r
+ return Replace (input, replacement, count, 0);\r
}\r
\r
public string Replace (string input, string replacement, int count, int startat) {\r
// split methods\r
\r
public string[] Split (string input) {\r
- return Split (input, Int32.MaxValue, 0);\r
+ if (RightToLeft) \r
+ return Split (input, Int32.MaxValue, input.Length);\r
+ else\r
+ return Split (input, Int32.MaxValue, 0);\r
}\r
\r
public string[] Split (string input, int count) {\r
- return Split (input, count, 0);\r
+ if (RightToLeft) \r
+ return Split (input, count, input.Length);\r
+ else\r
+ return Split (input, count, 0);\r
}\r
\r
public string[] Split (string input, int count, int startat) {\r
if (!m.Success)\r
break;\r
\r
- splits.Add (input.Substring (ptr, m.Index - ptr));\r
+ if (RightToLeft)\r
+ splits.Add (input.Substring (m.Index + m.Length , ptr - m.Index - m.Length ));\r
+ else\r
+ splits.Add (input.Substring (ptr, m.Index - ptr));\r
+ \r
int gcount = m.Groups.Count;\r
for (int gindex = 1; gindex < gcount; gindex++) {\r
Group grp = m.Groups [gindex];\r
splits.Add (input.Substring (grp.Index, grp.Length));\r
}\r
\r
- ptr = m.Index + m.Length;\r
+ if (RightToLeft)\r
+ ptr = m.Index; \r
+ else\r
+ ptr = m.Index + m.Length;\r
+ \r
}\r
\r
- if (ptr <= input.Length) {\r
- splits.Add (input.Substring (ptr));\r
+ if (RightToLeft) {\r
+ if ( ptr >= 0) {\r
+ splits.Add (input.Substring(0, ptr));\r
+ }\r
+ } \r
+ else {\r
+ if (ptr <= input.Length) {\r
+ splits.Add (input.Substring (ptr));\r
+ }\r
+ \r
}\r
\r
return (string []) splits.ToArray (typeof (string));\r
}\r
\r
+ // MS undocummented method\r
+ \r
+ protected void InitializeReferences() {\r
+ throw new Exception ("Not implemented.");\r
+ }\r
+ \r
+ protected bool UseOptionC(){\r
+ throw new Exception ("Not implemented.");\r
+ }\r
+\r
+ protected bool UseOptionR(){\r
+ throw new Exception ("Not implemented.");\r
+ }\r
+\r
// object methods\r
\r
public override string ToString () {\r
// ISerializable interface\r
public virtual void GetObjectData (SerializationInfo info, StreamingContext context) {\r
info.AddValue ("pattern", this.ToString (), typeof (string));\r
- info.AddValue ("options", this.Options, typeof (RegexOptions));\r
+ info.AddValue ("roptions", this.Options, typeof (RegexOptions));\r
}\r
\r
// internal\r
// private\r
\r
private IMachine CreateMachine () {\r
- return factory.NewInstance ();\r
+ return machineFactory.NewInstance ();\r
}\r
\r
- protected internal string pattern;\r
- private RegexOptions options;\r
-\r
- private IMachineFactory factory;\r
+ private IMachineFactory machineFactory;\r
private IDictionary mapping;\r
private int group_count;\r
+\r
+ \r
+ // protected members\r
+\r
+ protected internal string pattern;\r
+ protected internal RegexOptions roptions;\r
+ \r
+ // MS undocumented members\r
+ protected internal System.Collections.Hashtable capnames;\r
+ protected internal System.Collections.Hashtable cap;\r
+ protected internal int capsize;\r
+ protected internal string[] caplist;\r
+ protected internal RegexRunnerFactory factory;\r
}\r
\r
[Serializable]\r
return -1;\r
}\r
\r
- public virtual AnchorInfo GetAnchorInfo () {\r
+ public virtual AnchorInfo GetAnchorInfo (bool reverse) {\r
return new AnchorInfo (this, GetFixedWidth ());\r
}\r
\r
}\r
}\r
\r
- public override AnchorInfo GetAnchorInfo () {\r
+ public override AnchorInfo GetAnchorInfo (bool reverse) {\r
int ptr;\r
int width = GetFixedWidth ();\r
\r
// accumulate segments\r
\r
ptr = 0;\r
- foreach (Expression e in Expressions) {\r
- AnchorInfo info = e.GetAnchorInfo ();\r
+ //foreach (Expression e in Expressions) {\r
+ int count = Expressions.Count;\r
+ for (int i = 0; i < count; ++ i) {\r
+ Expression e;\r
+ if (reverse)\r
+ e = Expressions [count - i - 1];\r
+ else\r
+ e = Expressions [i]; \r
+ \r
+ AnchorInfo info = e.GetAnchorInfo (reverse);\r
infos.Add (info);\r
\r
if (info.IsPosition)\r
\r
if (!longest.IsEmpty) {\r
string str = "";\r
+ ArrayList strs = new ArrayList();\r
bool ignore = false;\r
\r
ptr = 0;\r
- foreach (AnchorInfo info in infos) {\r
+ \r
+ //foreach (AnchorInfo info in infos) {\r
+ for (int i = 0; i < infos.Count; ++ i) {\r
+ AnchorInfo info;\r
+\r
+ info = (AnchorInfo)infos[i]; \r
+ \r
if (info.IsSubstring && longest.Contains (info.GetInterval (ptr))) {\r
- str += info.Substring; // TODO mark subexpressions\r
+ //str += info.Substring; // TODO mark subexpressions\r
+ strs.Add(info.Substring);\r
ignore |= info.IgnoreCase;\r
}\r
\r
- if (info.IsUnknownWidth)\r
- break;\r
-\r
- ptr += info.Width;\r
+ \r
+ if (info.IsUnknownWidth) \r
+ break;\r
+ \r
+ ptr += info.Width;\r
+ } \r
+ \r
+ for (int i = 0; i< strs.Count; ++i)\r
+ {\r
+ if (reverse)\r
+ str += strs [strs.Count - i - 1];\r
+ else\r
+ str += strs [i];\r
+ \r
+ \r
}\r
+ \r
\r
return new AnchorInfo (this, longest.low, width, str, ignore);\r
}\r
\r
// anchoring expression\r
\r
- AnchorInfo info = GetAnchorInfo ();\r
- if (reverse)\r
- info = new AnchorInfo (this, GetFixedWidth ()); // FIXME\r
+ AnchorInfo info = GetAnchorInfo (reverse);\r
+ //if (reverse)\r
+ // info = new AnchorInfo (this, GetFixedWidth ()); // FIXME\r
\r
LinkRef pattern = cmp.NewLink ();\r
- cmp.EmitAnchor (info.Offset, pattern);\r
+ cmp.EmitAnchor (reverse, info.Offset, pattern);\r
\r
if (info.IsPosition)\r
cmp.EmitPosition (info.Position);\r
max = max * this.max;\r
}\r
\r
- public override AnchorInfo GetAnchorInfo () {\r
+ public override AnchorInfo GetAnchorInfo (bool reverse) {\r
int width = GetFixedWidth ();\r
if (Minimum == 0)\r
return new AnchorInfo (this, width);\r
\r
- AnchorInfo info = Expression.GetAnchorInfo ();\r
+ AnchorInfo info = Expression.GetAnchorInfo (reverse);\r
if (info.IsPosition)\r
return new AnchorInfo (this, info.Offset, width, info.Position);\r
\r
\r
// test expression: lookahead / lookbehind\r
\r
- TestExpression.Compile (cmp, reverse ^ this.reverse);\r
+ TestExpression.Compile (cmp, this.reverse);\r
cmp.EmitTrue ();\r
\r
// target expressions\r
}\r
\r
public override void Compile (ICompiler cmp, bool reverse) {\r
- LinkRef next = cmp.NewLink ();\r
+ // LinkRef next = cmp.NewLink ();\r
LinkRef tail = cmp.NewLink ();\r
\r
foreach (Expression e in Alternatives) {\r
+ LinkRef next = cmp.NewLink ();\r
cmp.EmitBranch (next);\r
e.Compile (cmp, reverse);\r
cmp.EmitJump (tail);\r
cmp.ResolveLink (next);\r
+ cmp.EmitBranchEnd();\r
}\r
\r
cmp.EmitFalse ();\r
cmp.ResolveLink (tail);\r
+ cmp.EmitAlternationEnd();\r
}\r
\r
public override void GetWidth (out int min, out int max) {\r
min = max = str.Length;\r
}\r
\r
- public override AnchorInfo GetAnchorInfo () {\r
+ public override AnchorInfo GetAnchorInfo (bool reverse) {\r
return new AnchorInfo (this, 0, str.Length, str, ignore);\r
}\r
\r
return false;\r
}\r
\r
- public override AnchorInfo GetAnchorInfo () {\r
+ public override AnchorInfo GetAnchorInfo (bool revers) {\r
switch (pos) {\r
case Position.StartOfString: case Position.StartOfLine: case Position.StartOfScan:\r
return new AnchorInfo (this, 0, 0, pos);\r
\r
public override void Compile (ICompiler cmp, bool reverse) {\r
// create the meta-collection\r
-\r
IntervalCollection meta =\r
intervals.GetMetaCollection (new IntervalCollection.CostDelegate (GetIntervalCost));\r
\r
LinkRef tail = cmp.NewLink ();\r
if (count > 1)\r
cmp.EmitIn (tail);\r
+ \r
\r
// emit categories\r
\r
}\r
}\r
}\r
+\r