private PathRegexElement ParseItemSequence(ref int pos, bool startsWithItem) { // Syntax: { element } int startPos = pos; var list = new List <PathRegexElement>(); for (;;) { string peekSym = PeekSymbol(pos, eofOk: true); if (Matches(peekSym, "", ")", "|")) { break; } else { PathRegexElement element = ParseItemElement(ref pos, startsWithItem); list.Add(element); startsWithItem = !element.EndsWithItem; } } switch (list.Count) { case 0: return(new Sequence(startsWithItem, !startsWithItem, startPos, list)); case 1: return(list.Single()); default: return(new Sequence(startsWithItem, list.Last().EndsWithItem, startPos, list)); } }
private PathRegexElement ParseItemAlternatives(ref int pos, bool startsWithItem) { // Syntax: sequence { '|' sequence } int startPos = pos; PathRegexElement first = ParseItemSequence(ref pos, startsWithItem); var elements = new List <PathRegexElement> { first }; while (Matches(PeekSymbol(pos, eofOk: true), "|")) { AdvanceSymbolPos(ref pos); elements.Add(ParseItemSequence(ref pos, startsWithItem)); } bool endsWithItem = first.EndsWithItem; foreach (var e in elements) { if (e.EndsWithItem != endsWithItem) { throw new RegexSyntaxException(_definition, e.TextPos, "Element in Regex does not end with " + ItemOrDependency(endsWithItem) + " like others"); } } return(elements.Count > 1 ? new Alternatives(startsWithItem: startsWithItem, endsWithItem: endsWithItem, textPos: startPos, elements: elements) : first); }
protected PathRegex([NotNull] string definition, [NotNull] Dictionary <string, TItemMatch> definedItemMatches, [NotNull] Dictionary <string, TDependencyMatch> definedDependencyMatches, bool ignoreCase) { _definedItemMatches = definedItemMatches; _definedDependencyMatches = definedDependencyMatches; _ignoreCase = ignoreCase; int pos = 0; _definition = definition; PathRegexElement regex = ParseItemAlternatives(ref pos, startsWithItem: true); _graph = regex.CreateGraphken(); _graph.EndNode.IsEnd = true; }
private PathRegexElement ParseItemElement(ref int pos, bool startsWithItem) { // Syntax: // /!startsWithItem/ . // | /startsWithItem/ : // | '(' alternative ')' ( ? | * | + )? // | '[' ( '^' )? NAME { NAME } ']' // | NAME int startPos = pos; string peekSym = PeekSymbol(startPos); if (Matches(peekSym, "(")) { AdvanceSymbolPos(ref pos); PathRegexElement inner = ParseItemAlternatives(ref pos, startsWithItem); peekSym = PeekSymbol(pos); if (!Matches(peekSym, ")")) { throw new RegexSyntaxException(_definition, pos, ") expected"); } AdvanceSymbolPos(ref pos); peekSym = PeekSymbol(pos, eofOk: true); if (Matches(peekSym, "?")) { AdvanceSymbolPos(ref pos); return(new Optional(startPos, inner)); } else if (Matches(peekSym, "*")) { AdvanceSymbolPos(ref pos); _containsLoops = true; return(new ZeroOrMore(startPos, inner)); } else if (Matches(peekSym, "+")) { AdvanceSymbolPos(ref pos); _containsLoops = true; return(new OneOrMore(startPos, inner)); } else { return(inner); } } else if (Matches(peekSym, "[")) { AdvanceSymbolPos(ref pos); bool invert = false; if (Matches(PeekSymbol(pos), "^")) { invert = true; AdvanceSymbolPos(ref pos); } var matches = new SortedDictionary <int, string> { { pos, PeekName(pos) } }; AdvanceSymbolPos(ref pos); while (!Matches(PeekSymbol(pos), "]")) { matches.Add(pos, PeekName(pos)); AdvanceSymbolPos(ref pos); } AdvanceSymbolPos(ref pos); bool isCount = ParseOptionalCount(ref pos); if (startsWithItem) { return(new ItemMatchAnyElement(invert, isCount, startPos, matches.Select(kvp => CreateItemMatch(kvp.Key, kvp.Value)))); } else { return(new DependencyMatchAnyElement(invert, isCount, startPos, matches.Select(kvp => CreateDependencyMatch(kvp.Key, kvp.Value)))); } } else if (Matches(peekSym, NAME_REGEX)) { AdvanceSymbolPos(ref pos); bool isCount = ParseOptionalCount(ref pos); if (startsWithItem) { return(new ItemMatchAnyElement(false, isCount, startPos, new[] { CreateItemMatch(startPos, peekSym) })); } else { return(new DependencyMatchAnyElement(false, isCount, startPos, new[] { CreateDependencyMatch(startPos, peekSym) })); } } else if (Matches(peekSym, ".")) { AdvanceSymbolPos(ref pos); if (startsWithItem) { throw new RegexSyntaxException(_definition, startPos, ". cannot be used at item position"); } bool isCount = ParseOptionalCount(ref pos); return(new DependencyMatchAnyElement(false, isCount, startPos, null)); } else if (Matches(peekSym, ":")) { AdvanceSymbolPos(ref pos); if (!startsWithItem) { throw new RegexSyntaxException(_definition, startPos, ": cannot be used at dependency position"); } bool isCount = ParseOptionalCount(ref pos); return(new ItemMatchAnyElement(false, isCount, startPos, null)); } else { throw new RegexSyntaxException(_definition, startPos, "Unexpected element - [, ( or " + (startsWithItem ? ":" : ".") + " expected"); } }
public OneOrMore(int textPos, PathRegexElement inner) : base(textPos) { Inner = inner; }
public Optional(int textPos, PathRegexElement inner) : base(textPos) { Inner = inner; }