public bool Parse(CharacterBuffer buffer) { int num; this.Start = buffer.IndexInOriginalBuffer; if (buffer.IsAtEnd) { Utility.ParseError("Reached end of buffer looking for a conditional!", buffer); this.IsValid = false; return false; } this.Literal = buffer.GetStringToMatchingParenthesis(); Match match = this.ConditionalRegex.Match(this.Literal); if (!match.Success) { buffer.Move(1 - this.Literal.Length); return false; } var item = match.Groups["Expression"]; int start = this.Start + item.Index; string str = item.Value.Substring(1, item.Value.Length - 2); this.Name = str; this.expType = Conditional.ExpType.Expression; this.Exp = new SubExpression(item.Value, start, buffer.IgnoreWhiteSpace, buffer.IsEcma, true) { Start = start, End = this.Exp.Start + item.Length }; if (this.Exp.Exp[0] is Group) { Group group = (Group)this.Exp.Exp[0]; switch (group.Type) { case GroupType.Balancing: { group.Description = "Test condition cannot be a balancing group"; group.IsValid = false; this.IsValid = false; break; } case GroupType.Named: { group.Description = "Test condition cannot be a named group"; group.IsValid = false; this.IsValid = false; break; } case GroupType.Numbered: { if (BackReference.ContainsName(str)) { this.expType = Conditional.ExpType.NamedCapture; break; } else if (int.TryParse(str, out num)) { this.expType = Conditional.ExpType.NumberedCapture; if (BackReference.ContainsNumber(str)) { break; } this.expType = Conditional.ExpType.NonExistentNumber; group.IsValid = false; break; } else if (!this.AlphanumericRegex.Match(str).Success) { group.Description = "Match if prefix is present"; break; } else if (!char.IsDigit(str[0])) { this.expType = Conditional.ExpType.NonExistentName; break; } else { this.expType = Conditional.ExpType.InvalidName; group.IsValid = false; break; } } case GroupType.Noncapturing: case GroupType.Greedy: case GroupType.OptionsInside: case GroupType.OptionsOutside: { group.Description = "Test condition is"; break; } case GroupType.SuffixPresent: { group.Description = "Match if suffix is present"; break; } case GroupType.PrefixPresent: { group.Description = "Match if prefix is present"; break; } case GroupType.SuffixAbsent: { group.Description = "Match if suffix is absent"; break; } case GroupType.PrefixAbsent: { group.Description = "Match if prefix is absent"; break; } case GroupType.Comment: { group.Description = "Test condition cannot be a comment!"; group.IsValid = false; this.IsValid = false; break; } default: { goto case GroupType.OptionsOutside; } } group.Description = string.Concat(group.Description, " ", group.Literal); } else { this.expType = Conditional.ExpType.NotAGroup; } item = match.Groups["Contents"]; string value = item.Value; List<int> nums = (new CharacterBuffer(value)).FindNakedPipes(); start = this.Start + item.Index; switch (nums.Count) { case 0: { this.Yes = new SubExpression(value, start, buffer.IgnoreWhiteSpace, buffer.IsEcma) { Start = start, End = this.Yes.Start + item.Length }; this.Description = "Conditional Expression with \"Yes\" clause only"; break; } case 1: { int item1 = nums[0] + 1; this.Yes = new SubExpression(value.Substring(0, item1 - 1), start, buffer.IgnoreWhiteSpace, buffer.IsEcma) { Start = start, End = this.Yes.Start + item1 - 1 }; start = this.Yes.Start + item1; this.No = new SubExpression(value.Substring(item1), start, buffer.IgnoreWhiteSpace, buffer.IsEcma) { Start = start, End = this.Yes.Start + item.Length }; this.Description = "Conditional Expression with \"Yes\" and \"No\" clause"; break; } default: { this.Yes = new SubExpression(value, start, buffer.IgnoreWhiteSpace, buffer.IsEcma) { Start = start, End = this.Yes.Start + item.Length }; this.Description = "Too many | symbols in a conditional expression"; this.IsValid = false; break; } } buffer.MoveNext(); base.ParseRepetitions(buffer); return true; }
public Group(CharacterBuffer buffer, bool SkipCaptureNumber) { char literal; char chr; int num; bool flag; bool flag1; //this.Image = ImageType.Group; this.Start = buffer.IndexInOriginalBuffer; bool needToParseRepititions = true; this.Literal = buffer.GetStringToMatchingParenthesis(); if (this.Literal == "") { return; } Match match = Group.RegGroup.Match(this.Literal); if (!match.Success) { this.Type = GroupType.Invalid; this.Content = new SubExpression("", 0, false, false); this.IsValid = false; needToParseRepititions = false; this.Description = "Syntax error in group definition"; buffer.Move(1 - this.Literal.Length); } else { string value = match.Groups["GroupType"].Value; string str = match.Groups["Name"].Value; string value1 = match.Groups["Number"].Value; string str1 = match.Groups["Options"].Value; string value2 = match.Groups["Contents"].Value; int start = this.Start + match.Groups["Contents"].Index; this.Name2 = match.Groups["Name2"].Value; if (str1 == "") { string str2 = value; string str3 = str2; if (str2 != null) { switch (str3) { case ":": { this.Type = GroupType.Noncapturing; goto Label0; } case "=": { this.Type = GroupType.SuffixPresent; goto Label0; } case "<=": { this.Type = GroupType.PrefixPresent; goto Label0; } case "<!": { this.Type = GroupType.PrefixAbsent; goto Label0; } case "!": { this.Type = GroupType.SuffixAbsent; goto Label0; } case "#": { this.Type = GroupType.Comment; needToParseRepititions = false; goto Label0; } case ">": { this.Type = GroupType.Greedy; goto Label0; } case "(": { this.Type = GroupType.Invalid; this.Content = new SubExpression("", 0, false, false); this.IsValid = false; this.Description = "Syntax error in group definition"; needToParseRepititions = false; buffer.Move(1 - this.Literal.Length); goto Label0; } case "": { if (value2.Length <= 0 || !(value2.Substring(0, 1) == "?")) { this.Type = GroupType.Numbered; if (SkipCaptureNumber) { this.Name = ""; goto Label0; } else { this.Name = BackReference.AddNumber().ToString(); goto Label0; } } else { this.Type = GroupType.Invalid; value2 = value2.Substring(1); this.Content = new SubExpression(value2, start + 1, buffer.IgnoreWhiteSpace, buffer.IsEcma); this.Description = "Illegal group syntax"; this.IsValid = false; goto Label0; } } case "-": { int index = match.Groups["Name"].Index - 1; int index1 = match.Groups["Name2"].Index + match.Groups["Name2"].Length; literal = this.Literal[index]; chr = this.Literal[index1]; if (literal != '<' || chr != '>') { flag1 = (literal != '\'' ? false : chr == '\''); } else { flag1 = true; } this.IsValid = flag1; if (!this.IsValid) { this.Description = "Invalid syntax for balancing group"; } this.Type = GroupType.Balancing; this.Name = str; if (this.Name != "") { if (!int.TryParse(this.Name, out num)) { BackReference.AddName(this.Name); } else { BackReference.AddNumber(num); } } if (!int.TryParse(this.Name2, out num)) { if (BackReference.ContainsName(this.Name2)) { goto Label0; } this.Description = string.Concat("Invalid group name in a balancing group: ", this.Name2); this.IsValid = false; goto Label0; } else { if (BackReference.ContainsNumber(this.Name2)) { goto Label0; } this.Description = string.Concat("Invalid group number in a balancing group: ", this.Name2); this.IsValid = false; goto Label0; } } } } literal = value[0]; chr = value[value.Length - 1]; if (literal != '<' || chr != '>') { flag = (literal != '\'' ? false : chr == '\''); } else { flag = true; } this.IsValid = flag; if (str.Length > 0) { this.Type = GroupType.Named; this.Name = str; BackReference.AddName(str); if (!this.IsValid) { this.Description = string.Concat("[", str, "] Invalid syntax for named group"); } } else if (value1.Length <= 0) { this.Type = GroupType.Named; this.Name = ""; this.IsValid = false; this.Description = "Missing name for a named group"; } else { this.Type = GroupType.Numbered; this.Name = value1; BackReference.AddNumber(int.Parse(value1)); if (!this.IsValid) { this.Description = string.Concat("[", value1, "] Invalid syntax for numbered group"); } } } else { this.DecodeOptions(str1); if (this.Type == GroupType.OptionsOutside) { needToParseRepititions = false; } } Label0: // TODO: Remove this and create proper logic! SetContent(buffer, value2, start); } buffer.MoveNext(); if (needToParseRepititions) { ParseRepetitions(buffer); } else { End = buffer.IndexInOriginalBuffer; RepeatType = Repeat.Once; } SetDescription(); }
public void MoveNext_ReturnsTrue_WhenIndexIsNotAtEnd() { // ARRANGE const string data = Fakes.Literal.BasicLiteral; var characterBuffer = new CharacterBuffer(data); // ACT var result = characterBuffer.MoveNext(); // ASSERT Assert.IsTrue(result); }
private void DecodeOptions(string options) { CharacterBuffer charBuffer = new CharacterBuffer(options); this.SetI = CheckState.Indeterminate; this.SetM = CheckState.Indeterminate; this.SetS = CheckState.Indeterminate; this.SetN = CheckState.Indeterminate; this.SetX = CheckState.Indeterminate; if (options.Substring(options.Length - 1, 1) != ":") { this.Type = GroupType.OptionsOutside; this.Options = string.Concat("Change options within the enclosing group [", options, "]"); } else { this.Type = GroupType.OptionsInside; this.Options = string.Concat("Change options within a new noncapturing group [", options, "]"); } bool flag = true; while (!charBuffer.IsAtEnd) { char current = charBuffer.CurrentCharacter; if (current > 'i') { switch (current) { case 'm': { if (!flag) { this.SetM = CheckState.Unchecked; break; } else { this.SetM = CheckState.Checked; break; } } case 'n': { if (!flag) { this.SetN = CheckState.Unchecked; break; } else { this.SetN = CheckState.Checked; break; } } default: { if (current == 's') { if (!flag) { this.SetS = CheckState.Unchecked; break; } else { this.SetS = CheckState.Checked; break; } } else if (current != 'x') { goto Label0; } else if (!flag) { this.SetX = CheckState.Unchecked; break; } else { this.SetX = CheckState.Checked; break; } } } } else if (current == '-') { flag = false; } else if (current != ':') { if (current != 'i') { goto Label0; } if (!flag) { this.SetI = CheckState.Unchecked; } else { this.SetI = CheckState.Checked; } } Label2: charBuffer.MoveNext(); } return; Label0: Utility.ParseError("Error in options construct!", charBuffer); this.IsValid = false; //goto Label2; // TODO: This does not complile so threw lines below... charBuffer.MoveNext(); return; }
public bool Parse(CharacterBuffer buffer) { int num; this.Start = buffer.IndexInOriginalBuffer; if (buffer.CurrentCharacter != '\\') { return false; } buffer.MoveNext(); if (buffer.IsAtEnd) { return false; } char current = buffer.CurrentCharacter; if (!char.IsDigit(current) && current != 'k') { buffer.Move(-1); return false; } Match match = BackReference.BackrefRegex.Match(buffer.GetToEnd()); if (!match.Success) { if (current != 'k') { return false; } this.IsValid = false; this.Literal = "\\k"; this.Description = "Invalid backreference"; this.contents = ""; buffer.MoveNext(); this.End = buffer.IndexInOriginalBuffer; return true; } string value = match.Groups["Backreference"].Value; string str = match.Groups["Decimal"].Value; string value1 = match.Groups["Octal"].Value; string str1 = match.Groups["Named"].Value; this.Literal = string.Concat('\\', match.Value); if (str1 != "") { if (BackReference.Names.Contains(str1)) { this.Description = string.Concat(this.Named, str1); } else if (!int.TryParse(str1, out num) || !BackReference.NumbersContains(num)) { this.Description = string.Concat(this.MissingName, str1); this.IsValid = false; } else { this.Description = string.Concat(this.Numbered, str1); } buffer.Move(match.Length); base.ParseRepetitions(buffer); this.isNamed = true; this.contents = str1; return true; } if (value1 != "") { this.Description = string.Concat(this.ASCII, value1); buffer.Move(match.Length); base.ParseRepetitions(buffer); //this.Image = ImageType.Character; this.isOctal = true; this.contents = value1; return true; } if (!buffer.IsEcma) { if (value != "") { if (!BackReference.NumbersContains(int.Parse(value))) { this.Description = string.Concat(this.MissingNumber, value); this.IsValid = false; } else { this.Description = string.Concat(this.Numbered, value); } buffer.Move(match.Length); base.ParseRepetitions(buffer); this.contents = value; return true; } num = int.Parse(str); if (BackReference.NumbersContains(num)) { this.Description = string.Concat(this.Numbered, str); this.contents = str; buffer.Move(match.Length); base.ParseRepetitions(buffer); return true; } match = BackReference.OctalBackParseRegex.Match(buffer.GetToEnd()); if (!match.Success) { return false; } this.Literal = string.Concat('\\', match.Value); this.Description = string.Concat(this.ASCII, match.Groups["Octal"].Value); buffer.Move(match.Length); base.ParseRepetitions(buffer); //this.Image = ImageType.Character; this.isOctal = true; this.contents = match.Groups["Octal"].Value; return true; } if (value != "") { num = int.Parse(value); if (BackReference.NumbersContains(num)) { this.Description = string.Concat(this.Numbered, value); buffer.Move(match.Length); this.contents = value; base.ParseRepetitions(buffer); return true; } match = BackReference.OctalBackParseRegex.Match(buffer.GetToEnd()); if (!match.Success) { return false; } this.Literal = string.Concat('\\', match.Value); this.Description = string.Concat(this.ASCII, match.Groups["Octal"].Value); buffer.Move(match.Length); base.ParseRepetitions(buffer); //this.Image = ImageType.Character; this.isOctal = true; this.contents = match.Groups["Octal"].Value; return true; } if (str == "") { return false; } for (int i = str.Length; i > 0; i--) { string str2 = str.Substring(0, i); num = int.Parse(str2); if (BackReference.NumbersContains(num)) { this.Description = string.Concat(this.Numbered, str2); this.Literal = string.Concat("\\", str2); this.contents = str2; buffer.Move(i); base.ParseRepetitions(buffer); return true; } } match = BackReference.OctalBackParseRegex.Match(buffer.GetToEnd()); if (!match.Success) { return false; } this.Literal = string.Concat('\\', match.Value); this.Description = string.Concat(this.ASCII, match.Groups["Octal"].Value); buffer.Move(match.Length); base.ParseRepetitions(buffer); //this.Image = ImageType.Character; this.isOctal = true; this.contents = match.Groups["Octal"].Value; return true; }
public SpecialCharacter(CharacterBuffer buffer) { //this.Image = ImageType.SpecialCharacter; this.Escaped = false; this.Start = buffer.IndexInOriginalBuffer; if (buffer.IsAtEnd) { this.CharacterType = CharType.Invalid; this.character = "\\"; this.Literal = "\\"; this.Description = "Illegal \\ at end of pattern"; this.IsValid = false; this.Start = this.Start - 1; this.End = this.Start + 1; } else if (buffer.CurrentCharacter == '[') { buffer.MoveNext(); if (buffer.CurrentCharacter != '\u005E') { buffer.MoveNext(); this.Literal = string.Concat("[\\", buffer.CurrentCharacter); } else { this.MatchIfAbsent = true; buffer.Move(2); this.Literal = string.Concat("[^\\", buffer.CurrentCharacter); } this.S = buffer.CurrentCharacter.ToString(); if (this.MatchIfAbsent) { this.Description = string.Concat("Any character other than ", this.Description); } buffer.MoveNext(); SpecialCharacter specialCharacter = this; specialCharacter.Literal = string.Concat(specialCharacter.Literal, buffer.CurrentCharacter); buffer.MoveNext(); } else if (buffer.CurrentCharacter != '\\') { this.S = buffer.CurrentCharacter.ToString(); this.Literal = this.S; buffer.MoveNext(); } else { buffer.MoveNext(); if (!buffer.IsAtEnd) { Match match = SpecialCharacter.RegNumeric.Match(buffer.GetToEnd()); if (!match.Success) { this.Escaped = true; this.S = buffer.CurrentCharacter.ToString(); this.Literal = string.Concat("\\", this.S); buffer.MoveNext(); } else { string str = match.Value.Substring(0, 1); string str1 = str; if (str != null) { if (str1 == "x") { this.Description = string.Concat("Hex ", match.Value.Substring(1)); this.CharacterType = CharType.Hex; this.character = match.Value.Substring(1); goto Label0; } else if (str1 == "u") { this.Description = string.Concat("Unicode ", match.Value.Substring(1)); this.CharacterType = CharType.Unicode; this.character = match.Value.Substring(1); goto Label0; } else { if (str1 != "c") { goto Label2; } this.Description = string.Concat("Control ", match.Value.Substring(1, 1)); this.CharacterType = CharType.Control; this.character = match.Value.Substring(1); goto Label0; } } Label2: this.Description = string.Concat("Octal ", match.Value); this.CharacterType = CharType.Octal; this.character = match.Value.Substring(2); Label0: this.Literal = string.Concat("\\", match.Value); buffer.Move(match.Length); } } else { Utility.ParseError("Illegal \\ at end of pattern", buffer); } } base.ParseRepetitions(buffer); }
public void ParseRepetitions(CharacterBuffer buffer) { int currentIndex = buffer.CurrentIndex; buffer.SkipWhiteSpace(); if (buffer.IsAtEnd) { RepeatType = Repeat.Once; buffer.MoveTo(currentIndex); End = buffer.IndexInOriginalBuffer; return; } char current = buffer.CurrentCharacter; switch (current) { case '*': { this.RepeatType = Repeat.Any; Element element = this; element.Literal = string.Concat(element.Literal, buffer.CurrentCharacter); buffer.MoveNext(); break; } case '+': { this.RepeatType = Repeat.OneOrMore; Element element1 = this; element1.Literal = string.Concat(element1.Literal, buffer.CurrentCharacter); buffer.MoveNext(); break; } default: { if (current == '?') { this.RepeatType = Repeat.ZeroOrOne; Element element2 = this; element2.Literal = string.Concat(element2.Literal, buffer.CurrentCharacter); buffer.MoveNext(); break; } else { if (current != '{') { this.RepeatType = Repeat.Once; buffer.MoveTo(currentIndex); this.End = buffer.IndexInOriginalBuffer; return; } this.ParseBrackets(buffer); break; } } } currentIndex = buffer.CurrentIndex; buffer.SkipWhiteSpace(); if (buffer.IsAtEnd || buffer.CurrentCharacter != '?') { buffer.MoveTo(currentIndex); } else { this.AsFewAsPossible = true; Element element3 = this; element3.Literal = string.Concat(element3.Literal, buffer.CurrentCharacter); buffer.MoveNext(); } this.End = buffer.IndexInOriginalBuffer; }
public void Parse(int offset, bool skipFirstCaptureNumber) { Character character; CharacterBuffer charBuffer = new CharacterBuffer(Literal) { Offset = offset, IgnoreWhiteSpace = IgnoreWhitespace, IsEcma = IsEcma }; //Label2: while (!charBuffer.IsAtEnd) { int indexInOriginalBuffer = charBuffer.IndexInOriginalBuffer; HandleWhiteSpace(charBuffer, indexInOriginalBuffer); if (charBuffer.IsAtEnd) break; // Exit the loop char current = charBuffer.CurrentCharacter; if (current > Characters.Dot) { if (current == Characters.QuestionMark) { //goto Label0; AddMisplacedQuantifier(charBuffer); continue; // was goto Label2; } switch (current) { case Characters.SquareBracketOpen: { this.Add(new CharacterClass(charBuffer)); continue; // Move to next iteration } case Characters.BackSlash: { if (!SpecialCharacter.NextIsWhitespace(charBuffer)) { BackReference backReference = new BackReference(); if (!backReference.Parse(charBuffer)) { NamedClass namedClass = new NamedClass(); if (!namedClass.Parse(charBuffer)) { this.Add(new SpecialCharacter(charBuffer)); continue; // Move to next iteration } else { this.Add(namedClass); continue; // Move to next iteration } } else { BackReference.NeedsSecondPass = true; if (!backReference.IsOctal) { this.Add(backReference); continue; // Move to next iteration } else { this.Add(new SpecialCharacter(backReference)); continue; // Move to next iteration } } } else { this.Add(new SpecialCharacter(charBuffer)); continue; // Move to next iteration } } case Characters.SquareBracketClosed: { break; } case Characters.CircumflexAccent: { //goto Label1; AddSpecialCharacter(charBuffer); continue; // was goto Label2; } default: { switch (current) { case Characters.CurlyBraceOpen: { character = new Character(charBuffer, true) { //Description = string.Concat(character.Literal, " Misplaced quantifier"), IsValid = false }; character.Description = string.Concat(character.Literal, " Misplaced quantifier"); if (character.RepeatType != Repeat.Once) { this.Add(character); continue; } else { this.Add(new Character(charBuffer)); continue; } } case Characters.Pipe: { SubExpression subExpression = new SubExpression(this.Clone()) { Literal = charBuffer.Substring(0, charBuffer.CurrentIndex), Start = charBuffer.Offset, End = charBuffer.IndexInOriginalBuffer }; this.alternatives.Add(subExpression); charBuffer.MoveNext(); int num = charBuffer.IndexInOriginalBuffer; charBuffer = new CharacterBuffer(charBuffer.GetToEnd()) { Offset = num, IgnoreWhiteSpace = IgnoreWhitespace, IsEcma = IsEcma }; this.Clear(); continue; } } break; } } } else { switch (current) { case '\t': case '\n': case '\r': { //goto Label1; AddSpecialCharacter(charBuffer); continue; // was goto Label2; } case '\v': case '\f': { break; } default: { switch (current) { case ' ': case '$': case '.': { //goto Label1; AddSpecialCharacter(charBuffer); continue; // was goto Label2; } case '#': { if (!this.IgnoreWhitespace) { this.Add(new Character(charBuffer)); continue; } else { this.Add(new Comment(charBuffer)); continue; } } case '(': { Conditional conditional = new Conditional(); if (!conditional.Parse(charBuffer)) { Group group = new Group(charBuffer, skipFirstCaptureNumber); if (group.Type == GroupType.OptionsOutside) { if (group.SetX == CheckState.Checked) { this.IgnoreWhitespace = true; } else if (group.SetX == CheckState.Unchecked) { this.IgnoreWhitespace = false; } charBuffer.IgnoreWhiteSpace = this.IgnoreWhitespace; } this.Add(group); continue; } else { this.Add(conditional); BackReference.NeedsSecondPass = true; continue; } } case Characters.BracketClosed: { character = new Character(charBuffer) { IsValid = false, Description = "Unbalanced parenthesis" }; this.Add(character); continue; // Move to next character } case Characters.Star: case Characters.Plus: { //goto Label0; AddMisplacedQuantifier(charBuffer); continue; // was goto Label2; } } break; } } } Add(new Character(charBuffer)); } HandleAlternatives(charBuffer); //Label0: // AddMisplacedQuantifier(charBuffer); // goto Label2; //Label1: // AddSpecialCharacter(charBuffer); // goto Label2; }