public void FindAll_CmpRegex() { KeywordRule acsRule = new KeywordRule { Keywords = "abstract,as,base,bool,break,byte,case,catch,char,checked,class,const,continue,decimal,default,delegate,do,double,else,enum,event,explicit,extern,false,finally,fixed,float,for,foreach,goto,if,implicit,in,int,interface,internal,is,lock,long,namespace,new,null,object,operator,out,override,params,private,protected,public,readonly,ref,return,sbyte,sealed,short,sizeof,stackalloc,static,string,struct,switch,this,throw,true,try,typeof,uint,ulong,unchecked,unsafe,ushort,using,using,static,virtual,void,volatile,while,get,set,yield,var" }; RegexRule regexRule = new RegexRule { Pattern = @"\babstract\b|\bas\b|\bbase\b|\bbool\b|\bbreak\b|\bbyte\b|\bcase\b|\bcatch\b|\bchar\b|\bchecked\b|\bclass\b|\bconst\b|\bcontinue\b|\bdecimal\b|\bdefault\b|\bdelegate\b|\bdo\b|\bdouble\b|\belse\b|\benum\b|\bevent\b|\bexplicit\b|\bextern\b|\bfalse\b|\bfinally\b|\bfixed\b|\bfloat\b|\bfor\b|\bforeach\b|\bgoto\b|\bif\b|\bimplicit\b|\bin\b|\bint\b|\binterface\b|\binternal\b|\bis\b|\block\b|\blong\b|\bnamespace\b|\bnew\b|\bnull\b|\bobject\b|\boperator\b|\bout\b|\boverride\b|\bparams\b|\bprivate\b|\bprotected\b|\bpublic\b|\breadonly\b|\bref\b|\breturn\b|\bsbyte\b|\bsealed\b|\bshort\b|\bsizeof\b|\bstackalloc\b|\bstatic\b|\bstring\b|\bstruct\b|\bswitch\b|\bthis\b|\bthrow\b|\btrue\b|\btry\b|\btypeof\b|\buint\b|\bulong\b|\bunchecked\b|\bunsafe\b|\bushort\b|\busing\b|\busing\b|\bstatic\b|\bvirtual\b|\bvoid\b|\bvolatile\b|\bwhile\b|\bget\b|\bset\b|\byield\b|\bvar\b" }; string file = Path.Combine(Environment.CurrentDirectory, @"..\..\..\UI.SyntaxBox\SyntaxRenderer.cs"); var input = File.ReadAllLines(file); var regex = input .SelectMany((x) => regexRule.Match(x)) .OrderBy((x) => x.FromChar) .ThenBy((x) => x.Length) .ToList(); var acs = input .SelectMany((x) => acsRule.Match(x)) .OrderBy((x) => x.FromChar) .ThenBy((x) => x.Length) .ToList(); Assert.AreEqual(regex.Count, acs.Count, "Not the same number of matches"); Assert.IsTrue(Enumerable.SequenceEqual(regex, acs, new FormatInstructionCmp()), "Different matches"); }
public void ParseInvalidSpecificKeyword() { var t_Rule = new KeywordRule("Jmp"); var t_Expression = t_Rule.Match(CreateState(new Token(TokenType.Keyword, "Add"))); t_Expression .HasError() .Should() .BeTrue(); }
public void ParseSpecificKeyword() { var t_Rule = new KeywordRule("Jmp"); var t_Expression = t_Rule.Match(CreateState(new Token(TokenType.Keyword, "Jmp"))); ((KeywordExpression)t_Expression.Value.Expressions.First()) .Keyword .Text .Should() .Be("Jmp"); }
public void FindAll_PerformanceVsRegex() { KeywordRule acsRule = new KeywordRule { Keywords = "abstract,as,base,bool,break,byte,case,catch,char,checked,class,const,continue,decimal,default,delegate,do,double,else,enum,event,explicit,extern,false,finally,fixed,float,for,foreach,goto,if,implicit,in,int,interface,internal,is,lock,long,namespace,new,null,object,operator,out,override,params,private,protected,public,readonly,ref,return,sbyte,sealed,short,sizeof,stackalloc,static,string,struct,switch,this,throw,true,try,typeof,uint,ulong,unchecked,unsafe,ushort,using,using,static,virtual,void,volatile,while,get,set,yield,var" }; acsRule.Match("empty"); // Warm it up RegexRule regexRule = new RegexRule { Pattern = @"\babstract\b|\bas\b|\bbase\b|\bbool\b|\bbreak\b|\bbyte\b|\bcase\b|\bcatch\b|\bchar\b|\bchecked\b|\bclass\b|\bconst\b|\bcontinue\b|\bdecimal\b|\bdefault\b|\bdelegate\b|\bdo\b|\bdouble\b|\belse\b|\benum\b|\bevent\b|\bexplicit\b|\bextern\b|\bfalse\b|\bfinally\b|\bfixed\b|\bfloat\b|\bfor\b|\bforeach\b|\bgoto\b|\bif\b|\bimplicit\b|\bin\b|\bint\b|\binterface\b|\binternal\b|\bis\b|\block\b|\blong\b|\bnamespace\b|\bnew\b|\bnull\b|\bobject\b|\boperator\b|\bout\b|\boverride\b|\bparams\b|\bprivate\b|\bprotected\b|\bpublic\b|\breadonly\b|\bref\b|\breturn\b|\bsbyte\b|\bsealed\b|\bshort\b|\bsizeof\b|\bstackalloc\b|\bstatic\b|\bstring\b|\bstruct\b|\bswitch\b|\bthis\b|\bthrow\b|\btrue\b|\btry\b|\btypeof\b|\buint\b|\bulong\b|\bunchecked\b|\bunsafe\b|\bushort\b|\busing\b|\busing\b|\bstatic\b|\bvirtual\b|\bvoid\b|\bvolatile\b|\bwhile\b|\bget\b|\bset\b|\byield\b|\bvar\b" }; regexRule.Match("empty"); // Warm it up int iter = 10; string file = Path.Combine(Environment.CurrentDirectory, @"..\..\..\UI.SyntaxBox\SyntaxRenderer.cs"); var input = File.ReadAllLines(file); System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); for (int i = 0; i < iter; i++) { input.SelectMany((x) => regexRule.Match(x)).ToList(); } sw.Stop(); long regex = sw.ElapsedMilliseconds; sw.Reset(); sw.Start(); for (int i = 0; i < iter; i++) { input.SelectMany((x) => acsRule.Match(x)).ToList(); } sw.Stop(); long acs = sw.ElapsedMilliseconds; Assert.Inconclusive($"Regex: {regex}ms, Acs: {acs}ms"); }
public void ParseAddKeyword() { var t_Rule = new KeywordRule(); var t_Expression = t_Rule.Match(CreateState(new Token(TokenType.Keyword, "Add"))); t_Expression .HasError() .Should() .BeFalse(); t_Expression.Value.Expressions.First() .Should() .BeOfType <KeywordExpression>(); ((KeywordExpression)t_Expression.Value.Expressions.First()) .Keyword .Text .Should() .Be("Add"); }
// 트윗수 길이 맞추는 작업은 나중에하기 private static string ToFormat(string format, SongInfo info, bool checkFormat = false, KeywordRule rule = KeywordRule.All, int fitSize = 0) { var current = new StringBuilder(); var stack = new Stack <StringBuilder>(); string str; char c; bool b; int i = 0; while (i < format.Length) { // { 부터 } 까지다 c = format[i++]; switch (c) { case '{': { stack.Push(current); current = new StringBuilder(); } break; case '}': { str = current.ToString(); if (checkFormat) { b = str.IndexOf("/Title/", StringComparison.CurrentCultureIgnoreCase) >= 0 || str.IndexOf("/Artist/", StringComparison.CurrentCultureIgnoreCase) >= 0 || str.IndexOf("/Album/", StringComparison.CurrentCultureIgnoreCase) >= 0 || // str.IndexOf("/Client/", StringComparison.CurrentCultureIgnoreCase) >= 0 || str.IndexOf("/Via/", StringComparison.CurrentCultureIgnoreCase) >= 0 || // str.IndexOf("/Track/", StringComparison.CurrentCultureIgnoreCase) >= 0 || str.IndexOf("/TTrack/", StringComparison.CurrentCultureIgnoreCase) >= 0 || str.IndexOf("/Disc/", StringComparison.CurrentCultureIgnoreCase) >= 0 || str.IndexOf("/TDisc/", StringComparison.CurrentCultureIgnoreCase) >= 0 || str.IndexOf("/Year/", StringComparison.CurrentCultureIgnoreCase) >= 0 || str.IndexOf("/Genre/", StringComparison.CurrentCultureIgnoreCase) >= 0; if (b) { current = stack.Pop(); current.Append(str); } else { // { } 안에는 최소한 하나가 있어야함 throw new Exception(); } } else { b = false; // b -> { } 안에 포멧 변환된게 있음 str = Replace(str, "/Client/", info.Rule.Client, ref b); str = Replace(str, "/Via/", SongInfo.Via, ref b); if ((rule & KeywordRule.TitleFit) == KeywordRule.TitleFit) { str = Replace(str, "/Title/", info.Title, fitSize, true, ref b); } if ((rule & KeywordRule.ArtistFit) == KeywordRule.ArtistFit) { str = Replace(str, "/Artist/", info.Artist, fitSize, false, ref b); } str = Replace(str, "/Title/", ((rule & KeywordRule.Title) == KeywordRule.Title) ? info.Title : null, ref b); str = Replace(str, "/Artist/", ((rule & KeywordRule.Artist) == KeywordRule.Artist) ? info.Artist : null, ref b); str = Replace(str, "/Album/", ((rule & KeywordRule.Album) == KeywordRule.Album) ? info.Album : null, ref b); // 추가 태그 if ((rule & KeywordRule.Extension) == KeywordRule.Extension) { str = Replace(str, "/Track/", info.Track > 0 ? info.Track.ToString() : null, ref b); str = Replace(str, "/TTrack/", info.TTrack > 0 ? info.TTrack.ToString() : null, ref b); str = Replace(str, "/Disc/", info.Disc > 0 ? info.Disc.ToString() : null, ref b); str = Replace(str, "/TDisc/", info.TDisc > 0 ? info.TDisc.ToString() : null, ref b); str = Replace(str, "/Year/", info.Year > 0 ? info.Year.ToString() : null, ref b); str = Replace(str, "/Genre/", info.Genre, ref b); } else { str = ReplaceWithComparison(str, "/Track", null); str = ReplaceWithComparison(str, "/TTrack", null); str = ReplaceWithComparison(str, "/Disc", null); str = ReplaceWithComparison(str, "/TDisc", null); str = ReplaceWithComparison(str, "/Year", null); str = ReplaceWithComparison(str, "/Genre", null); } current = stack.Pop(); if (b) { current.Append(str); } } } break; case '\\': { if (i < format.Length) { switch (format[i]) { case '{': case '}': c = format[i]; i++; break; case 'n': c = '\n'; i++; break; case '\\': c = '\\'; i++; break; } } current.Append(c); } break; default: current.Append(c); break; } } if (checkFormat && stack.Count > 0) { throw new Exception(); } return(!checkFormat?current.ToString() : null); }